• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "nstackx_dfile.h"
17 #include "nstackx_util.h"
18 #include "nstackx_event.h"
19 #include "nstackx_log.h"
20 #include "nstackx_epoll.h"
21 #include "nstackx_dfile_session.h"
22 #include "nstackx_dfile_config.h"
23 #include "nstackx_dfile_mp.h"
24 #include "nstackx_congestion.h"
25 #ifdef MBEDTLS_INCLUDED
26 #include "nstackx_mbedtls.h"
27 #else
28 #include "nstackx_openssl.h"
29 #endif
30 #include "nstackx_dfile_private.h"
31 #include "securec.h"
32 #include "nstackx_socket.h"
33 
34 #define TAG "nStackXDFile"
35 #define Coverity_Tainted_Set(pkt)
36 
37 #define SOCKET_SEND_BUFFER                 (0x38000 * 15)
38 #define SOCKET_RECV_BUFFER                 (0x38000 * 192)
39 
40 /* this lock will been destroy only when process exit. */
41 static pthread_mutex_t g_dFileSessionIdMutex = PTHREAD_MUTEX_INITIALIZER;
42 static pthread_mutex_t g_dFileSessionChainMutex = PTHREAD_MUTEX_INITIALIZER;
43 static List g_dFileSessionChain = {&(g_dFileSessionChain), &(g_dFileSessionChain)};
44 static uint16_t g_dFileSessionId = 0;
45 /* currently enabled capabilities */
46 static uint32_t g_capabilities = NSTACKX_CAPS_WLAN_CATAGORY;
47 /* wlan catagory from APP */
48 static uint32_t g_wlanCatagory = NSTACKX_WLAN_CAT_TCP;
49 
50 typedef struct DFileSessionNode {
51     List list;
52     uint16_t sessionId;
53     DFileSession *session;
54 } DFileSessionNode;
55 
56 typedef struct {
57     DFileSession *session;
58     char *path;
59 } DFileSetStoragePathCtx;
60 
61 typedef struct {
62     DFileSession *session;
63     OnDFileRenameFile onRenameFile;
64 } DFileSetRenameHookCtx;
65 
GetDFileSessionId(uint16_t * sessionId)66 static int32_t GetDFileSessionId(uint16_t *sessionId)
67 {
68     if (PthreadMutexLock(&g_dFileSessionIdMutex) != 0) {
69         return NSTACKX_EFAILED;
70     }
71 
72     if (g_dFileSessionId == 0) {
73         ListInitHead(&g_dFileSessionChain);
74     }
75     if (g_dFileSessionId == UINT16_MAX) {
76         g_dFileSessionId = 1;
77     } else {
78         g_dFileSessionId++;
79     }
80     *sessionId = g_dFileSessionId;
81 
82     if (PthreadMutexUnlock(&g_dFileSessionIdMutex) != 0) {
83         *sessionId = 0;
84         return NSTACKX_EFAILED;
85     }
86 
87     return NSTACKX_EOK;
88 }
89 
GetDFileSessionNodeById(uint16_t sessionId)90 static DFileSessionNode *GetDFileSessionNodeById(uint16_t sessionId)
91 {
92     List *pos = NULL;
93     DFileSessionNode *node = NULL;
94     uint8_t isFound = NSTACKX_FALSE;
95     if (PthreadMutexLock(&g_dFileSessionChainMutex) != 0) {
96         LOGE(TAG, "lock g_dFileSessionChainMutex failed");
97         return NULL;
98     }
99     LIST_FOR_EACH(pos, &g_dFileSessionChain) {
100         node = (DFileSessionNode *)pos;
101         if (node->sessionId == sessionId) {
102             isFound = NSTACKX_TRUE;
103             break;
104         }
105     }
106     if (PthreadMutexUnlock(&g_dFileSessionChainMutex) != 0) {
107         LOGE(TAG, "unlock g_dFileSessionChainMutex failed");
108         return NULL;
109     }
110     if (isFound) {
111         return node;
112     }
113     return NULL;
114 }
115 
AddDFileSessionNode(DFileSession * session)116 static int32_t AddDFileSessionNode(DFileSession *session)
117 {
118     DFileSessionNode *node = calloc(1, sizeof(DFileSessionNode));
119     if (node == NULL) {
120         return NSTACKX_EFAILED;
121     }
122 
123     node->session = session;
124     node->sessionId = session->sessionId;
125     if (PthreadMutexLock(&g_dFileSessionChainMutex) != 0) {
126         LOGE(TAG, "lock g_dFileSessionChainMutex failed");
127         free(node);
128         return NSTACKX_EFAILED;
129     }
130     ListInsertTail(&g_dFileSessionChain, &node->list);
131     if (PthreadMutexUnlock(&g_dFileSessionChainMutex) != 0) {
132         LOGE(TAG, "unlock g_dFileSessionChainMutex failed");
133         ListRemoveNode(&node->list);
134         free(node);
135         return NSTACKX_EFAILED;
136     }
137     return NSTACKX_EOK;
138 }
139 
PopDFileSessionNodeById(uint16_t sessionId)140 static DFileSessionNode *PopDFileSessionNodeById(uint16_t sessionId)
141 {
142     DFileSessionNode *node = NULL;
143     List *pos = NULL;
144     List *tmp = NULL;
145     uint8_t isFound = NSTACKX_FALSE;
146     if (PthreadMutexLock(&g_dFileSessionChainMutex) != 0) {
147         LOGE(TAG, "lock g_dFileSessionChainMutex failed");
148         return NULL;
149     }
150     LIST_FOR_EACH_SAFE(pos, tmp, &g_dFileSessionChain) {
151         node = (DFileSessionNode *)pos;
152         if (node->sessionId == sessionId) {
153             ListRemoveNode(&node->list);
154             isFound = NSTACKX_TRUE;
155             break;
156         }
157     }
158     if (PthreadMutexUnlock(&g_dFileSessionChainMutex) != 0) {
159         LOGE(TAG, "unlock g_dFileSessionChainMutex failed");
160         if (node != NULL) {
161             ListInsertTail(&g_dFileSessionChain, &node->list);
162         }
163         return NULL;
164     }
165 
166     if (isFound) {
167         return node;
168     }
169     return NULL;
170 }
171 
CheckSessionIdValid(int32_t sessionId)172 static int32_t CheckSessionIdValid(int32_t sessionId)
173 {
174     if (sessionId < 0 || sessionId > UINT16_MAX) {
175         return NSTACKX_EINVAL;
176     }
177     return NSTACKX_EOK;
178 }
179 
CheckDFileSessionNodeValid(const DFileSessionNode * node)180 static int32_t CheckDFileSessionNodeValid(const DFileSessionNode *node)
181 {
182     if (node == NULL || node->session == NULL) {
183         return NSTACKX_EINVAL;
184     }
185     return NSTACKX_EOK;
186 }
187 
CheckFileNum(uint32_t fileNum)188 static int32_t CheckFileNum(uint32_t fileNum)
189 {
190     if (fileNum == 0 || fileNum > NSTACKX_DFILE_MAX_FILE_NUM) {
191         return NSTACKX_EINVAL;
192     }
193     return NSTACKX_EOK;
194 }
195 
DFileSetStoragePathInner(void * arg)196 static void DFileSetStoragePathInner(void *arg)
197 {
198     DFileSetStoragePathCtx *ctx = arg;
199     if (ctx->session == NULL) {
200         free(ctx->path);
201         free(ctx);
202         return;
203     }
204 
205     if (FileManagerSetWritePath(ctx->session->fileManager, ctx->path) != NSTACKX_EOK) {
206         LOGE(TAG, "filemanager set write path failed");
207     }
208     free(ctx->path);
209     free(ctx);
210 }
211 
CheckSetStoragePathPara(int32_t sessionId,const char * path)212 static int32_t CheckSetStoragePathPara(int32_t sessionId, const char *path)
213 {
214     size_t len;
215     if (CheckSessionIdValid(sessionId) != NSTACKX_EOK || path == NULL) {
216         LOGE(TAG, "invalid arg input");
217         return NSTACKX_EINVAL;
218     }
219 
220     len = strlen(path);
221     if (len == 0 || len > NSTACKX_MAX_PATH_LEN) {
222         LOGE(TAG, "Invalid path name length");
223         return NSTACKX_EINVAL;
224     }
225     return NSTACKX_EOK;
226 }
227 
NSTACKX_DFileSetStoragePath(int32_t sessionId,const char * path)228 int32_t NSTACKX_DFileSetStoragePath(int32_t sessionId, const char *path)
229 {
230     /* EaglEye test */
231     Coverity_Tainted_Set((void *)&sessionId);
232     Coverity_Tainted_Set((void *)path);
233 
234     DFileSetStoragePathCtx *ctx = NULL;
235 
236     if (CheckSetStoragePathPara(sessionId, path) != NSTACKX_EOK) {
237         return NSTACKX_EINVAL;
238     }
239 
240     DFileSessionNode *node = GetDFileSessionNodeById((uint16_t)sessionId);
241     if (CheckDFileSessionNodeValid(node) != NSTACKX_EOK) {
242         LOGE(TAG, "no session found for id %d", sessionId);
243         return NSTACKX_EINVAL;
244     }
245 
246     ctx = malloc(sizeof(DFileSetStoragePathCtx));
247     if (ctx == NULL) {
248         return NSTACKX_ENOMEM;
249     }
250 
251     /* When second parameter is NULL, realpath() uses malloc() to allocate a buffer of up to PATH_MAX bytes. */
252     ctx->path = realpath(path, NULL);
253     if (ctx->path == NULL) {
254         LOGE(TAG, "can't get canonicalized absolute pathname");
255         free(ctx);
256         return NSTACKX_EFAILED;
257     }
258 
259     if (!IsAccessiblePath(ctx->path, W_OK, S_IFDIR)) {
260         LOGE(TAG, "the input path isn't a valid writable folder");
261         free(ctx->path);
262         free(ctx);
263         return NSTACKX_EFAILED;
264     }
265 
266     ctx->session = node->session;
267 
268     if (PostEvent(&node->session->eventNodeChain, node->session->epollfd, DFileSetStoragePathInner, ctx) !=
269         NSTACKX_EOK) {
270         free(ctx->path);
271         free(ctx);
272         return NSTACKX_EFAILED;
273     }
274 
275     return NSTACKX_EOK;
276 }
277 
HasRepeatedNumber(const uint16_t * data,uint16_t len)278 static uint8_t HasRepeatedNumber(const uint16_t *data, uint16_t len)
279 {
280     uint16_t i, j;
281     for (i = 0; i < len; i++) {
282         for (j = i + 1; j < len; j++) {
283             if (data[i] == data[j]) {
284                 return NSTACKX_TRUE;
285             }
286         }
287     }
288     return NSTACKX_FALSE;
289 }
290 
291 
292 typedef struct {
293     DFileSession *session;
294     char *pathList[NSTACKX_MAX_STORAGE_PATH_NUM];
295     uint16_t pathType[NSTACKX_MAX_STORAGE_PATH_NUM];
296     uint16_t pathNum;
297 } DFileSetStoragePathListCtx;
298 
ClearStoragePathListCtx(DFileSetStoragePathListCtx * ctx)299 static void ClearStoragePathListCtx(DFileSetStoragePathListCtx *ctx)
300 {
301     if (ctx == NULL) {
302         return;
303     }
304     for (uint16_t i = 0; i < ctx->pathNum; i++) {
305         free(ctx->pathList[i]);
306         ctx->pathList[i] = NULL;
307     }
308     free(ctx);
309 }
310 
DFileSetStoragePathListInner(void * arg)311 static void DFileSetStoragePathListInner(void *arg)
312 {
313     DFileSetStoragePathListCtx *ctx = arg;
314 
315     if (ctx == NULL) {
316         return;
317     }
318 
319     if (ctx->session == NULL) {
320         ClearStoragePathListCtx(ctx);
321         return;
322     }
323 
324     if (FileManagerSetWritePathList(ctx->session->fileManager, ctx->pathList, ctx->pathType, ctx->pathNum) !=
325         NSTACKX_EOK) {
326         ClearStoragePathListCtx(ctx);
327         return;
328     }
329 
330     /* if set filemanager write path list successfully, the pathList menmber will be freed in filemanager */
331     free(ctx);
332 }
333 
CreateStoragePathListCtx(const DFileSession * session,const char * path[],const uint16_t * pathType,uint16_t pathNum)334 DFileSetStoragePathListCtx *CreateStoragePathListCtx(const DFileSession *session, const char *path[],
335                                                      const uint16_t *pathType, uint16_t pathNum)
336 {
337     DFileSetStoragePathListCtx *ctx = NULL;
338     uint16_t i, pos;
339 
340     if (pathNum > NSTACKX_MAX_STORAGE_PATH_NUM) {
341         LOGE(TAG, "invalid pathNum");
342         return NULL;
343     }
344 
345     ctx = malloc(sizeof(DFileSetStoragePathListCtx));
346     if (ctx == NULL) {
347         return NULL;
348     }
349 
350     for (i = 0; i < pathNum; i++) {
351         /* When second parameter is NULL, realpath() uses malloc() to allocate a buffer of up to PATH_MAX bytes. */
352         ctx->pathList[i] = realpath(path[i], NULL);
353         if (ctx->pathList[i] == NULL) {
354             LOGE(TAG, "can't get canonicalized absolute pathname");
355             pos = i;
356             goto L_ERR;
357         }
358         if (!IsAccessiblePath(ctx->pathList[i], W_OK, S_IFDIR)) {
359             LOGE(TAG, "the input path isn't a valid writable folder");
360             pos = i + 1;
361             goto L_ERR;
362         }
363         ctx->pathType[i] = pathType[i];
364     }
365     ctx->pathNum = pathNum;
366     ctx->session = (DFileSession *)session;
367     return ctx;
368 
369 L_ERR:
370     while (pos > 0) {
371         free(ctx->pathList[pos - 1]);
372         ctx->pathList[pos - 1] = NULL;
373         pos--;
374     }
375     free(ctx);
376     return NULL;
377 }
378 
CheckSetStoragePathListPara(int32_t sessionId,const char * path[],const uint16_t * pathType,uint16_t pathNum)379 static int32_t CheckSetStoragePathListPara(int32_t sessionId, const char *path[], const uint16_t *pathType,
380                                            uint16_t pathNum)
381 {
382     if (CheckSessionIdValid(sessionId) != NSTACKX_EOK || path == NULL || pathType == NULL || pathNum == 0 ||
383         pathNum > NSTACKX_MAX_STORAGE_PATH_NUM) {
384         LOGE(TAG, "invalid arg input");
385         return NSTACKX_EINVAL;
386     }
387 
388     if (HasRepeatedNumber(pathType, pathNum)) {
389         LOGE(TAG, "has repeated type");
390         return NSTACKX_EINVAL;
391     }
392     return NSTACKX_EOK;
393 }
394 
NSTACKX_DFileSetStoragePathList(int32_t sessionId,const char * path[],const uint16_t * pathType,uint16_t pathNum)395 int32_t NSTACKX_DFileSetStoragePathList(int32_t sessionId, const char *path[], const uint16_t *pathType,
396                                         uint16_t pathNum)
397 {
398     /* EaglEye test */
399     Coverity_Tainted_Set((void *)&sessionId);
400     Coverity_Tainted_Set((void *)path);
401     Coverity_Tainted_Set((void *)pathType);
402     Coverity_Tainted_Set((void *)&pathNum);
403 
404     DFileSetStoragePathListCtx *ctx = NULL;
405 
406     if (CheckSetStoragePathListPara(sessionId, path, pathType, pathNum) != NSTACKX_EOK) {
407         return NSTACKX_EINVAL;
408     }
409 
410     DFileSessionNode *node = GetDFileSessionNodeById((uint16_t)sessionId);
411     if (CheckDFileSessionNodeValid(node) != NSTACKX_EOK) {
412         LOGE(TAG, "no session found for id %d", sessionId);
413         return NSTACKX_EINVAL;
414     }
415 
416     ctx = CreateStoragePathListCtx(node->session, path, pathType, pathNum);
417     if (ctx == NULL) {
418         return NSTACKX_ENOMEM;
419     }
420 
421     if (PostEvent(&node->session->eventNodeChain, node->session->epollfd, DFileSetStoragePathListInner, ctx) !=
422         NSTACKX_EOK) {
423         ClearStoragePathListCtx(ctx);
424         ctx = NULL;
425         return NSTACKX_EFAILED;
426     }
427     return NSTACKX_EOK;
428 }
429 
430 typedef struct {
431     DFileSession *session;
432     FileListInfo *fileListInfo;
433 } DFileSendFileCtx;
434 
AddFileList(DFileSession * session,FileListInfo * fileListInfo)435 static inline void AddFileList(DFileSession *session, FileListInfo *fileListInfo)
436 {
437 #ifdef NSTACKX_SMALL_FILE_SUPPORT
438     if (fileListInfo->smallFlag == NSTACKX_TRUE) {
439         ListInsertTail(&session->smallFileLists, &fileListInfo->list);
440         session->smallListPendingCnt++;
441     } else {
442         ListInsertTail(&session->pendingFileLists, &fileListInfo->list);
443         session->fileListPendingCnt++;
444     }
445 #else
446     ListInsertTail(&session->pendingFileLists, &fileListInfo->list);
447     session->fileListPendingCnt++;
448 #endif
449 }
450 
DFileSendFileFail(void * arg)451 static void DFileSendFileFail(void *arg)
452 {
453     DFileSendFileCtx *ctx = arg;
454     DFileSession *session = ctx->session;
455     DFileMsg data;
456 
457     (void)memset_s(&data, sizeof(data), 0, sizeof(data));
458     data.errorCode = NSTACKX_EINVAL;
459     data.fileList.files = (const char **)ctx->fileListInfo->files;
460     data.fileList.fileNum = ctx->fileListInfo->fileNum;
461     data.fileList.userData = ctx->fileListInfo->userData;
462     NotifyMsgRecver(session, DFILE_ON_FILE_SEND_FAIL, &data);
463     DestroyFileListInfo(ctx->fileListInfo);
464     free(ctx);
465 }
466 
DFileSendFileInner(void * arg)467 static void DFileSendFileInner(void *arg)
468 {
469     DFileSendFileCtx *ctx = arg;
470     DFileSession *session = ctx->session;
471     DFileMsg data;
472 
473     (void)memset_s(&data, sizeof(data), 0, sizeof(data));
474     if (session == NULL) {
475         data.errorCode = NSTACKX_EINVAL;
476         LOGE(TAG, "session is NULL");
477         goto L_END;
478     }
479 #ifdef NSTACKX_SMALL_FILE_SUPPORT
480     uint32_t totalCnt = session->fileListProcessingCnt + session->fileListPendingCnt + session->smallListProcessingCnt +
481         session->smallListPendingCnt;
482 #else
483     uint32_t totalCnt = session->fileListProcessingCnt + session->fileListPendingCnt;
484 #endif
485     LOGI(TAG, "recv filelist fileNum %u tarFlag %hhu path %s, total %u", ctx->fileListInfo->fileNum,
486         ctx->fileListInfo->tarFlag, ctx->fileListInfo->files[0], totalCnt + 1);
487     CalculateSessionTransferRatePrepare(session);
488     if (session->fileListProcessingCnt + session->smallListProcessingCnt >= NSTACKX_FILE_MANAGER_THREAD_NUM) {
489         AddFileList(session, ctx->fileListInfo);
490     } else {
491         int32_t ret = DFileStartTrans(session, ctx->fileListInfo);
492         if (ret != NSTACKX_EOK) {
493             data.errorCode = ret;
494             LOGE(TAG, "DFileStartTrans fail, error: %d", ret);
495             goto L_END;
496         }
497     }
498 
499     free(ctx);
500     return;
501 
502 L_END:
503     data.fileList.files = (const char **)ctx->fileListInfo->files;
504     data.fileList.fileNum = ctx->fileListInfo->fileNum;
505     data.fileList.userData = ctx->fileListInfo->userData;
506     NotifyMsgRecver(session, DFILE_ON_FILE_SEND_FAIL, &data);
507     DestroyFileListInfo(ctx->fileListInfo);
508     free(ctx);
509 }
510 
IsValidStringArray(const char * str[],uint32_t fileNum,size_t maxLen)511 static uint8_t IsValidStringArray(const char *str[], uint32_t fileNum, size_t maxLen)
512 {
513     if (str == NULL || fileNum == 0) {
514         return NSTACKX_FALSE;
515     }
516     for (uint32_t i = 0; i < fileNum; i++) {
517         if (str[i] == NULL) {
518             return NSTACKX_FALSE;
519         }
520         size_t len = strlen(str[i]);
521         if (len == 0 || len > maxLen) {
522             return NSTACKX_FALSE;
523         }
524     }
525     return NSTACKX_TRUE;
526 }
527 
CheckSendFilesPara(int32_t sessionId,const char * files[],uint32_t fileNum,const char * userData)528 static int32_t CheckSendFilesPara(int32_t sessionId, const char *files[], uint32_t fileNum, const char *userData)
529 {
530     size_t userDataLen;
531     if (CheckSessionIdValid(sessionId) != NSTACKX_EOK ||
532         !IsValidStringArray(files, fileNum, NSTACKX_MAX_FILE_NAME_LEN)) {
533         return NSTACKX_EINVAL;
534     }
535 
536     if (CheckFileNum(fileNum) != NSTACKX_EOK) {
537         LOGE(TAG, "fileNum to send is 0 or too large");
538         return NSTACKX_EINVAL;
539     }
540 
541     if (userData == NULL) {
542         userDataLen = 0;
543         LOGW(TAG, "send file with no user data.");
544     } else {
545         userDataLen = strlen(userData);
546     }
547 
548     if (userDataLen > NSTACKX_MAX_USER_DATA_SIZE) {
549         LOGE(TAG, "send file with too long user data len");
550         return NSTACKX_EINVAL;
551     }
552     return NSTACKX_EOK;
553 }
554 
SetVtransInfo(DFileSendFileCtx * ctx,DFileRebuildFileList * rFilelist,uint16_t index)555 void SetVtransInfo(DFileSendFileCtx *ctx, DFileRebuildFileList *rFilelist, uint16_t index)
556 {
557     if (rFilelist->realTransId > 0) {
558         ctx->fileListInfo->vtransFlag = NSTACKX_TRUE;
559         ctx->fileListInfo->vtransTotalNum = rFilelist->transNum;
560         ctx->fileListInfo->vtransRealTransId = rFilelist->realTransId;
561         ctx->fileListInfo->vtransRealFileId = rFilelist->realFileId[index];
562         ctx->fileListInfo->vtransTotalFileNum = rFilelist->totalFileNum;
563         ctx->fileListInfo->vtransTotalFileSize = rFilelist->totalFileSize;
564     }
565 }
566 
SendFilesInner(int32_t sessionId,const char * files[],const char * remotePath[],uint32_t fileNum,const char * userData)567 int32_t SendFilesInner(int32_t sessionId, const char *files[], const char *remotePath[],
568     uint32_t fileNum, const char *userData)
569 {
570     DFileRebuildFileList rFilelist;
571 
572     DFileSessionNode *node = GetDFileSessionNodeById((uint16_t)sessionId);
573     if (CheckDFileSessionNodeValid(node) != NSTACKX_EOK) {
574         LOGE(TAG, "no session found for id %d", sessionId);
575         return NSTACKX_EINVAL;
576     }
577     if (RebuildFilelist(files, remotePath, fileNum, node->session, &rFilelist) != NSTACKX_EOK) {
578         return NSTACKX_EFAILED;
579     }
580     for (uint16_t i = 0; i < rFilelist.transNum; i++) {
581         DFileSendFileCtx *ctx = malloc(sizeof(DFileSendFileCtx));
582         if (ctx == NULL) {
583             LOGE(TAG, "malloc ctx error: NULL");
584             return NSTACKX_ENOMEM;
585         }
586         ctx->session = node->session;
587 
588         FileListPara para = NEW_FILE_LIST_PARA(&(rFilelist.files[i]), (remotePath ? &(rFilelist.remotePath[i]) : NULL),
589             (rFilelist.realTransId ? 1 : fileNum), userData,
590             NSTACKX_FALSE, &(rFilelist.startOffset[i]), &(rFilelist.fileSize[i]));
591         ctx->fileListInfo = CreateFileListInfo(&para);
592         if (ctx->fileListInfo == NULL) {
593             LOGE(TAG, "CreateFileListInfo error: NULL");
594             free(ctx);
595             return NSTACKX_ENOMEM;
596         }
597         SetVtransInfo(ctx, &rFilelist, i);
598 
599         ctx->fileListInfo->noticeFileNameType = remotePath ? NOTICE_FULL_FILE_NAME_TYPE : NOTICE_FILE_NAME_TYPE;
600         ctx->fileListInfo->pathType = NSTACKX_RESERVED_PATH_TYPE;
601         ctx->fileListInfo->tarFlag = NSTACKX_FALSE;
602         ctx->fileListInfo->smallFlag = NSTACKX_FALSE;
603         int32_t ret = PostEvent(&node->session->eventNodeChain, node->session->epollfd, DFileSendFileInner, ctx);
604         if (ret != NSTACKX_EOK) {
605             DestroyFileListInfo(ctx->fileListInfo);
606             free(ctx);
607             return ret;
608         }
609     }
610 
611     node->session->allTaskCount++;
612 
613     return NSTACKX_EOK;
614 }
615 
NSTACKX_DFileSendFiles(int32_t sessionId,const char * files[],uint32_t fileNum,const char * userData)616 int32_t NSTACKX_DFileSendFiles(int32_t sessionId, const char *files[], uint32_t fileNum, const char *userData)
617 {
618     /* EaglEye test */
619     Coverity_Tainted_Set((void *)&sessionId);
620     Coverity_Tainted_Set((void *)files);
621     Coverity_Tainted_Set((void *)&fileNum);
622     Coverity_Tainted_Set((void *)userData);
623 
624     if (CheckSendFilesPara(sessionId, files, fileNum, userData) != NSTACKX_EOK) {
625         return NSTACKX_EINVAL;
626     }
627 
628     return SendFilesInner(sessionId, files, NULL, fileNum, userData);
629 }
630 
CheckSendFilesWithRemotePathPara(int32_t sessionId,const char * files[],const char * remotePath[],uint32_t fileNum,const char * userData)631 static int32_t CheckSendFilesWithRemotePathPara(int32_t sessionId, const char *files[], const char *remotePath[],
632                                                 uint32_t fileNum, const char *userData)
633 {
634     if (CheckSessionIdValid(sessionId) != NSTACKX_EOK ||
635         !IsValidStringArray(files, fileNum, NSTACKX_MAX_FILE_NAME_LEN) ||
636         !IsValidStringArray(remotePath, fileNum, NSTACKX_MAX_REMOTE_PATH_LEN)) {
637         LOGE(TAG, "invalid arg input");
638         return NSTACKX_EINVAL;
639     }
640     if (CheckFileNum(fileNum) != NSTACKX_EOK) {
641         LOGE(TAG, "fileNum to send is 0 or too large");
642         return NSTACKX_EINVAL;
643     }
644 
645     if (userData != NULL && strlen(userData) > NSTACKX_MAX_USER_DATA_SIZE) {
646         LOGE(TAG, "send file with too long user data len");
647         return NSTACKX_EINVAL;
648     }
649     return NSTACKX_EOK;
650 }
651 
NSTACKX_DFileSendFilesWithRemotePath(int32_t sessionId,const char * files[],const char * remotePath[],uint32_t fileNum,const char * userData)652 int32_t NSTACKX_DFileSendFilesWithRemotePath(int32_t sessionId, const char *files[], const char *remotePath[],
653                                              uint32_t fileNum, const char *userData)
654 {
655     /* EaglEye test */
656     Coverity_Tainted_Set((void *)&sessionId);
657     Coverity_Tainted_Set((void *)files);
658     Coverity_Tainted_Set((void *)remotePath);
659     Coverity_Tainted_Set((void *)&fileNum);
660     Coverity_Tainted_Set((void *)userData);
661 
662     if (remotePath == NULL) {
663         return NSTACKX_DFileSendFiles(sessionId, files, fileNum, userData);
664     }
665 
666     if (CheckSendFilesWithRemotePathPara(sessionId, files, remotePath, fileNum, userData) != NSTACKX_EOK) {
667         return NSTACKX_EINVAL;
668     }
669 
670     return SendFilesInner(sessionId, files, remotePath, fileNum, userData);
671 }
672 
CheckSendFilesWithRemotePathAndType(int32_t sessionId,NSTACKX_FilesInfo * filesInfo)673 static int32_t CheckSendFilesWithRemotePathAndType(int32_t sessionId, NSTACKX_FilesInfo *filesInfo)
674 {
675     if (CheckSessionIdValid(sessionId) != NSTACKX_EOK) {
676         return NSTACKX_EINVAL;
677     }
678     if (filesInfo == NULL || CheckFileNum(filesInfo->fileNum) != NSTACKX_EOK) {
679         return NSTACKX_EINVAL;
680     }
681     if (filesInfo->pathType == NSTACKX_RESERVED_PATH_TYPE) {
682         return NSTACKX_EINVAL;
683     }
684     if (!IsValidStringArray(filesInfo->files, filesInfo->fileNum, NSTACKX_MAX_FILE_NAME_LEN)) {
685         return NSTACKX_EINVAL;
686     }
687     if (filesInfo->tarFlag == NSTACKX_TRUE) {
688         /* when tarFlag is set, only remotePath[0] will be accessed */
689         if (!IsValidStringArray(filesInfo->remotePath, 1, NSTACKX_MAX_REMOTE_PATH_LEN)) {
690             return NSTACKX_EINVAL;
691         }
692     } else {
693         if (!IsValidStringArray(filesInfo->remotePath, filesInfo->fileNum, NSTACKX_MAX_REMOTE_PATH_LEN)) {
694             return NSTACKX_EINVAL;
695         }
696     }
697     if (filesInfo->userData != NULL && strlen(filesInfo->userData) > NSTACKX_MAX_USER_DATA_SIZE) {
698         LOGE(TAG, "send file with too long user data len");
699         return NSTACKX_EINVAL;
700     }
701     return NSTACKX_EOK;
702 }
703 
PostSendFailAsync(int32_t sessionId,const NSTACKX_FilesInfo * filesInfo)704 static void PostSendFailAsync(int32_t sessionId, const NSTACKX_FilesInfo *filesInfo)
705 {
706     const char *firstFileName = NULL;
707     if (CheckSessionIdValid(sessionId) != NSTACKX_EOK || filesInfo == NULL) {
708         return;
709     }
710     if (filesInfo->tarFlag == NSTACKX_TRUE) {
711         firstFileName = filesInfo->remotePath[0];
712     } else {
713         firstFileName = filesInfo->files[0];
714     }
715     if (firstFileName == NULL) {
716         return;
717     }
718     DFileSessionNode *node = GetDFileSessionNodeById((uint16_t)sessionId);
719     if (CheckDFileSessionNodeValid(node) != NSTACKX_EOK) {
720         LOGE(TAG, "no session found for id %d", sessionId);
721         return;
722     }
723     DFileSendFileCtx *ctx = calloc(1, sizeof(DFileSendFileCtx));
724     if (ctx == NULL) {
725         return;
726     }
727     ctx->session = node->session;
728     ctx->fileListInfo = calloc(1, sizeof(FileListInfo));
729     if (ctx->fileListInfo == NULL) {
730         goto L_ERR;
731     }
732     ctx->fileListInfo->fileNum = 1;
733     ctx->fileListInfo->files = calloc(1, sizeof(char *));
734     if (ctx->fileListInfo->files == NULL) {
735         goto L_ERR;
736     }
737     ctx->fileListInfo->files[0] = calloc(1, strlen(firstFileName) + 1);
738     if (ctx->fileListInfo->files[0] == NULL) {
739         goto L_ERR;
740     }
741     if (memcpy_s(ctx->fileListInfo->files[0], strlen(firstFileName) + 1,
742         firstFileName, strlen(firstFileName)) != NSTACKX_EOK) {
743         LOGE(TAG, "memcpy_s failed");
744         goto L_ERR;
745     }
746     if (PostEvent(&node->session->eventNodeChain, node->session->epollfd, DFileSendFileFail, ctx) == NSTACKX_EOK) {
747         return;
748     }
749 L_ERR:
750     DestroyFileListInfo(ctx->fileListInfo);
751     free(ctx);
752 }
753 
PackPrepareTar(const char * remotePath,char * tarName,uint32_t maxNameLen)754 static int32_t PackPrepareTar(const char *remotePath, char *tarName, uint32_t maxNameLen)
755 {
756     (void)remotePath;
757     (void)tarName;
758     (void)maxNameLen;
759     return NSTACKX_EOK;
760 }
761 
NSTACKX_DFileSendFilesWithRemotePathAndType(int32_t sessionId,NSTACKX_FilesInfo * filesInfo)762 int32_t NSTACKX_DFileSendFilesWithRemotePathAndType(int32_t sessionId, NSTACKX_FilesInfo *filesInfo)
763 {
764     /* EaglEye test */
765     Coverity_Tainted_Set((void *)filesInfo);
766 
767     char tarName[PATH_MAX + 1] = {0};
768     if (CheckSendFilesWithRemotePathAndType(sessionId, filesInfo) != NSTACKX_EOK) {
769         PostSendFailAsync(sessionId, filesInfo);
770         return NSTACKX_EINVAL;
771     }
772 
773     if (filesInfo->tarFlag == NSTACKX_TRUE) {
774         LOGE(TAG, "warning: tarflag is not supported now");
775         (void)PackPrepareTar(filesInfo->remotePath[0], tarName, PATH_MAX);
776         return NSTACKX_NOTSUPPORT;
777     }
778 
779     DFileSessionNode *node = GetDFileSessionNodeById((uint16_t)sessionId);
780     if (CheckDFileSessionNodeValid(node) != NSTACKX_EOK) {
781         LOGE(TAG, "no session found for id %d", sessionId);
782         return NSTACKX_EINVAL;
783     }
784 
785     DFileSendFileCtx *ctx = malloc(sizeof(DFileSendFileCtx));
786     if (ctx == NULL) {
787         return NSTACKX_ENOMEM;
788     }
789     ctx->session = node->session;
790     FileListPara fileListPara = NEW_FILE_LIST_PARA(filesInfo->files, filesInfo->remotePath, filesInfo->fileNum,
791         filesInfo->userData, filesInfo->tarFlag, NULL, NULL);
792     ctx->fileListInfo = CreateFileListInfo(&fileListPara);
793     if (ctx->fileListInfo == NULL) {
794         free(ctx);
795         ctx = NULL;
796         PostSendFailAsync(sessionId, filesInfo);
797         return NSTACKX_ENOMEM;
798     }
799 #ifdef NSTACKX_SMALL_FILE_SUPPORT
800     ctx->fileListInfo->smallFlag = filesInfo->smallFlag;
801 #else
802     ctx->fileListInfo->smallFlag = NSTACKX_FALSE;
803 #endif
804     ctx->fileListInfo->noSyncFlag = NSTACKX_TRUE;
805     ctx->fileListInfo->noticeFileNameType = NOTICE_FULL_FILE_NAME_TYPE;
806     ctx->fileListInfo->pathType = filesInfo->pathType;
807     ctx->fileListInfo->tarFile = strdup(tarName);
808 
809     int32_t ret = PostEvent(&node->session->eventNodeChain, node->session->epollfd, DFileSendFileInner, ctx);
810     if (ret != NSTACKX_EOK) {
811         DestroyFileListInfo(ctx->fileListInfo);
812         free(ctx);
813         ctx = NULL;
814         return ret;
815     }
816     return NSTACKX_EOK;
817 }
818 
DFileSessionBaseInit(DFileSession * session,DFileSessionType type,DFileMsgReceiver msgReceiver,uint16_t sessionId)819 static void DFileSessionBaseInit(DFileSession *session, DFileSessionType type, DFileMsgReceiver msgReceiver,
820     uint16_t sessionId)
821 {
822     uint32_t i;
823 
824     session->sessionId = sessionId;
825     session->transFlag = NSTACKX_FALSE;
826     session->bindType = INIT_STATUS;
827     session->sessionType = type;
828     session->msgReceiver = msgReceiver;
829     session->peerInfoCnt = 0;
830     ListInitHead(&session->eventNodeChain);
831     ListInitHead(&session->dFileTransChain);
832     ListInitHead(&session->peerInfoChain);
833     ListInitHead(&session->outboundQueue);
834     ListInitHead(&session->inboundQueue);
835     ListInitHead(&session->pendingFileLists);
836     ListInitHead(&session->vtransManagerList);
837 #ifdef NSTACKX_SMALL_FILE_SUPPORT
838     ListInitHead(&session->smallFileLists);
839 #endif
840 
841     for (i = 0; i < NSTACKX_FILE_MANAGER_THREAD_NUM; i++) {
842         session->transSlot[i].isWorking = NSTACKX_FALSE;
843         session->transSlot[i].transId = 0;
844         session->transSlot[i].peerInfo = NULL;
845     }
846 
847     for (i = 0; i < NSTACKX_MAX_CLIENT_SEND_THREAD_NUM; i++) {
848         ListInitHead(&session->freeIovList[i]);
849     }
850 }
851 
DFileSessionMutexInit(DFileSession * session)852 static int32_t DFileSessionMutexInit(DFileSession *session)
853 {
854     if (session == NULL) {
855         return NSTACKX_EFAILED;
856     }
857     if (PthreadMutexInit(&session->outboundQueueLock, NULL) != 0) {
858         goto L_ERR_OUTBOUND_QUEUE_LOCK;
859     }
860     if (PthreadMutexInit(&session->inboundQueueLock, NULL) != 0) {
861         goto L_ERR_INBOUND_QUEUE_LOCK;
862     }
863 
864     if (PthreadMutexInit(&session->transIdLock, NULL) != 0) {
865         goto L_ERR_TRANS_ID_LOCK;
866     }
867 
868     if (PthreadMutexInit(&session->backPressLock, NULL) != 0) {
869         goto L_ERR_BACKPRESS_LOCK;
870     }
871 
872     if (MutexListInit(&session->transferDoneAckList, MAX_TRANSFERDONE_ACK_NODE_COUNT) != NSTACKX_EOK) {
873         LOGE(TAG, "transferDoneAckList InitList error");
874         goto L_ERR_TRANS_DONE_ACK_LOCK;
875     }
876 
877     if (MutexListInit(&session->tranIdStateList, MAX_TRANSTATELISTSIZE) != NSTACKX_EOK) {
878         LOGE(TAG, "tranIdStateList InitList error");
879         goto L_ERR_TRANS_STATE_LOCK;
880     }
881     return NSTACKX_EOK;
882 L_ERR_TRANS_STATE_LOCK:
883     MutexListDestory(&session->transferDoneAckList);
884 L_ERR_TRANS_DONE_ACK_LOCK:
885     PthreadMutexDestroy(&session->backPressLock);
886 L_ERR_BACKPRESS_LOCK:
887     PthreadMutexDestroy(&session->transIdLock);
888 L_ERR_TRANS_ID_LOCK:
889     PthreadMutexDestroy(&session->inboundQueueLock);
890 L_ERR_INBOUND_QUEUE_LOCK:
891     PthreadMutexDestroy(&session->outboundQueueLock);
892 L_ERR_OUTBOUND_QUEUE_LOCK:
893     return NSTACKX_EFAILED;
894 }
895 
PostSessionCreate(DFileSession * session)896 static inline void PostSessionCreate(DFileSession *session)
897 {
898     session->capability = g_capabilities;
899     session->wlanCatagory = g_wlanCatagory;
900 
901     LOGI(TAG, "current capabilities tcp:%d", CapsTcp(session));
902 }
903 
DFileSessionCreate(DFileSessionType type,DFileMsgReceiver msgReceiver)904 static DFileSession *DFileSessionCreate(DFileSessionType type, DFileMsgReceiver msgReceiver)
905 {
906     uint16_t sessionId = 0;
907     if (GetDFileSessionId(&sessionId) != NSTACKX_EOK) {
908         return NULL;
909     }
910 
911     DFileSession *session = calloc(1, sizeof(DFileSession));
912     if (session == NULL) {
913         return NULL;
914     }
915 
916     DFileSessionBaseInit(session, type, msgReceiver, sessionId);
917 
918     if (InitOutboundQueueWait(session) != NSTACKX_EOK) {
919         goto L_ERR_SEM;
920     }
921 
922     session->epollfd = CreateEpollDesc();
923     if (!IsEpollDescValid(session->epollfd)) {
924         goto L_ERR_EPOLL;
925     }
926 
927     session->recvBuffer = calloc(1, NSTACKX_RECV_BUFFER_LEN);
928     if (session->recvBuffer == NULL) {
929         LOGE(TAG, "can not get memory");
930         goto L_ERR_RECVBUFFER;
931     }
932 
933     if (DFileSessionMutexInit(session) != NSTACKX_EOK) {
934         goto L_ERR_MUTEX;
935     }
936     PostSessionCreate(session);
937     return session;
938 L_ERR_MUTEX:
939     free(session->recvBuffer);
940 L_ERR_RECVBUFFER:
941     CloseEpollDesc(session->epollfd);
942 L_ERR_EPOLL:
943     DestroyOutboundQueueWait(session);
944 L_ERR_SEM:
945     free(session);
946     return NULL;
947 }
948 
DFileClearTransferDoneAckList(DFileSession * session)949 static void DFileClearTransferDoneAckList(DFileSession *session)
950 {
951     List *pos = NULL;
952     List *tmp = NULL;
953     TransferDoneAckNode *transferDoneAckNode = NULL;
954     if (PthreadMutexLock(&session->transferDoneAckList.lock) != 0) {
955         LOGE(TAG, "pthread mutex lock error");
956         return;
957     }
958     LIST_FOR_EACH_SAFE(pos, tmp, &session->transferDoneAckList.head) {
959         transferDoneAckNode = (TransferDoneAckNode *)pos;
960         ListRemoveNode(&transferDoneAckNode->list);
961         free(transferDoneAckNode);
962         session->transferDoneAckList.size--;
963     }
964     if (PthreadMutexUnlock(&session->transferDoneAckList.lock) != 0) {
965         LOGE(TAG, "pthread mutex unlock error");
966         return;
967     }
968     return;
969 }
970 
DFileSessionClean(DFileSession * session)971 static void DFileSessionClean(DFileSession *session)
972 {
973     List *tmp = NULL;
974     List *pos = NULL;
975     PeerInfo *peerInfo = NULL;
976 
977     LIST_FOR_EACH_SAFE(pos, tmp, &session->peerInfoChain) {
978         peerInfo = (PeerInfo *)pos;
979         if (peerInfo->settingTimer != NULL) {
980             TimerDelete(peerInfo->settingTimer);
981             peerInfo->settingTimer = NULL;
982         }
983         ListRemoveNode(&peerInfo->list);
984         free(peerInfo);
985     }
986     if (IsEpollDescValid(session->epollfd)) {
987         CloseEpollDesc(session->epollfd);
988         session->epollfd = INVALID_EPOLL_DESC;
989     }
990     DestroyOutboundQueueWait(session);
991     PthreadMutexDestroy(&session->inboundQueueLock);
992     PthreadMutexDestroy(&session->outboundQueueLock);
993     PthreadMutexDestroy(&session->transIdLock);
994     PthreadMutexDestroy(&session->backPressLock);
995     DFileClearTransferDoneAckList(session);
996     MutexListDestory(&session->transferDoneAckList);
997     MutexListDestory(&session->tranIdStateList);
998     free(session->recvBuffer);
999     free(session);
1000     return;
1001 }
1002 
DFileRecverInit(DFileSession * session,struct sockaddr_in * sockAddr,uint8_t socketIndex)1003 static int32_t DFileRecverInit(DFileSession *session, struct sockaddr_in *sockAddr, uint8_t socketIndex)
1004 {
1005     SocketProtocol protocol;
1006 
1007     if (CapsTcp(session)) {
1008         protocol = NSTACKX_PROTOCOL_TCP;
1009     } else {
1010         protocol = NSTACKX_PROTOCOL_UDP;
1011     }
1012 
1013     Socket *socket = ServerSocket(protocol, sockAddr);
1014     if (socket == NULL) {
1015         return NSTACKX_EFAILED;
1016     }
1017 
1018     /* Note: If the monitoring method is not select, this restriction should be removed */
1019     if (CheckFdSetSize(socket->sockfd) != NSTACKX_EOK) {
1020         LOGE(TAG, "CheckFdSetSize failed");
1021         CloseSocket(socket);
1022         return NSTACKX_EFAILED;
1023     }
1024 
1025     session->socket[socketIndex] = socket;
1026     session->protocol = protocol;
1027     LOGI(TAG, "create server socket %d protocol is %d", socket->sockfd, protocol);
1028     int32_t optVal = 0;
1029     socklen_t optLen = sizeof(optVal);
1030     if (getsockopt(socket->sockfd, SOL_SOCKET, SO_RCVBUF, (void *)&optVal, &optLen) == 0) {
1031         LOGI(TAG, "default recv buf is %d bytes", optVal);
1032     }
1033 
1034     return NSTACKX_EOK;
1035 }
1036 
DFileRecverDestory(DFileSession * session)1037 static void DFileRecverDestory(DFileSession *session)
1038 {
1039     CloseSocket(session->socket[0]);
1040     CloseSocket(session->socket[1]);
1041     session->socket[0] = NULL;
1042     session->socket[1] = NULL;
1043 }
1044 
StartDFileThreads(DFileSession * session)1045 static int32_t StartDFileThreads(DFileSession *session)
1046 {
1047     if (CreateReceiverPipe(session) != NSTACKX_EOK) {
1048         LOGE(TAG, "Create pipe failed");
1049         goto L_ERR_PIPE;
1050     }
1051 
1052     if (EventModuleInit(&session->eventNodeChain, session->epollfd) != NSTACKX_EOK) {
1053         LOGE(TAG, "Event module init failed!");
1054         goto L_ERR_EVENT;
1055     }
1056 
1057     if (StartDFileThreadsInner(session) == NSTACKX_EOK) {
1058         return NSTACKX_EOK;
1059     }
1060 
1061     EventNodeChainClean(&session->eventNodeChain);
1062     CloseEpollDesc(session->epollfd);
1063     session->epollfd = INVALID_EPOLL_DESC;
1064 L_ERR_EVENT:
1065     DestroyReceiverPipe(session);
1066 L_ERR_PIPE:
1067     return NSTACKX_EFAILED;
1068 }
1069 
StopDFileThreads(DFileSession * session)1070 static void StopDFileThreads(DFileSession *session)
1071 {
1072     /* Notify main loop thread to terminate */
1073     if (PostEvent(&session->eventNodeChain, session->epollfd, TerminateMainThreadInner, session) != NSTACKX_EOK) {
1074         DFileSessionSetTerminateFlag(session);
1075 
1076         /* Notify sender thread to terminate */
1077         PostOutboundQueueWait(session);
1078 
1079         /* Unblock "select" and notify receiver thread to terminate */
1080         NotifyPipeEvent(session);
1081     }
1082 
1083     /* Terminate 3 handling threads */
1084     PthreadJoin(session->tid, NULL);
1085     session->tid = INVALID_TID;
1086 
1087     PthreadJoin(session->senderTid[0], NULL);
1088     session->senderTid[0] = INVALID_TID;
1089 
1090     PthreadJoin(session->receiverTid, NULL);
1091     session->receiverTid = INVALID_TID;
1092     PthreadJoin(session->controlTid, NULL);
1093     session->controlTid = INVALID_TID;
1094 
1095     /* Terminate file IO thread */
1096     StopFileManagerThreads(session->fileManager);
1097     /* Clear event callback */
1098     ClearEvent(&session->eventNodeChain, session->epollfd);
1099     EventNodeChainClean(&session->eventNodeChain);
1100     CloseEpollDesc(session->epollfd);
1101     session->epollfd = INVALID_EPOLL_DESC;
1102     DestroyReceiverPipe(session);
1103 }
1104 
StartSessionRunning(DFileSession * session,uint16_t SendThreadNum)1105 int32_t StartSessionRunning(DFileSession *session, uint16_t SendThreadNum)
1106 {
1107     session->clientSendThreadNum = SendThreadNum;
1108     if (StartDFileThreads(session) != NSTACKX_EOK) {
1109         return NSTACKX_EFAILED;
1110     }
1111     if (AddDFileSessionNode(session) != NSTACKX_EOK) {
1112         return NSTACKX_EFAILED;
1113     }
1114 
1115     return NSTACKX_EOK;
1116 }
1117 
NSTACKX_DFileInit(void)1118 static int32_t NSTACKX_DFileInit(void)
1119 {
1120     if (SocketModuleInit() != NSTACKX_EOK) {
1121         return NSTACKX_EFAILED;
1122     }
1123     if (CongModuleInit() != NSTACKX_EOK) {
1124         goto L_ERR_CONG;
1125     }
1126 #ifdef NSTACKX_WITH_LITEOS
1127     EpollEventPtrInit();
1128 #endif
1129 
1130     return NSTACKX_EOK;
1131 
1132 L_ERR_CONG:
1133     SocketModuleClean();
1134     LOGE(TAG, "fail to create dfile server ");
1135     return NSTACKX_EFAILED;
1136 }
1137 
NSTACKX_DFileServer(struct sockaddr_in * localAddr,socklen_t addrLen,const uint8_t * key,uint32_t keyLen,DFileMsgReceiver msgReceiver)1138 int32_t NSTACKX_DFileServer(struct sockaddr_in *localAddr, socklen_t addrLen, const uint8_t *key, uint32_t keyLen,
1139                             DFileMsgReceiver msgReceiver)
1140 {
1141     /* EaglEye test */
1142     Coverity_Tainted_Set((void *)localAddr);
1143     Coverity_Tainted_Set((void *)&addrLen);
1144     Coverity_Tainted_Set((void *)key);
1145     Coverity_Tainted_Set((void *)&keyLen);
1146     Coverity_Tainted_Set((void *)msgReceiver);
1147 
1148     LOGI(TAG, "Begin to create dfile server ");
1149     DFileSession *session = NULL;
1150     struct sockaddr_in sockAddr;
1151 
1152     if (localAddr == NULL || localAddr->sin_family != AF_INET || sizeof(struct sockaddr_in) != addrLen) {
1153         return NSTACKX_EFAILED;
1154     }
1155     if (NSTACKX_DFileInit() != NSTACKX_EOK) {
1156         return NSTACKX_EFAILED;
1157     }
1158     session = DFileSessionCreate(DFILE_SESSION_TYPE_SERVER, msgReceiver);
1159     if (session == NULL) {
1160         goto L_ERR_SESSION;
1161     }
1162 
1163     (void)memset_s(&sockAddr, sizeof(sockAddr), 0, sizeof(sockAddr));
1164     sockAddr.sin_port = htons(localAddr->sin_port);
1165     sockAddr.sin_addr.s_addr = htonl(localAddr->sin_addr.s_addr);
1166     if (DFileRecverInit(session, &sockAddr, 0) != NSTACKX_EOK) {
1167         goto L_ERR_RECVER_INIT;
1168     }
1169 
1170     if (CreateFileManager(session, key, keyLen, NSTACKX_FALSE, CONNECT_TYPE_NONE) != NSTACKX_EOK) {
1171         goto L_ERR_FILE_MANAGER;
1172     }
1173 
1174     if (StartSessionRunning(session, 1) != NSTACKX_EOK) {
1175         goto L_ERR_THREAD;
1176     }
1177 
1178     return session->sessionId;
1179 L_ERR_THREAD:
1180     StopFileManagerThreads(session->fileManager);
1181     FileManagerDestroy(session->fileManager);
1182 L_ERR_FILE_MANAGER:
1183     DFileRecverDestory(session);
1184 L_ERR_RECVER_INIT:
1185     DFileSessionClean(session);
1186 L_ERR_SESSION:
1187     CongModuleClean();
1188     SocketModuleClean();
1189     LOGE(TAG, "fail to create dfile server ");
1190     return NSTACKX_EFAILED;
1191 }
1192 
DFileSenderInitWithTargetDev(DFileSession * session,const struct sockaddr_in * sockAddr,uint16_t * connType,const char * localInterface,uint8_t socketIndex)1193 static int32_t DFileSenderInitWithTargetDev(DFileSession *session, const struct sockaddr_in *sockAddr,
1194                                             uint16_t *connType, const char *localInterface, uint8_t socketIndex)
1195 {
1196     SocketProtocol protocol;
1197 
1198     protocol = CapsTcp(session) ? NSTACKX_PROTOCOL_TCP : NSTACKX_PROTOCOL_UDP;
1199 
1200     Socket *socket = ClientSocketWithTargetDev(protocol, sockAddr, localInterface);
1201     if (socket == NULL) {
1202         LOGE(TAG, "socket is null");
1203         return NSTACKX_EFAILED;
1204     }
1205 
1206     /* Note: If the monitoring method is not select, this restriction should be removed */
1207     if (CheckFdSetSize(socket->sockfd) != NSTACKX_EOK) {
1208         LOGE(TAG, "CheckFdSetSize failed");
1209         CloseSocket(socket);
1210         return NSTACKX_EFAILED;
1211     }
1212 
1213     session->socket[socketIndex] = socket;
1214     session->protocol = protocol;
1215 
1216     if (CapsTcp(session)) {
1217         SetTcpKeepAlive(socket->sockfd);
1218     }
1219 
1220     int32_t ret = GetConnectionType(socket->srcAddr.sin_addr.s_addr, socket->dstAddr.sin_addr.s_addr,
1221                                     connType);
1222     if (ret != NSTACKX_EOK) {
1223         LOGE(TAG, "get connect type failed, ret = %d", ret);
1224         goto L_ERR_PEER_INFO;
1225     }
1226     if ((*connType != CONNECT_TYPE_P2P && *connType != CONNECT_TYPE_WLAN)) {
1227         *connType = CONNECT_TYPE_WLAN;
1228         LOGI(TAG, "connet type isn't wlan or p2p, and will be set to wlan by default");
1229     }
1230     PeerInfo *peerInfo = CreatePeerInfo(session, &socket->dstAddr, 0, *connType, socketIndex);
1231     if (peerInfo == NULL) {
1232         goto L_ERR_PEER_INFO;
1233     }
1234     ListInsertTail(&session->peerInfoChain, &peerInfo->list);
1235     *connType = peerInfo->connType;
1236     return NSTACKX_EOK;
1237 
1238 L_ERR_PEER_INFO:
1239     CloseSocket(session->socket[0]);
1240     CloseSocket(session->socket[1]);
1241     session->socket[0] = NULL;
1242     session->socket[1] = NULL;
1243     return NSTACKX_EFAILED;
1244 }
1245 
DFileSenderDestory(DFileSession * session)1246 static void DFileSenderDestory(DFileSession *session)
1247 {
1248     CloseSocket(session->socket[0]);
1249     CloseSocket(session->socket[1]);
1250     session->socket[0] = NULL;
1251     session->socket[1] = NULL;
1252 
1253     List *pos = NULL;
1254     List *tmp = NULL;
1255     LIST_FOR_EACH_SAFE(pos, tmp, &session->peerInfoChain) {
1256         PeerInfo *peerInfo = (PeerInfo *)pos;
1257         ListRemoveNode(&peerInfo->list);
1258         free(peerInfo);
1259         session->peerInfoCnt--;
1260     }
1261 }
1262 
InitSockaddr(const struct sockaddr_in * inSockAddr,struct sockaddr_in * sockAddr)1263 static inline void InitSockaddr(const struct sockaddr_in *inSockAddr, struct sockaddr_in *sockAddr)
1264 {
1265     (void)memset_s(sockAddr, sizeof(*sockAddr), 0, sizeof(*sockAddr));
1266     sockAddr->sin_family = AF_INET;
1267     sockAddr->sin_port = htons(inSockAddr->sin_port);
1268     sockAddr->sin_addr.s_addr = htonl(inSockAddr->sin_addr.s_addr);
1269 }
1270 
GetClientSendThreadNum(uint16_t connType)1271 static uint16_t GetClientSendThreadNum(uint16_t connType)
1272 {
1273     if (connType == CONNECT_TYPE_WLAN) {
1274         return NSTACKX_WLAN_CLIENT_SEND_THREAD_NUM;
1275     } else if (connType == CONNECT_TYPE_P2P) {
1276         return 1;
1277     } else {
1278         return 1;
1279     }
1280 }
1281 
CheckSessionPara(NSTACKX_SessionPara * sessionPara)1282 static int32_t CheckSessionPara(NSTACKX_SessionPara *sessionPara)
1283 {
1284     if (sessionPara == NULL) {
1285         return NSTACKX_EFAILED;
1286     }
1287 
1288     if (sessionPara->addr == NULL ||
1289         sessionPara->addr->sin_family != AF_INET ||
1290         sessionPara->addrLen != sizeof(struct sockaddr_in)) {
1291         return NSTACKX_EFAILED;
1292     }
1293 
1294     return NSTACKX_EOK;
1295 }
1296 
SendSettingToServer(DFileSession * session)1297 void SendSettingToServer(DFileSession *session)
1298 {
1299     List *pos = NULL;
1300     PeerInfo *peerInfo = NULL;
1301     LIST_FOR_EACH(pos, &session->peerInfoChain) {
1302         peerInfo = (PeerInfo *)pos;
1303         peerInfo->state = SETTING_NEGOTIATING;
1304         DFileSessionSendSetting(peerInfo);
1305     }
1306 }
1307 
NSTACKX_DFileClientWithTargetDev(NSTACKX_SessionPara * para)1308 int32_t NSTACKX_DFileClientWithTargetDev(NSTACKX_SessionPara *para)
1309 {
1310     /* EaglEye test */
1311     Coverity_Tainted_Set((void *)para);
1312 
1313     LOGI(TAG, "begin to Create Dfile client");
1314     struct sockaddr_in sockAddr;
1315 
1316     if (CheckSessionPara(para) != NSTACKX_EOK) {
1317         return NSTACKX_EFAILED;
1318     }
1319     InitSockaddr(para->addr, &sockAddr);
1320 
1321     if (SocketModuleInit() != NSTACKX_EOK) {
1322         return NSTACKX_EFAILED;
1323     }
1324     if (CongModuleInit() != NSTACKX_EOK) {
1325         goto L_ERR_CONG;
1326     }
1327     DFileSession *session = DFileSessionCreate(DFILE_SESSION_TYPE_CLIENT, para->msgReceiver);
1328     if (session == NULL) {
1329         goto L_ERR_SESSION;
1330     }
1331     uint16_t type = CONNECT_TYPE_NONE;
1332     if (DFileSenderInitWithTargetDev(session, &sockAddr, &type, para->localInterfaceName, 0) != NSTACKX_EOK) {
1333         goto L_ERR_SENDER_INIT;
1334     }
1335 
1336     if (CreateFileManager(session, para->key, para->keyLen, NSTACKX_TRUE, type) != NSTACKX_EOK) {
1337         goto L_ERR_FILE_MANAGER;
1338     }
1339 
1340     if (StartSessionRunning(session, GetClientSendThreadNum(type)) != NSTACKX_EOK) {
1341         goto L_ERR_THREAD;
1342     }
1343 
1344     SendSettingToServer(session);
1345 
1346     return session->sessionId;
1347 L_ERR_THREAD:
1348     StopFileManagerThreads(session->fileManager);
1349     FileManagerDestroy(session->fileManager);
1350 L_ERR_FILE_MANAGER:
1351     DFileSenderDestory(session);
1352 L_ERR_SENDER_INIT:
1353     DFileSessionClean(session);
1354 L_ERR_SESSION:
1355     CongModuleClean();
1356 L_ERR_CONG:
1357     SocketModuleClean();
1358     LOGE(TAG, "fail to create dfile client");
1359     return NSTACKX_EFAILED;
1360 }
1361 
NSTACKX_DFileClient(struct sockaddr_in * srvAddr,socklen_t addrLen,const uint8_t * key,uint32_t keyLen,DFileMsgReceiver msgReceiver)1362 int32_t NSTACKX_DFileClient(struct sockaddr_in *srvAddr, socklen_t addrLen, const uint8_t *key, uint32_t keyLen,
1363                             DFileMsgReceiver msgReceiver)
1364 {
1365     /* EaglEye test */
1366     Coverity_Tainted_Set((void *)srvAddr);
1367     Coverity_Tainted_Set((void *)&addrLen);
1368     Coverity_Tainted_Set((void *)key);
1369     Coverity_Tainted_Set((void *)&keyLen);
1370     Coverity_Tainted_Set((void *)msgReceiver);
1371 
1372     NSTACKX_SessionPara sessionPara;
1373 
1374     (void)memset_s(&sessionPara, sizeof(sessionPara), 0, sizeof(sessionPara));
1375     sessionPara.addr = srvAddr;
1376     sessionPara.addrLen = addrLen;
1377     sessionPara.key = key;
1378     sessionPara.keyLen = keyLen;
1379     sessionPara.msgReceiver = msgReceiver;
1380     sessionPara.localInterfaceName = NULL;
1381 #ifdef NSTACKX_WITH_LITEOS
1382     EpollEventPtrInit();
1383 #endif
1384     return NSTACKX_DFileClientWithTargetDev(&sessionPara);
1385 }
1386 
ClearPendingFileList(DFileSession * session)1387 static inline void ClearPendingFileList(DFileSession *session)
1388 {
1389     List *tmp = NULL;
1390     List *pos = NULL;
1391     LIST_FOR_EACH_SAFE(pos, tmp, &session->pendingFileLists) {
1392         FileListInfo *fileListInfo = (FileListInfo *)pos;
1393         ListRemoveNode(&fileListInfo->list);
1394         DestroyFileListInfo(fileListInfo);
1395     }
1396 }
1397 
1398 #ifdef NSTACKX_SMALL_FILE_SUPPORT
ClearSmallFileList(DFileSession * session)1399 static inline void ClearSmallFileList(DFileSession *session)
1400 {
1401     List *tmp = NULL;
1402     List *pos = NULL;
1403     LIST_FOR_EACH_SAFE(pos, tmp, &session->smallFileLists) {
1404         FileListInfo *fileListInfo = (FileListInfo *)pos;
1405         ListRemoveNode(&fileListInfo->list);
1406         DestroyFileListInfo(fileListInfo);
1407     }
1408 }
1409 #endif
1410 
ClearTransChain(DFileSession * session)1411 static inline void ClearTransChain(DFileSession *session)
1412 {
1413     while (!ListIsEmpty(&session->dFileTransChain)) {
1414         DFileTrans *trans = (DFileTrans *)ListPopFront(&session->dFileTransChain);
1415         DFileTransDestroy(trans);
1416     }
1417 }
1418 
ClearOutboundQueue(DFileSession * session)1419 static inline void ClearOutboundQueue(DFileSession *session)
1420 {
1421     List *tmp = NULL;
1422     List *pos = NULL;
1423     LIST_FOR_EACH_SAFE(pos, tmp, &session->outboundQueue) {
1424         QueueNode *node = (QueueNode *)pos;
1425         ListRemoveNode(&node->list);
1426         free(node->frame);
1427         free(node);
1428     }
1429 }
1430 
ClearInboundQueue(DFileSession * session)1431 static inline void ClearInboundQueue(DFileSession *session)
1432 {
1433     List *tmp = NULL;
1434     List *pos = NULL;
1435     LIST_FOR_EACH_SAFE(pos, tmp, &session->inboundQueue) {
1436         QueueNode *node = (QueueNode *)pos;
1437         ListRemoveNode(&node->list);
1438         free(node->frame);
1439         free(node);
1440     }
1441 }
1442 
1443 
NSTACKX_DFileClose(int32_t sessionId)1444 void NSTACKX_DFileClose(int32_t sessionId)
1445 {
1446     /* EaglEye test */
1447     Coverity_Tainted_Set((void *)&sessionId);
1448 
1449     LOGI(TAG, "begin to close session");
1450     if (CheckSessionIdValid(sessionId) != NSTACKX_EOK) {
1451         LOGE(TAG, "invalid session id (%d) for close", sessionId);
1452         return;
1453     }
1454 
1455     DFileSessionNode *sessionNode = PopDFileSessionNodeById((uint16_t)sessionId);
1456     if (CheckDFileSessionNodeValid(sessionNode) != NSTACKX_EOK) {
1457         LOGE(TAG, "no session found for id %d", sessionId);
1458         return;
1459     }
1460 
1461     StopDFileThreads(sessionNode->session);
1462     ClearPendingFileList(sessionNode->session);
1463 #ifdef NSTACKX_SMALL_FILE_SUPPORT
1464     ClearSmallFileList(sessionNode->session);
1465 #endif
1466     ClearTransChain(sessionNode->session);
1467     ClearOutboundQueue(sessionNode->session);
1468     ClearInboundQueue(sessionNode->session);
1469     ClearTransStateList(sessionNode->session);
1470     FileManagerDestroy(sessionNode->session->fileManager);
1471     CloseSocket(sessionNode->session->socket[0]);
1472     CloseSocket(sessionNode->session->socket[1]);
1473     if (sessionNode->session->sessionType == DFILE_SESSION_TYPE_SERVER) {
1474         if (sessionNode->session->acceptSocket != NULL) {
1475             CloseSocket(sessionNode->session->acceptSocket);
1476         }
1477     }
1478 
1479     DFileSessionClean(sessionNode->session);
1480     free(sessionNode);
1481     CongModuleClean();
1482     SocketModuleClean();
1483     LOGI(TAG, "finish to close session");
1484 }
1485 
DFileSetRenameHookInner(void * arg)1486 static void DFileSetRenameHookInner(void *arg)
1487 {
1488     DFileSetRenameHookCtx *ctx = arg;
1489     if (ctx->session == NULL) {
1490         free(ctx);
1491         return;
1492     }
1493     ctx->session->onRenameFile = ctx->onRenameFile;
1494     free(ctx);
1495 }
1496 
NSTACKX_DFileSetRenameHook(int32_t sessionId,OnDFileRenameFile onRenameFile)1497 int32_t NSTACKX_DFileSetRenameHook(int32_t sessionId, OnDFileRenameFile onRenameFile)
1498 {
1499     /* EaglEye test */
1500     Coverity_Tainted_Set((void *)&sessionId);
1501     Coverity_Tainted_Set((void *)onRenameFile);
1502     DFileSetRenameHookCtx *ctx = NULL;
1503 
1504     if (CheckSessionIdValid(sessionId) != NSTACKX_EOK || onRenameFile == NULL) {
1505         LOGE(TAG, "invalid arg input");
1506         return NSTACKX_EINVAL;
1507     }
1508 
1509     DFileSessionNode *node = GetDFileSessionNodeById((uint16_t)sessionId);
1510     if (CheckDFileSessionNodeValid(node) != NSTACKX_EOK) {
1511         LOGE(TAG, "no session found for id %d", sessionId);
1512         return NSTACKX_EINVAL;
1513     }
1514 
1515     ctx = malloc(sizeof(DFileSetRenameHookCtx));
1516     if (ctx == NULL) {
1517         return NSTACKX_ENOMEM;
1518     }
1519     ctx->session = node->session;
1520     ctx->onRenameFile = onRenameFile;
1521 
1522     if (PostEvent(&node->session->eventNodeChain, node->session->epollfd, DFileSetRenameHookInner, ctx) !=
1523         NSTACKX_EOK) {
1524         free(ctx);
1525         return NSTACKX_EFAILED;
1526     }
1527 
1528     return NSTACKX_EOK;
1529 }
1530 
1531 static DFileLogImpl g_userLogImpl;
1532 
LogWrapper(const char * tag,uint32_t level,const char * format,va_list args)1533 static void LogWrapper(const char *tag, uint32_t level, const char *format, va_list args)
1534 {
1535     if (g_userLogImpl) {
1536         g_userLogImpl(tag, level, format, args);
1537     }
1538 }
1539 
NSTACKX_DFileRegisterLog(DFileLogImpl logImpl)1540 int32_t NSTACKX_DFileRegisterLog(DFileLogImpl logImpl)
1541 {
1542     if (logImpl == NULL) {
1543         (void)printf("NULL pointer\n");
1544         return NSTACKX_EFAILED;
1545     }
1546     g_userLogImpl = logImpl;
1547     SetLogImpl(LogWrapper);
1548     return NSTACKX_EOK;
1549 }
1550 
NSTACKX_DFileGetCapabilities(void)1551 uint32_t NSTACKX_DFileGetCapabilities(void)
1552 {
1553     return g_capabilities;
1554 }
1555 
NSTACKX_DFileSetCapabilities(uint32_t capabilities,uint32_t value)1556 int32_t NSTACKX_DFileSetCapabilities(uint32_t capabilities, uint32_t value)
1557 {
1558     /* EaglEye test */
1559     Coverity_Tainted_Set((void *)&capabilities);
1560     Coverity_Tainted_Set((void *)&value);
1561     /* unused para */
1562     (void)(capabilities);
1563     (void)(value);
1564     return NSTACKX_EOK;
1565 }
1566