• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 
16 #include <fcntl.h>
17 #include <unistd.h>
18 
19 #include "beget_ext.h"
20 #include "control_fd.h"
21 #include "init_utils.h"
22 #include "securec.h"
23 
24 static CmdService g_cmdService;
25 
26 CallbackControlFdProcess g_controlFdFunc = NULL;
27 
OnClose(const TaskHandle task)28 static void OnClose(const TaskHandle task)
29 {
30     CmdTask *agent = (CmdTask *)LE_GetUserData(task);
31     BEGET_ERROR_CHECK(agent != NULL, return, "[control_fd] Can not get agent");
32     OH_ListRemove(&agent->item);
33     OH_ListInit(&agent->item);
34 }
35 
CmdOnRecvMessage(const TaskHandle task,const uint8_t * buffer,uint32_t buffLen)36 CONTROL_FD_STATIC void CmdOnRecvMessage(const TaskHandle task, const uint8_t *buffer, uint32_t buffLen)
37 {
38     if (buffer == NULL) {
39         return;
40     }
41     CmdTask *agent = (CmdTask *)LE_GetUserData(task);
42     BEGET_ERROR_CHECK(agent != NULL, return, "[control_fd] Can not get agent");
43 
44     // parse msg to exec
45     CmdMessage *msg = (CmdMessage *)buffer;
46     if ((msg->type >= ACTION_MAX) || (msg->cmd[0] == '\0') || (msg->ptyName[0] == '\0')) {
47         BEGET_LOGE("[control_fd] Received msg is invaild");
48         return;
49     }
50 #ifndef STARTUP_INIT_TEST
51     agent->pid = fork();
52     if (agent->pid == 0) {
53         OpenConsole();
54         char *realPath = GetRealPath(msg->ptyName);
55         BEGET_ERROR_CHECK(realPath != NULL, return, "Failed get realpath, err=%d", errno);
56         char *strl = strstr(realPath, "/dev/pts");
57         BEGET_ERROR_CHECK(strl != NULL, return, "pty slave path %s is invaild", realPath);
58         int fd = open(realPath, O_RDWR);
59         free(realPath);
60         BEGET_ERROR_CHECK(fd >= 0, return, "Failed open %s, err=%d", msg->ptyName, errno);
61         (void)dup2(fd, STDIN_FILENO);
62         (void)dup2(fd, STDOUT_FILENO);
63         (void)dup2(fd, STDERR_FILENO); // Redirect fd to 0, 1, 2
64         (void)close(fd);
65         if (g_controlFdFunc != NULL) {
66             g_controlFdFunc(msg->type, msg->cmd, NULL);
67         }
68         exit(0);
69     } else if (agent->pid < 0) {
70         BEGET_LOGE("[control_fd] Failed fork service");
71     }
72 #endif
73     return;
74 }
75 
SendMessage(LoopHandle loop,TaskHandle task,const char * message)76 CONTROL_FD_STATIC int SendMessage(LoopHandle loop, TaskHandle task, const char *message)
77 {
78     if (message == NULL) {
79         BEGET_LOGE("[control_fd] Invalid parameter");
80         return -1;
81     }
82     BufferHandle handle = NULL;
83     uint32_t bufferSize = strlen(message) + 1;
84     handle = LE_CreateBuffer(loop, bufferSize);
85     char *buff = (char *)LE_GetBufferInfo(handle, NULL, &bufferSize);
86     BEGET_ERROR_CHECK(buff != NULL, return -1, "[control_fd] Failed get buffer info");
87     int ret = memcpy_s(buff, bufferSize, message, strlen(message) + 1);
88     BEGET_ERROR_CHECK(ret == 0, LE_FreeBuffer(LE_GetDefaultLoop(), task, handle);
89         return -1, "[control_fd] Failed memcpy_s err=%d", errno);
90     LE_STATUS status = LE_Send(loop, task, handle, strlen(message) + 1);
91     BEGET_ERROR_CHECK(status == LE_SUCCESS, return -1, "[control_fd] Failed le send msg");
92     return 0;
93 }
94 
CmdOnIncommingConnect(const LoopHandle loop,const TaskHandle server)95 CONTROL_FD_STATIC int CmdOnIncommingConnect(const LoopHandle loop, const TaskHandle server)
96 {
97     TaskHandle client = NULL;
98     LE_StreamInfo info = {};
99 #ifndef STARTUP_INIT_TEST
100     info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT;
101 #else
102     info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT | TASK_TEST;
103 #endif
104     info.baseInfo.close = OnClose;
105     info.baseInfo.userDataSize = sizeof(CmdTask);
106     info.disConnectComplete = NULL;
107     info.sendMessageComplete = NULL;
108     info.recvMessage = CmdOnRecvMessage;
109     int ret = LE_AcceptStreamClient(LE_GetDefaultLoop(), server, &client, &info);
110     BEGET_ERROR_CHECK(ret == 0, return -1, "[control_fd] Failed accept stream")
111     CmdTask *agent = (CmdTask *)LE_GetUserData(client);
112     BEGET_ERROR_CHECK(agent != NULL, return -1, "[control_fd] Invalid agent");
113     agent->task = client;
114     OH_ListInit(&agent->item);
115     ret = SendMessage(LE_GetDefaultLoop(), agent->task, "connect success.");
116     BEGET_ERROR_CHECK(ret == 0, return -1, "[control_fd] Failed send msg");
117     OH_ListAddTail(&g_cmdService.head, &agent->item);
118     return 0;
119 }
120 
CmdServiceInit(const char * socketPath,CallbackControlFdProcess func)121 void CmdServiceInit(const char *socketPath, CallbackControlFdProcess func)
122 {
123     if ((socketPath == NULL) || (func == NULL)) {
124         BEGET_LOGE("[control_fd] Invalid parameter");
125         return;
126     }
127     OH_ListInit(&g_cmdService.head);
128     LE_StreamServerInfo info = {};
129     info.baseInfo.flags = TASK_STREAM | TASK_SERVER | TASK_PIPE;
130     info.server = (char *)socketPath;
131     info.socketId = -1;
132     info.baseInfo.close = NULL;
133     info.disConnectComplete = NULL;
134     info.incommingConnect = CmdOnIncommingConnect;
135     info.sendMessageComplete = NULL;
136     info.recvMessage = NULL;
137     g_controlFdFunc = func;
138     (void)LE_CreateStreamServer(LE_GetDefaultLoop(), &g_cmdService.serverTask, &info);
139 }
140 
ClientTraversalProc(ListNode * node,void * data)141 static int ClientTraversalProc(ListNode *node, void *data)
142 {
143     CmdTask *info = ListEntry(node, CmdTask, item);
144     int pid = *(int *)data;
145     return pid - info->pid;
146 }
147 
CmdServiceProcessDelClient(pid_t pid)148 void CmdServiceProcessDelClient(pid_t pid)
149 {
150     ListNode *node = OH_ListFind(&g_cmdService.head, (void *)&pid, ClientTraversalProc);
151     if (node != NULL) {
152         CmdTask *agent = ListEntry(node, CmdTask, item);
153         OH_ListRemove(&agent->item);
154         OH_ListInit(&agent->item);
155         LE_CloseTask(LE_GetDefaultLoop(), agent->task);
156     }
157 }
158