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