param_request.c 9.7 KB
Newer Older
M
Mupceet 已提交
1
/*
M
Mupceet 已提交
2
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
M
Mupceet 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "init_param.h"

#include <errno.h>
#include <stdatomic.h>
#include <stddef.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>

A
an_xinwei 已提交
24
#include "init_log.h"
M
Mupceet 已提交
25
#include "init_utils.h"
A
an_xinwei 已提交
26
#include "param_base.h"
M
Mupceet 已提交
27 28 29 30 31 32 33
#include "param_manager.h"
#include "param_message.h"
#include "param_security.h"

#define INVALID_SOCKET (-1)
static const uint32_t RECV_BUFFER_MAX = 5 * 1024;
static atomic_uint g_requestId = ATOMIC_VAR_INIT(1);
M
Mupceet 已提交
34
static int g_clientFd = INVALID_SOCKET;
M
Mupceet 已提交
35
static pthread_mutex_t g_clientMutex = PTHREAD_MUTEX_INITIALIZER;
M
Mupceet 已提交
36

M
Mupceet 已提交
37
__attribute__((constructor)) static void ParameterInit(void)
M
Mupceet 已提交
38
{
M
Mupceet 已提交
39 40
    if (getpid() == 1) {
        return;
M
Mupceet 已提交
41
    }
42
    EnableInitLog(INIT_INFO);
A
an_xinwei 已提交
43 44 45 46 47 48 49 50 51
    PARAM_WORKSPACE_OPS ops = {0};
    ops.updaterMode = 0;
#ifdef PARAM_BASE_LOG
    ops.logFunc = InitLog;
#endif
#ifdef PARAM_SUPPORT_SELINUX
    ops.setfilecon = NULL;
#endif
    InitParamWorkSpace(1, &ops);
M
Mupceet 已提交
52 53
}

M
Mupceet 已提交
54
__attribute__((destructor)) static void ParameterDeinit(void)
M
Mupceet 已提交
55
{
M
Mupceet 已提交
56 57 58
    if (g_clientFd != INVALID_SOCKET) {
        close(g_clientFd);
        g_clientFd = INVALID_SOCKET;
M
Mupceet 已提交
59
    }
M
Mupceet 已提交
60
    pthread_mutex_destroy(&g_clientMutex);
M
Mupceet 已提交
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
}

static int ProcessRecvMsg(const ParamMessage *recvMsg)
{
    PARAM_LOGV("ProcessRecvMsg type: %u msgId: %u name %s", recvMsg->type, recvMsg->id.msgId, recvMsg->key);
    int result = PARAM_CODE_INVALID_PARAM;
    switch (recvMsg->type) {
        case MSG_SET_PARAM:
            result = ((ParamResponseMessage *)recvMsg)->result;
            break;
        case MSG_NOTIFY_PARAM: {
            uint32_t offset = 0;
            ParamMsgContent *valueContent = GetNextContent(recvMsg, &offset);
            PARAM_CHECK(valueContent != NULL, return PARAM_CODE_TIMEOUT, "Invalid msg");
            result = 0;
            break;
        }
        default:
            break;
    }
    return result;
}

M
Mupceet 已提交
84
static int ReadMessage(int fd, char *buffer, uint32_t timeout)
M
Mupceet 已提交
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
{
    int ret = 0;
    uint32_t diff = 0;
    time_t startTime;
    (void)time(&startTime);
    do {
        ssize_t recvLen = recv(fd, (char *)buffer, RECV_BUFFER_MAX, 0);
        if (recvLen > 0) {
            break;
        }
        time_t finishTime;
        (void)time(&finishTime);
        diff = (uint32_t)difftime(finishTime, startTime);
        if (diff >= timeout) {
            ret = PARAM_CODE_TIMEOUT;
            break;
        }
        if (errno == EAGAIN || errno == EINTR) {
M
Mupceet 已提交
103
            usleep(10*1000); // 10*1000 wait 10ms
M
Mupceet 已提交
104 105 106
            continue;
        }
    } while (1);
M
Mupceet 已提交
107
    if (ret != 0) {
M
Mupceet 已提交
108
        PARAM_LOGE("ReadMessage errno %d diff %u timeout %d ret %d", errno, diff, timeout, ret);
M
Mupceet 已提交
109
    }
M
Mupceet 已提交
110 111 112
    return ret;
}

M
Mupceet 已提交
113
static int GetClientSocket(int timeout)
M
Mupceet 已提交
114 115 116 117
{
    struct timeval time;
    time.tv_sec = timeout;
    time.tv_usec = 0;
C
cheng_jinsong 已提交
118
    int clientFd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
M
Mupceet 已提交
119
    PARAM_CHECK(clientFd >= 0, return -1, "Failed to create socket");
L
laiguizhong 已提交
120
    int ret = ConnectServer(clientFd, CLIENT_PIPE_NAME);
M
Mupceet 已提交
121
    if (ret == 0) {
M
Mupceet 已提交
122 123
        setsockopt(clientFd, SOL_SOCKET, SO_SNDTIMEO, (char *)&time, sizeof(struct timeval));
        setsockopt(clientFd, SOL_SOCKET, SO_RCVTIMEO, (char *)&time, sizeof(struct timeval));
M
Mupceet 已提交
124 125 126
    } else {
        close(clientFd);
        clientFd = INVALID_SOCKET;
M
Mupceet 已提交
127
    }
M
Mupceet 已提交
128 129
    return clientFd;
}
M
Mupceet 已提交
130

M
Mupceet 已提交
131 132
static int StartRequest(int clientFd, ParamMessage *request, int timeout)
{
C
chengjinsong2 已提交
133
    errno = 0;
M
Mupceet 已提交
134
    ssize_t sendLen = send(clientFd, (char *)request, request->msgSize, 0);
C
cheng_jinsong 已提交
135 136 137 138
    if (errno == EINVAL || errno == EACCES) {
        return PARAM_CODE_INVALID_SOCKET;
    }
    PARAM_CHECK(sendLen >= 0, return PARAM_CODE_FAIL_CONNECT, "Failed to send message err: %d", errno);
M
Mupceet 已提交
139
    PARAM_LOGV("sendMessage sendLen fd %d %zd", clientFd, sendLen);
C
codex  
chengjinsong 已提交
140
    int ret = ReadMessage(clientFd, (char *)request, timeout);
M
Mupceet 已提交
141 142 143 144 145 146 147 148 149
    if (ret == 0) {
        ret = ProcessRecvMsg(request);
    }
    return ret;
}

int SystemSetParameter(const char *name, const char *value)
{
    PARAM_CHECK(name != NULL && value != NULL, return -1, "Invalid name or value");
M
Mupceet 已提交
150 151 152 153
    int ret = CheckParamName(name, 0);
    PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", name);
    ret = CheckParamValue(NULL, name, value, GetParamValueType(name));
    PARAM_CHECK(ret == 0, return ret, "Illegal param value %s", value);
M
Mupceet 已提交
154 155 156 157 158 159 160 161 162 163 164 165 166

    size_t msgSize = sizeof(ParamMsgContent);
    msgSize = (msgSize < RECV_BUFFER_MAX) ? RECV_BUFFER_MAX : msgSize;

    ParamMessage *request = (ParamMessage *)CreateParamMessage(MSG_SET_PARAM, name, msgSize);
    PARAM_CHECK(request != NULL, return -1, "Failed to malloc for connect");
    uint32_t offset = 0;
    ret = FillParamMsgContent(request, &offset, PARAM_VALUE, value, strlen(value));
    PARAM_CHECK(ret == 0, free(request);
        return -1, "Failed to fill value");
    request->msgSize = offset + sizeof(ParamMessage);
    request->id.msgId = atomic_fetch_add(&g_requestId, 1);

M
Mupceet 已提交
167
    PARAM_LOGI("SystemSetParameter name %s msgid:%d ", name, request->id.msgId);
M
Mupceet 已提交
168
    pthread_mutex_lock(&g_clientMutex);
C
cheng_jinsong 已提交
169 170 171 172 173 174
    int retryCount = 0;
    while (retryCount < 2) { // max retry 2
        if (g_clientFd == INVALID_SOCKET) {
            g_clientFd = GetClientSocket(DEFAULT_PARAM_SET_TIMEOUT);
        }
        if (g_clientFd < 0) {
C
chengjinsong2 已提交
175
            ret = DAC_RESULT_FORBIDED;
C
cheng_jinsong 已提交
176 177 178 179 180 181 182
            break;
        }
        ret = StartRequest(g_clientFd, request, DEFAULT_PARAM_SET_TIMEOUT);
        if (ret == PARAM_CODE_INVALID_SOCKET) {
            close(g_clientFd);
            g_clientFd = INVALID_SOCKET;
            retryCount++;
C
chengjinsong2 已提交
183
            ret = DAC_RESULT_FORBIDED;
C
cheng_jinsong 已提交
184 185 186
        } else {
            break;
        }
M
Mupceet 已提交
187 188
    }
    PARAM_LOGI("SystemSetParameter name %s msgid:%d  ret: %d ", name, request->id.msgId, ret);
M
Mupceet 已提交
189
    pthread_mutex_unlock(&g_clientMutex);
M
Mupceet 已提交
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
    free(request);
    return ret;
}

int SystemWaitParameter(const char *name, const char *value, int32_t timeout)
{
    PARAM_CHECK(name != NULL, return -1, "Invalid name");
    int ret = CheckParamName(name, 0);
    PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", name);
    ParamHandle handle = 0;
    ret = ReadParamWithCheck(name, DAC_READ, &handle);
    if (ret != PARAM_CODE_NOT_FOUND && ret != 0 && ret != PARAM_CODE_NODE_EXIST) {
        PARAM_CHECK(ret == 0, return ret, "Forbid to wait parameter %s", name);
    }
    if (timeout <= 0) {
        timeout = DEFAULT_PARAM_WAIT_TIMEOUT;
    }
    uint32_t msgSize = sizeof(ParamMessage) + sizeof(ParamMsgContent) + sizeof(ParamMsgContent) + sizeof(uint32_t);
    msgSize = (msgSize < RECV_BUFFER_MAX) ? RECV_BUFFER_MAX : msgSize;
    uint32_t offset = 0;
    ParamMessage *request = NULL;
    if (value != NULL && strlen(value) > 0) {
        msgSize += PARAM_ALIGN(strlen(value) + 1);
        request = (ParamMessage *)CreateParamMessage(MSG_WAIT_PARAM, name, msgSize);
        PARAM_CHECK(request != NULL, return -1, "Failed to malloc for wait");
        ret = FillParamMsgContent(request, &offset, PARAM_VALUE, value, strlen(value));
    } else {
        msgSize += PARAM_ALIGN(1);
        request = (ParamMessage *)CreateParamMessage(MSG_WAIT_PARAM, name, msgSize);
        PARAM_CHECK(request != NULL, return -1, "Failed to malloc for wait");
        ret = FillParamMsgContent(request, &offset, PARAM_VALUE, "*", 1);
    }
    PARAM_CHECK(ret == 0, free(request);
        return -1, "Failed to fill value");
    ParamMsgContent *content = (ParamMsgContent *)(request->data + offset);
    content->type = PARAM_WAIT_TIMEOUT;
    content->contentSize = sizeof(uint32_t);
    *((uint32_t *)(content->content)) = timeout;
    offset += sizeof(ParamMsgContent) + sizeof(uint32_t);

    request->msgSize = offset + sizeof(ParamMessage);
    request->id.waitId = atomic_fetch_add(&g_requestId, 1);
M
Mupceet 已提交
232 233 234 235
#ifdef STARTUP_INIT_TEST
    timeout = 1;
#endif
    int fd = GetClientSocket(timeout);
L
laiguizhong 已提交
236
    PARAM_CHECK(fd >= 0, return -1, "Failed to connect server for wait %s", name);
M
Mupceet 已提交
237 238
    ret = StartRequest(fd, request, timeout);
    close(fd);
M
Mupceet 已提交
239 240 241 242 243
    free(request);
    PARAM_LOGI("SystemWaitParameter %s value %s result %d ", name, value, ret);
    return ret;
}

M
Mupceet 已提交
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
int SystemCheckParamExist(const char *name)
{
    return SysCheckParamExist(name);
}

int SystemFindParameter(const char *name, ParamHandle *handle)
{
    PARAM_CHECK(name != NULL && handle != NULL, return -1, "The name or handle is null");
    int ret = ReadParamWithCheck(name, DAC_READ, handle);
    if (ret != PARAM_CODE_NOT_FOUND && ret != 0 && ret != PARAM_CODE_NODE_EXIST) {
        PARAM_CHECK(ret == 0, return ret, "Forbid to access parameter %s", name);
    }
    return ret;
}

M
Mupceet 已提交
259 260 261 262 263 264 265 266 267 268 269 270
int WatchParamCheck(const char *keyprefix)
{
    PARAM_CHECK(keyprefix != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid keyprefix");
    int ret = CheckParamName(keyprefix, 0);
    PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", keyprefix);
    ParamHandle handle = 0;
    ret = ReadParamWithCheck(keyprefix, DAC_WATCH, &handle);
    if (ret != PARAM_CODE_NOT_FOUND && ret != 0 && ret != PARAM_CODE_NODE_EXIST) {
        PARAM_CHECK(ret == 0, return ret, "Forbid to watch parameter %s", keyprefix);
    }
    return 0;
}