• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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