1 /*
2 * This file is part of the openHiTLS project.
3 *
4 * openHiTLS is licensed under the Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 *
8 * http://license.coscl.org.cn/MulanPSL2
9 *
10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13 * See the Mulan PSL v2 for more details.
14 */
15
16 #include <stdio.h>
17 #include <stdint.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <sys/time.h>
21 #include <sys/syscall.h>
22 #include <libgen.h>
23 #include "lock.h"
24 #include "hlt.h"
25 #include "logger.h"
26 #include "tls_res.h"
27 #include "channel_res.h"
28 #include "control_channel.h"
29 #include "rpc_func.h"
30 #include "hitls.h"
31 #include "hitls_config.h"
32 #include "process.h"
33
34 #define SUCCESS 0
35 #define ERROR (-1)
36 #define CMD_MAX_LEN (512)
37 #define DOMAIN_PATH_LEN (128)
38 #define START_PROCESS_CMD "./process %d ./%s_%d ./%s %d > ./%s_%d.log &"
39
40 #define ASSERT_RETURN(condition, log) \
41 do { \
42 if (!(condition)) { \
43 LOG_ERROR(log); \
44 return ERROR; \
45 } \
46 } while (0)
47
48 typedef struct ProcessRes {
49 Process *process;
50 struct ProcessRes *next;
51 } ProcessRes;
52
53 typedef struct ProcessList {
54 ProcessRes *processRes;
55 uint8_t num;
56 } ProcessList;
57
58 static ProcessList g_processList;
59 static Process *g_process = NULL;
60 static int g_processIndex = 0;
61
62 // Initialization process linked list, which is used only in the Local Process process and is used to save the Remote
63 // Process.
InitProcessList(void)64 int InitProcessList(void)
65 {
66 g_processList.processRes = (ProcessRes*)malloc(sizeof(ProcessRes));
67 ASSERT_RETURN(g_processList.processRes != NULL, "Malloc ProcessRes Error");
68 memset_s(g_processList.processRes, sizeof(ProcessRes), 0, sizeof(ProcessRes));
69 g_processList.num = 0;
70 return SUCCESS;
71 }
72
73 // Inserts a process to a linked list. Currently, only remote processes are stored.
InsertProcessToList(Process * tmpProcess)74 int InsertProcessToList(Process *tmpProcess)
75 {
76 ProcessRes *frontProcessRes = g_processList.processRes;
77 ProcessRes *nextProcessRes = NULL;
78 ProcessRes *tmpProcessRes;
79 ASSERT_RETURN(tmpProcess != NULL, "TmpProcess is NULL");
80 // Find the last process resource. The obtained frontProcessRes is the last process resource.
81 nextProcessRes = frontProcessRes->next;
82 while (nextProcessRes != NULL) {
83 frontProcessRes = nextProcessRes;
84 nextProcessRes = frontProcessRes->next;
85 }
86 // Applying for Process Resources
87 tmpProcessRes = (ProcessRes*)malloc(sizeof(ProcessRes));
88 ASSERT_RETURN(tmpProcessRes != NULL, "Malloc ProcessRes Error");
89 tmpProcessRes->process = tmpProcess;
90 tmpProcessRes->next = NULL;
91 frontProcessRes->next = tmpProcessRes;
92 g_processList.num++;
93 return SUCCESS;
94 }
95
GetProcessFromList(void)96 Process *GetProcessFromList(void)
97 {
98 ProcessRes *headProcessRes = g_processList.processRes;
99 ProcessRes *firstProcessRes, *nextProcessRes;
100 Process* resultProcess;
101
102 if (g_processList.num == 0) {
103 return NULL;
104 }
105
106 // Find the last element
107 firstProcessRes = headProcessRes->next;
108 nextProcessRes = firstProcessRes;
109 while ((nextProcessRes != NULL) && (nextProcessRes->next != NULL)) {
110 firstProcessRes = nextProcessRes;
111 nextProcessRes = firstProcessRes->next;
112 }
113 resultProcess = firstProcessRes->process;
114 firstProcessRes->next = NULL;
115 g_processList.num--;
116 return resultProcess;
117 }
118
FreeProcessResList(void)119 void FreeProcessResList(void)
120 {
121 ProcessRes *frontProcessRes = g_processList.processRes;
122 ProcessRes *nextProcessRes = NULL;
123 ProcessRes *tmpProcessRes = NULL;
124
125 nextProcessRes = frontProcessRes->next;
126 while (nextProcessRes != NULL) {
127 tmpProcessRes = nextProcessRes->next;
128 free(nextProcessRes);
129 nextProcessRes = tmpProcessRes;
130 }
131
132 free(g_processList.processRes);
133 memset_s(&g_processList, sizeof(g_processList), 0, sizeof(g_processList));
134 return;
135 }
136
InitProcess(void)137 int InitProcess(void)
138 {
139 g_process= (Process*)malloc(sizeof(Process));
140 ASSERT_RETURN(g_process != NULL, "Malloc ProcessRes Error");
141 (void)memset_s(g_process, sizeof(Process), 0, sizeof(Process));
142 return SUCCESS;
143 }
144
GetProcess(void)145 Process *GetProcess(void)
146 {
147 return g_process;
148 }
149
FreeProcess(void)150 void FreeProcess(void)
151 {
152 if (g_process != NULL) {
153 free(g_process);
154 g_process = NULL;
155 }
156 return;
157 }
158
MonitorControlChannel(void)159 void MonitorControlChannel(void)
160 {
161 fd_set fdSet;
162 char *endPtr = NULL;
163 int ret, fdMax, index;
164 ControlChannelBuf dataBuf;
165 ControlChannelRes *channelInfo;
166 channelInfo = GetControlChannelRes();
167 int32_t fd = channelInfo->sockFd;
168 fdMax = fd + 1;
169 struct timeval stTimeOut = {0};
170 while (!channelInfo->isExit) {
171 stTimeOut.tv_sec = 1;
172 stTimeOut.tv_usec = 0;
173 FD_ZERO(&fdSet);
174 FD_SET(fd, &fdSet);
175 ret = select(fdMax, &fdSet, NULL, NULL, &stTimeOut);
176 if (ret <= 0) {
177 LOG_ERROR("Select Error");
178 continue;
179 }
180
181 if (FD_ISSET(fd, &fdSet)) {
182 ret = ControlChannelRead(fd, &dataBuf);
183 if (ret != SUCCESS) {
184 LOG_ERROR("ControlChannelRead Error");
185 continue;
186 }
187 CmdData cmdData = {0};
188 ret = ParseCmdFromStr(dataBuf.data, &cmdData);
189 index = (int)strtol(cmdData.id, &endPtr, 0) % MAX_RCV_BUFFER_NUM;
190 ret = PushResultToChannelIdBuffer(channelInfo, dataBuf.data, index);
191 if (ret != SUCCESS) {
192 LOG_ERROR("PushResultToChannelRcvBuffer Error");
193 return;
194 }
195 LOG_DEBUG("Local Process Rcv is %s", dataBuf.data);
196 } else {
197 LOG_ERROR("FD_ISSET Error");
198 }
199 }
200 }
201
InitSrcProcess(TLS_TYPE tlsType,char * srcDomainPath)202 HLT_Process *InitSrcProcess(TLS_TYPE tlsType, char *srcDomainPath)
203 {
204 int ret, srcPathLen;
205 ControlChannelRes *channelInfo;
206 char srcControlDomainPath[DOMAIN_PATH_LEN] = {0};
207 HLT_Process *process;
208
209 // Check whether the call is the first time.
210 process = GetProcess();
211 if (process != NULL) {
212 LOG_ERROR("Repeat Init LocalProcess Is Not Support");
213 return NULL;
214 }
215
216 // The printf output buffer is not set.
217 setbuf(stdout, NULL);
218
219 // Initializes the command statistics global variable, which is required only by the local process.
220 InitCmdIndex();
221
222 srcPathLen = strlen(srcDomainPath);
223 if (srcPathLen == 0) {
224 LOG_ERROR("srcDomainPath is NULL");
225 return NULL;
226 }
227
228 ret = sprintf_s(srcControlDomainPath, DOMAIN_PATH_LEN, "%s.%u.sock", basename(srcDomainPath), getpid());
229
230 ret = InitProcess();
231 if (ret != SUCCESS) {
232 LOG_ERROR("InitProcess Error");
233 return NULL;
234 }
235
236 process = GetProcess();
237
238 if (HLT_LibraryInit(tlsType) != SUCCESS) {
239 LOG_ERROR("HLT_TlsRegCallback ERROR is %d", ret);
240 goto ERR;
241 }
242
243 // Initialize the process resource linked list, which is used to store remote process resources.
244 ret = InitProcessList();
245 if (ret != SUCCESS) {
246 LOG_ERROR("InitProcessList ERROR");
247 goto ERR;
248 }
249
250 // Initializes the CTX SSL resource linked list.
251 ret = InitTlsResList();
252 if (ret != SUCCESS) {
253 LOG_ERROR("InitTlsResList ERROR");
254 goto ERR;
255 }
256
257 // Initialize the control link.
258 ret = InitControlChannelRes(srcControlDomainPath, strlen(srcControlDomainPath), NULL, 0);
259 if (ret != SUCCESS) {
260 LOG_ERROR("InitControlChannelRes ERROR");
261 goto ERR;
262 }
263
264 channelInfo = GetControlChannelRes();
265
266 // Create control link UDP domain socket
267 ret = ControlChannelInit(channelInfo);
268 if (ret != SUCCESS) {
269 LOG_ERROR("ControlChannelInit ERROR");
270 goto ERR;
271 }
272
273 // Start a thread to listen to the control link. The link is used to receive the results returned by other processes
274 pthread_t tId;
275 channelInfo->isExit = false;
276 if (pthread_create(&tId, NULL, (void*)MonitorControlChannel, NULL) != 0) {
277 LOG_ERROR("Create MonitorControlChannel Thread Error ...");
278 goto ERR;
279 }
280 channelInfo->tid = tId;
281
282 // Populate Process Information
283 process->tlsType = tlsType;
284 process->controlChannelFd = channelInfo->sockFd;
285 process->remoteFlag = 0;
286 process->tlsResNum = 0;
287 process->hltTlsResNum = 0;
288 process->connType = NONE_TYPE;
289 process->connFd = 0;
290 ret = memcpy_s(process->srcDomainPath, DOMAIN_PATH_LEN, srcControlDomainPath, strlen(srcControlDomainPath));
291 if (ret != EOK) {
292 LOG_ERROR("memcpy_s process->srcDomainPath ERROR");
293 goto ERR;
294 }
295 LOG_DEBUG("Init Local Process Successful");
296 return (HLT_Process*)process;
297
298 ERR:
299 free(process);
300 return NULL;
301 }
302
InitPeerProcess(TLS_TYPE tlsType,HILT_TransportType connType,int port,bool isBlock)303 HLT_Process *InitPeerProcess(TLS_TYPE tlsType, HILT_TransportType connType, int port, bool isBlock)
304 {
305 // peerDomainPath address, which is the IP address of the monitoring process.
306 // Creating a Process
307 int ret, peerPathLen, tryNum;
308 char startCmd[CMD_MAX_LEN] = {0};
309 HLT_Process *localProcess;
310 HLT_Process *process = NULL;
311
312 localProcess = GetProcess();
313 if (localProcess == NULL) {
314 LOG_ERROR("Must Call HLT_InitLocalProcess First");
315 return NULL;
316 }
317
318 peerPathLen = strlen(localProcess->srcDomainPath);
319 if (peerPathLen == 0) {
320 LOG_ERROR("peerDomainPath is NULL");
321 return NULL;
322 }
323
324 process = (HLT_Process*)malloc(sizeof(HLT_Process));
325 if (process == NULL) {
326 LOG_ERROR("Malloc Process is NULL");
327 return NULL;
328 }
329 (void)memset_s(process, sizeof(HLT_Process), 0, sizeof(HLT_Process));
330 pid_t localpid = getpid();
331 ret = sprintf_s(startCmd,
332 CMD_MAX_LEN,
333 START_PROCESS_CMD,
334 tlsType,
335 localProcess->srcDomainPath,
336 g_processIndex,
337 localProcess->srcDomainPath,
338 localpid,
339 localProcess->srcDomainPath,
340 g_processIndex);
341 if (ret == 0) {
342 LOG_ERROR("sprintf_s Error");
343 free(process);
344 return NULL;
345 }
346
347 LOG_DEBUG("Exect Cmd is %s", startCmd);
348 ret = system(startCmd);
349 if (ret == ERROR) {
350 LOG_ERROR("System Error");
351 free(process);
352 return NULL;
353 }
354
355 // After the remote process is started successfully, the remote process is stored in the linked list.
356 InsertProcessToList(process);
357
358 // The message is received, indicating that the peer end is in the receiveable state.
359 CmdData expectCmdData = {0};
360 (void)sprintf_s(expectCmdData.id, sizeof(expectCmdData.id), "0");
361 (void)sprintf_s(expectCmdData.funcId, sizeof(expectCmdData.funcId), "HEART");
362 tryNum = 0;
363 do {
364 ret = WaitResultFromPeer(&expectCmdData);
365 tryNum++;
366 } while ((ret == ERROR) && (tryNum < 2)); // Retry once
367
368 if (ret == ERROR) {
369 LOG_ERROR("WaitResultFromPeer Error");
370 goto ERR;
371 }
372
373 // Populate Process Information
374 process->connType = NONE_TYPE;
375 process->connFd = 0;
376 process->tlsType = tlsType;
377 process->remoteFlag = 1;
378 ret = sprintf_s(process->srcDomainPath, DOMAIN_PATH_LEN, "%s_%d", localProcess->srcDomainPath, g_processIndex);
379 if (ret <= 0) {
380 LOG_ERROR("sprintf_s Error");
381 goto ERR;
382 }
383 // Creating a Data Link
384 if (connType != NONE_TYPE) {
385 DataChannelParam channelParam;
386 HLT_FD sockFd = {0};
387 channelParam.port = port;
388 channelParam.type = connType;
389 channelParam.isBlock = isBlock; // The SCTP link is set to non-block. Otherwise, the SCTP link may be suspended.
390 sockFd = HLT_CreateDataChannel(process, localProcess, channelParam);
391 localProcess->connType = connType;
392 localProcess->connFd = sockFd.peerFd;
393 localProcess->sockAddr = sockFd.sockAddr;
394 process->connType = connType;
395 process->connFd = sockFd.srcFd;
396 process->connPort = sockFd.connPort;
397 if ((sockFd.srcFd <= 0) || (sockFd.peerFd <= 0)) {
398 LOG_ERROR("Create CHANNEL ERROR");
399 goto ERR;
400 }
401 }
402 g_processIndex++;
403 return (HLT_Process*)process;
404 ERR:
405 // You do not need to release the process. If you can go to this point,
406 // the process is successfully created and inserted into the table.
407 // The process resource is released in the HLT_FreeAllProcess function.
408 // If the remote process is released in advance, the remote process may be successfully started but cannot be exited
409 g_processIndex++;
410 return NULL;
411 }
412