1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *      http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include "param_osadp.h"
16
17#include <pthread.h>
18#include <sys/ipc.h>
19#include <sys/mman.h>
20#include <sys/shm.h>
21
22#include "param_message.h"
23#include "param_utils.h"
24#include "securec.h"
25
26static const uint32_t RECV_BUFFER_MAX = 5 * 1024;
27
28static RecvMessage g_recvMessage;
29static void OnReceiveRequest(const TaskHandle task, const uint8_t *buffer, uint32_t nread)
30{
31    if (nread == 0 || buffer == NULL || g_recvMessage == NULL) {
32        return;
33    }
34    uint32_t curr = 0;
35    while (curr < nread) {
36        const ParamMessage *msg = (const ParamMessage *)(buffer + curr);
37        if ((nread - curr < msg->msgSize) ||
38            (nread - curr < sizeof(ParamMessage)) ||
39            (msg->msgSize < sizeof(ParamMessage))) {
40            break;
41        }
42        curr += msg->msgSize;
43        g_recvMessage(task, msg);
44    }
45}
46
47int ParamServerCreate(ParamTaskPtr *stream, const ParamStreamInfo *streamInfo)
48{
49    PARAM_CHECK(stream != NULL && streamInfo != NULL, return -1, "Invalid param");
50    PARAM_CHECK(streamInfo->incomingConnect != NULL, return -1, "Invalid incomingConnect");
51    LE_StreamServerInfo info = {};
52    info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_SERVER | TASK_PUBLIC;
53    info.server = streamInfo->server;
54    info.baseInfo.close = streamInfo->close;
55    info.incommingConnect = streamInfo->incomingConnect;
56    return LE_CreateStreamServer(LE_GetDefaultLoop(), stream, &info);
57}
58
59int ParamStreamCreate(ParamTaskPtr *stream, ParamTaskPtr server,
60    const ParamStreamInfo *streamInfo, uint16_t userDataSize)
61{
62    PARAM_CHECK(stream != NULL && streamInfo != NULL, return -1, "Invalid stream");
63    PARAM_CHECK(streamInfo->recvMessage != NULL, return -1, "Invalid recvMessage");
64    PARAM_CHECK(streamInfo->close != NULL, return -1, "Invalid close");
65    LE_StreamInfo info = {};
66    info.baseInfo.userDataSize = userDataSize;
67    info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT;
68    if (streamInfo->flags & PARAM_TEST_FLAGS) {
69        info.baseInfo.flags |= TASK_TEST;
70    }
71    info.baseInfo.close = streamInfo->close;
72    info.disConnectComplete = NULL;
73    info.sendMessageComplete = NULL;
74    info.recvMessage = OnReceiveRequest;
75    g_recvMessage = streamInfo->recvMessage;
76    LE_STATUS status = LE_AcceptStreamClient(LE_GetDefaultLoop(), server, stream, &info);
77    PARAM_CHECK(status == 0, return -1, "Failed to create client");
78    return 0;
79}
80
81void *ParamGetTaskUserData(const ParamTaskPtr stream)
82{
83    PARAM_CHECK(stream != NULL, return NULL, "Invalid stream");
84    return LE_GetUserData(stream);
85}
86
87int ParamTaskSendMsg(const ParamTaskPtr stream, const ParamMessage *msg)
88{
89    PARAM_CHECK(msg != NULL, return -1, "Invalid stream");
90    PARAM_CHECK(stream != NULL, free((void *)msg);
91        return -1, "Invalid stream");
92    uint32_t dataSize = msg->msgSize;
93    BufferHandle bufferHandle = LE_CreateBuffer(LE_GetDefaultLoop(), dataSize);
94    PARAM_CHECK(bufferHandle != NULL, return -1, "Failed to create request");
95    uint8_t *buffer = LE_GetBufferInfo(bufferHandle, NULL, NULL);
96    int ret = memcpy_s(buffer, dataSize, msg, dataSize);
97    free((void *)msg);
98    PARAM_CHECK(ret == EOK, LE_FreeBuffer(LE_GetDefaultLoop(), NULL, bufferHandle);
99        return -1, "Failed to copy message");
100    return LE_Send(LE_GetDefaultLoop(), stream, bufferHandle, dataSize);
101}
102
103int ParamEventTaskCreate(ParamTaskPtr *stream, LE_ProcessAsyncEvent eventProcess)
104{
105    PARAM_CHECK(stream != NULL && eventProcess != NULL, return -1, "Invalid info or stream");
106    return LE_CreateAsyncTask(LE_GetDefaultLoop(), stream, eventProcess);
107}
108
109int ParamEventSend(const ParamTaskPtr stream, uint64_t eventId, const char *content, uint32_t size)
110{
111    PARAM_CHECK(stream != NULL, return -1, "Invalid stream");
112    PARAM_CHECK(size <= RECV_BUFFER_MAX, return -1, "Invalid stream");
113    return LE_StartAsyncEvent(LE_GetDefaultLoop(), stream, eventId, (const uint8_t *)content, size);
114}
115
116int ParamTaskClose(const ParamTaskPtr stream)
117{
118    PARAM_CHECK(stream != NULL, return -1, "Invalid param");
119    LE_CloseTask(LE_GetDefaultLoop(), stream);
120    return 0;
121}
122
123
124int ParamTimerCreate(ParamTaskPtr *timer, ProcessTimer process, void *context)
125{
126    PARAM_CHECK(timer != NULL && process != NULL, return -1, "Invalid timer");
127    LE_STATUS status = LE_CreateTimer(LE_GetDefaultLoop(), timer, (LE_ProcessTimer)process, context);
128    return (int)status;
129}
130
131int ParamTimerStart(const ParamTaskPtr timer, uint64_t timeout, uint64_t repeat)
132{
133    PARAM_CHECK(timer != NULL, return -1, "Invalid timer");
134    return LE_StartTimer(LE_GetDefaultLoop(), timer, timeout, repeat);
135}
136
137void ParamTimerClose(ParamTaskPtr timer)
138{
139    PARAM_CHECK(timer != NULL, return, "Invalid param");
140    LE_CloseTask(LE_GetDefaultLoop(), (ParamTaskPtr)timer);
141}
142
143int ParamServiceStart(void)
144{
145    LE_RunLoop(LE_GetDefaultLoop());
146    return 0;
147}
148
149int ParamServiceStop(void)
150{
151    LE_StopLoop(LE_GetDefaultLoop());
152    return 0;
153}