1/*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include "it_test_liteipc.h"
33#include "signal.h"
34#include "sys/wait.h"
35
36#include "unistd.h"
37#include "liteipc.h"
38#include "stdlib.h"
39#include "stdio.h"
40#include "string.h"
41#include "sys/ioctl.h"
42#include "sys/time.h"
43
44#include "smgr_demo.h"
45
46ServiceName g_serviceNameMap[MAX_SREVICE_NUM];
47BOOL g_cmsRunningFlag = FALSE;
48
49static void InitCms()
50{
51    (void)memset_s(g_serviceNameMap, sizeof(g_serviceNameMap), 0, sizeof(g_serviceNameMap));
52}
53
54uint32_t SetCms(int fd)
55{
56    return ioctl(fd, IPC_SET_CMS, 200);
57}
58
59void SendReply(int fd, IpcMsg *dataIn, uint32_t result, uint32_t serviceHandle)
60{
61    IpcContent data1;
62    IpcMsg dataOut;
63    unsigned int ret;
64    uint32_t ptr[2];
65
66    data1.flag = SEND | BUFF_FREE;
67    data1.buffToFree = dataIn;
68    data1.outMsg = &dataOut;
69    (void)memset_s(data1.outMsg, sizeof(IpcMsg), 0, sizeof(IpcMsg));
70    data1.outMsg->type = MT_REPLY;
71    data1.outMsg->target.handle = dataIn->taskID;
72    data1.outMsg->target.token = dataIn->target.token;
73    data1.outMsg->code = dataIn->code;
74#if (USE_TIMESTAMP == 1)
75    data1.outMsg->timestamp = dataIn->timestamp;
76#endif
77    ptr[0] = result;
78    ptr[1] = serviceHandle;
79    data1.outMsg->dataSz = 8;
80    data1.outMsg->data = ptr;
81    ret = ioctl(fd, IPC_SEND_RECV_MSG, &data1);
82    if (ret) {
83        printf("SendReply failed\n");
84    }
85}
86
87void FreeBuffer(int fd, IpcMsg *dataIn)
88{
89    IpcContent data1;
90    unsigned int ret;
91    data1.flag = BUFF_FREE;
92    data1.buffToFree = dataIn;
93    ret = ioctl(fd, IPC_SEND_RECV_MSG, &data1);
94    if (ret) {
95        printf("FreeBuffer failed\n");
96    }
97}
98
99static uint32_t SendCmsCmd(int fd, CmsCmdContent *content)
100{
101    unsigned int ret;
102    ret = ioctl(fd, IPC_CMS_CMD, content);
103    if (ret) {
104        printf("SendCmsCmd failed\n");
105    }
106    return ret;
107}
108
109uint32_t RegService(int fd, char *serviceName, uint32_t nameLen, uint32_t *serviceHandle)
110{
111    IpcContent data1;
112    IpcMsg dataIn;
113    IpcMsg dataOut;
114    uint32_t ret;
115    uint32_t *ptr = nullptr;
116    ServiceName name;
117
118    if (nameLen > NAME_LEN_MAX) {
119        return -1;
120    }
121    (void)memcpy_s(name.serviceName, nameLen, serviceName, nameLen);
122    name.nameLen = nameLen;
123
124    data1.flag = SEND | RECV;
125    data1.outMsg = &dataOut;
126    (void)memset_s(data1.outMsg, sizeof(IpcMsg), 0, sizeof(IpcMsg));
127    data1.outMsg->type = MT_REQUEST;
128    data1.outMsg->target.handle = 0;
129    data1.outMsg->code = REG_CODE;
130    data1.outMsg->dataSz = sizeof(ServiceName);
131    data1.outMsg->data = &name;
132
133    ret = ioctl(fd, IPC_SEND_RECV_MSG, &data1);
134    if (ret != 0) {
135        printf("RegService failed\n");
136        return ret;
137    }
138    ptr = (uint32_t*)(data1.inMsg->data);
139    *serviceHandle = ptr[1];
140    FreeBuffer(fd, data1.inMsg);
141    return ptr[0];
142}
143
144uint32_t GetService(int fd, char *serviceName, uint32_t nameLen, uint32_t *serviceHandle)
145{
146    IpcContent data1;
147    IpcMsg dataIn;
148    IpcMsg dataOut;
149    uint32_t ret;
150    uint32_t *ptr = nullptr;
151    ServiceName name;
152
153    if (nameLen > NAME_LEN_MAX) {
154        return -1;
155    }
156    (void)memcpy_s(name.serviceName, nameLen, serviceName, nameLen);
157    name.nameLen = nameLen;
158
159    data1.flag = SEND | RECV;
160    data1.outMsg = &dataOut;
161    (void)memset_s(data1.outMsg, sizeof(IpcMsg), 0, sizeof(IpcMsg));
162    data1.outMsg->type = MT_REQUEST;
163    data1.outMsg->target.handle = 0;
164    data1.outMsg->code = GET_CODE;
165    data1.outMsg->dataSz = sizeof(ServiceName);
166    data1.outMsg->data = &name;
167
168    ret = ioctl(fd, IPC_SEND_RECV_MSG, &data1);
169    if (ret != 0) {
170        return ret;
171    }
172    ptr = (uint32_t*)(data1.inMsg->data);
173    *serviceHandle = ptr[1];
174    FreeBuffer(fd, data1.inMsg);
175    return ptr[0];
176}
177
178static void HandleServiceRegAndGet(int fd, IpcMsg *data)
179{
180    uint32_t ret, i;
181
182    if (data->code == STOP_CODE) {
183        g_cmsRunningFlag = FALSE;
184        return;
185    }
186
187    ServiceName *info = (ServiceName*)(data->data);
188    CmsCmdContent content;
189    if ((info->nameLen == 0) || (info->serviceName == NULL)) {
190        goto ERROR_EXIT;
191    }
192    for (i = 0; i < MAX_SREVICE_NUM; i++) {
193        if (g_serviceNameMap[i].serviceName != NULL && g_serviceNameMap[i].nameLen == info->nameLen) {
194            if(memcmp(g_serviceNameMap[i].serviceName, info->serviceName, info->nameLen) == 0) {
195                break;
196            }
197        }
198    }
199    printf("receive service request, code:%d, service name:%s\n", data->code, info->serviceName);
200    switch (data->code) {
201        case REG_CODE:
202            if (i == MAX_SREVICE_NUM) {
203                content.cmd = CMS_GEN_HANDLE;
204                content.taskID = data->taskID;
205                ret = SendCmsCmd(fd, &content);
206                if (ret) {
207                    goto ERROR_EXIT;
208                }
209                if (g_serviceNameMap[content.serviceHandle].serviceName != NULL && g_serviceNameMap[content.serviceHandle].nameLen == info->nameLen) {
210                    printf("the task has already a service named:%s\n", g_serviceNameMap[content.serviceHandle].serviceName);
211                    goto ERROR_REG;
212                } else {
213                    (void)memcpy_s(g_serviceNameMap[content.serviceHandle].serviceName, info->nameLen,
214                                   info->serviceName, info->nameLen);
215                    g_serviceNameMap[content.serviceHandle].nameLen = info->nameLen;
216                    SendReply(fd, data, 0, content.serviceHandle);
217                }
218            }else {
219                printf("this service already registered\n");
220                goto ERROR_EXIT;
221            }
222            break;
223        case GET_CODE:
224            if (i == MAX_SREVICE_NUM) {
225                goto ERROR_EXIT;
226            }else {
227                content.cmd = CMS_ADD_ACCESS;
228                content.taskID = data->taskID;
229                content.serviceHandle = i;
230                SendCmsCmd(fd, &content);
231                SendReply(fd, data, 0, i);
232            }
233            break;
234        default:
235            break;
236    }
237    return;
238ERROR_REG:
239    content.cmd = CMS_REMOVE_HANDLE;
240    SendCmsCmd(fd, &content);
241ERROR_EXIT:
242    SendReply(fd, data, -1, 0);
243}
244
245static uint32_t CmsLoop(int fd)
246{
247    IpcContent data1;
248    IpcMsg dataIn;
249    IpcMsg dataOut;
250    uint32_t ret;
251    g_cmsRunningFlag = TRUE;
252    while (g_cmsRunningFlag == TRUE) {
253        data1.flag = RECV;
254        ret = ioctl(fd, IPC_SEND_RECV_MSG, &data1);
255        if (ret != 0) {
256            printf("bad request!\n");
257            continue;
258        }
259        switch (data1.inMsg->type) {
260            case MT_REQUEST:
261                HandleServiceRegAndGet(fd, data1.inMsg);
262                break;
263            default:
264                printf("request not support:%d!\n", data1.inMsg->type);
265                FreeBuffer(fd, data1.inMsg);
266                break;
267        }
268    }
269}
270
271void StartCms(int fd)
272{
273    InitCms();
274    CmsLoop(fd);
275}
276
277void StopCms(int fd)
278{
279    IpcContent data1;
280    IpcMsg dataOut;
281    int ret;
282
283    data1.flag = SEND;
284    data1.outMsg = &dataOut;
285    (void)memset_s(data1.outMsg, sizeof(IpcMsg), 0, sizeof(IpcMsg));
286    data1.outMsg->type = MT_REQUEST;
287    data1.outMsg->target.handle = 0;
288    data1.outMsg->code = STOP_CODE;
289    data1.outMsg->dataSz = 0;
290    data1.outMsg->data = 0;
291
292    ret = ioctl(fd, IPC_SEND_RECV_MSG, &data1);
293    if (ret != 0) {
294        printf("StopCms failed ioctl ret:%d!\n", ret);
295    }
296}
297
298