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 25 26
#ifdef PARAM_BASE_LOG
#include "init_log.h"
#endif
M
Mupceet 已提交
27
#include "init_utils.h"
A
an_xinwei 已提交
28
#include "param_base.h"
M
Mupceet 已提交
29 30 31 32 33 34 35
#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 已提交
36
static int g_clientFd = INVALID_SOCKET;
M
Mupceet 已提交
37
static pthread_mutex_t g_clientMutex = PTHREAD_MUTEX_INITIALIZER;
M
Mupceet 已提交
38

M
Mupceet 已提交
39
__attribute__((constructor)) static void ParameterInit(void)
M
Mupceet 已提交
40
{
M
Mupceet 已提交
41 42
    if (getpid() == 1) {
        return;
M
Mupceet 已提交
43
    }
C
cheng_jinsong 已提交
44
    EnableInitLog(INIT_ERROR);
A
an_xinwei 已提交
45 46 47 48 49 50 51 52 53
    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 已提交
54 55
}

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

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 已提交
86
static int ReadMessage(int fd, char *buffer, uint32_t timeout)
M
Mupceet 已提交
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
{
    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 已提交
105
            usleep(10*1000); // 10*1000 wait 10ms
M
Mupceet 已提交
106 107 108
            continue;
        }
    } while (1);
M
Mupceet 已提交
109
    if (ret != 0) {
M
Mupceet 已提交
110
        PARAM_LOGE("ReadMessage errno %d diff %u timeout %d ret %d", errno, diff, timeout, ret);
M
Mupceet 已提交
111
    }
M
Mupceet 已提交
112 113 114
    return ret;
}

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

M
Mupceet 已提交
133 134
static int StartRequest(int clientFd, ParamMessage *request, int timeout)
{
M
Mupceet 已提交
135
    ssize_t sendLen = send(clientFd, (char *)request, request->msgSize, 0);
C
cheng_jinsong 已提交
136 137 138 139
    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 已提交
140
    PARAM_LOGV("sendMessage sendLen fd %d %zd", clientFd, sendLen);
C
codex  
chengjinsong 已提交
141
    int ret = ReadMessage(clientFd, (char *)request, timeout);
M
Mupceet 已提交
142 143 144 145 146 147 148 149 150
    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 已提交
151 152 153 154
    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 已提交
155 156 157 158 159 160 161 162 163 164 165 166 167

    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 已提交
168
    PARAM_LOGI("SystemSetParameter name %s msgid:%d ", name, request->id.msgId);
M
Mupceet 已提交
169
    pthread_mutex_lock(&g_clientMutex);
C
cheng_jinsong 已提交
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
    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) {
            ret = PARAM_CODE_INVALID_PARAM;
            break;
        }
        ret = StartRequest(g_clientFd, request, DEFAULT_PARAM_SET_TIMEOUT);
        if (ret == PARAM_CODE_INVALID_SOCKET) {
            close(g_clientFd);
            g_clientFd = INVALID_SOCKET;
            retryCount++;
            ret = 0;
        } else {
            break;
        }
M
Mupceet 已提交
188 189
    }
    PARAM_LOGI("SystemSetParameter name %s msgid:%d  ret: %d ", name, request->id.msgId, ret);
M
Mupceet 已提交
190
    pthread_mutex_unlock(&g_clientMutex);
M
Mupceet 已提交
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 232
    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 已提交
233 234 235 236
#ifdef STARTUP_INIT_TEST
    timeout = 1;
#endif
    int fd = GetClientSocket(timeout);
L
laiguizhong 已提交
237
    PARAM_CHECK(fd >= 0, return -1, "Failed to connect server for wait %s", name);
M
Mupceet 已提交
238 239
    ret = StartRequest(fd, request, timeout);
    close(fd);
M
Mupceet 已提交
240 241 242 243 244
    free(request);
    PARAM_LOGI("SystemWaitParameter %s value %s result %d ", name, value, ret);
    return ret;
}

M
Mupceet 已提交
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
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 已提交
260 261 262 263 264 265 266 267 268 269 270 271
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;
}