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_file_manager.h"
17 #include "nstackx_dfile_config.h"
18 #include "nstackx_dfile_session.h"
19 #include "nstackx_error.h"
20 #include "nstackx_event.h"
21 #include "nstackx_file_manager_client.h"
22 #include "nstackx_dfile_log.h"
23 #ifdef MBEDTLS_INCLUDED
24 #include "nstackx_mbedtls.h"
25 #else
26 #include "nstackx_openssl.h"
27 #endif
28 #include "nstackx_util.h"
29 #include "securec.h"
30 
31 #define TAG "nStackXDFile"
32 
33 static FileRecvState FileGetRecvStatus(FileInfo *fileInfo);
34 
35 typedef struct {
36     FileManagerMsgReceiver msgReceiver;
37     FileManagerMsgType msgType;
38     int32_t errCode;
39     void *context;
40 } FileManagerMsgCtx;
41 
42 typedef struct {
43     FileListMsgReceiver msgReceiver;
44     FileManagerMsgType msgType;
45     uint16_t fileId;
46     FileManagerMsg msg;
47     void *context;
48     uint16_t transId;
49 } FileListMsgCtx;
50 
NotifyFileManagerMsgInner(void * arg)51 static void NotifyFileManagerMsgInner(void *arg)
52 {
53     FileManagerMsgCtx *ctx = arg;
54     ctx->msgReceiver(ctx->msgType, ctx->errCode, ctx->context);
55     free(ctx);
56     return;
57 }
58 
NotifyFileListMsgInner(void * arg)59 static void NotifyFileListMsgInner(void *arg)
60 {
61     FileListMsgCtx *ctx = arg;
62     ctx->msgReceiver(ctx->fileId, ctx->msgType, &ctx->msg, ctx->context, ctx->transId);
63     free(ctx);
64     return;
65 }
66 
NotifyFileManagerMsg(const FileManager * fileManager,FileManagerMsgType msgType)67 void NotifyFileManagerMsg(const FileManager *fileManager, FileManagerMsgType msgType)
68 {
69     FileManagerMsgCtx *ctx = NULL;
70     if (fileManager->msgReceiver == NULL || !IsEpollDescValid(fileManager->epollfd)) {
71         return;
72     }
73     ctx = (FileManagerMsgCtx *)calloc(1, sizeof(FileManagerMsgCtx));
74     if (ctx == NULL) {
75         return;
76     }
77     ctx->msgReceiver = fileManager->msgReceiver;
78     ctx->msgType = msgType;
79     ctx->context = fileManager->context;
80     ctx->errCode = fileManager->errCode;
81     if (PostEvent(fileManager->eventNodeChain, fileManager->epollfd, NotifyFileManagerMsgInner, ctx) != NSTACKX_EOK) {
82         free(ctx);
83         return;
84     }
85 }
86 
NotifyFileListMsg(const FileListTask * fileList,FileManagerMsgType msgType)87 void NotifyFileListMsg(const FileListTask *fileList, FileManagerMsgType msgType)
88 {
89     FileListMsgCtx *ctx = NULL;
90     if (fileList == NULL) {
91         DFILE_LOGE(TAG, "NotifyFileListMsg fileList error");
92         return;
93     }
94 
95     if (fileList->msgReceiver == NULL || !IsEpollDescValid(fileList->epollfd)) {
96         return;
97     }
98     ctx = (FileListMsgCtx *)calloc(1, sizeof(FileListMsgCtx));
99     if (ctx == NULL) {
100         return;
101     }
102     if (msgType == FILE_MANAGER_TRANS_IN_PROGRESS) {
103         if (fileList->bytesTransferredLastRecord >= fileList->totalBytes) {
104             free(ctx);
105             return;
106         }
107         ctx->msg.transferUpdate.bytesTransferred = fileList->bytesTransferredLastRecord;
108         ctx->msg.transferUpdate.totalBytes = fileList->totalBytes;
109         ctx->msg.transferUpdate.transId = fileList->transId;
110     }
111 
112     ctx->msgReceiver = fileList->msgReceiver;
113     ctx->fileId = NSTACKX_RESERVED_FILE_ID;
114     ctx->msgType = msgType;
115     ctx->msg.errorCode = fileList->errCode;
116     ctx->context = fileList->context;
117     ctx->transId = fileList->transId;
118     if (PostEvent(fileList->eventNodeChain, fileList->epollfd, NotifyFileListMsgInner, ctx) != NSTACKX_EOK) {
119         free(ctx);
120         return;
121     }
122 }
123 
NotifyFileMsg(const FileListTask * fileList,uint16_t fileId,FileManagerMsgType msgType)124 void NotifyFileMsg(const FileListTask *fileList, uint16_t fileId, FileManagerMsgType msgType)
125 {
126     FileListMsgCtx *ctx = NULL;
127     if (fileList->msgReceiver == NULL || !IsEpollDescValid(fileList->epollfd) || fileId == 0 ||
128         fileId > fileList->fileNum) {
129         return;
130     }
131     ctx = (FileListMsgCtx *)calloc(1, sizeof(FileListMsgCtx));
132     if (ctx == NULL) {
133         return;
134     }
135     ctx->msgReceiver = fileList->msgReceiver;
136     ctx->fileId = fileId;
137     ctx->msgType = msgType;
138     ctx->msg.errorCode = fileList->fileInfo[fileId - 1].errCode;
139     ctx->context = fileList->context;
140     ctx->transId = fileList->transId;
141     if (PostEvent(fileList->eventNodeChain, fileList->epollfd, NotifyFileListMsgInner, ctx) != NSTACKX_EOK) {
142         free(ctx);
143         return;
144     }
145 }
146 
ConvertErrCode(int32_t error)147 int32_t ConvertErrCode(int32_t error)
148 {
149     switch (error) {
150         case ENOSPC:
151             return FILE_MANAGER_FILE_ENOSPC;
152         case ENOMEM:
153             return FILE_MANAGER_FILE_ENOMEM;
154         case ENFILE:
155             return FILE_MANAGER_FILE_ENFILE;
156         case EACCES:
157             return FILE_MANAGER_FILE_EACCES;
158         case ENAMETOOLONG:
159             return FILE_MANAGER_FILE_ENAMETOOLONG;
160         case ETXTBSY:
161             return FILE_MANAGER_FILE_ETXTBSY;
162         default:
163             return FILE_MANAGER_FILE_EOTHER;
164     }
165 }
166 
MutexListInit(MutexList * mutexList,uint32_t maxSize)167 int32_t MutexListInit(MutexList *mutexList, uint32_t maxSize)
168 {
169     if (mutexList == NULL || maxSize == 0) {
170         DFILE_LOGE(TAG, "list with lock dosn't exist of maxSize if zero");
171         return NSTACKX_EINVAL;
172     }
173     (void)memset_s(mutexList, sizeof(MutexList), 0, sizeof(MutexList));
174     if (PthreadMutexInit(&mutexList->lock, NULL) != 0) {
175         DFILE_LOGE(TAG, "PthreadMutexInit error");
176         return NSTACKX_EFAILED;
177     }
178     ListInitHead(&mutexList->head);
179     mutexList->maxSize = maxSize;
180     return NSTACKX_EOK;
181 }
182 
MutexListDestory(MutexList * mutexList)183 void MutexListDestory(MutexList *mutexList)
184 {
185     PthreadMutexDestroy(&mutexList->lock);
186 }
187 
MutexListAddNode(MutexList * mutexList,List * element,uint8_t isFront)188 int32_t MutexListAddNode(MutexList *mutexList, List *element, uint8_t isFront)
189 {
190     int32_t ret;
191     if (PthreadMutexLock(&mutexList->lock) != 0) {
192         DFILE_LOGE(TAG, "pthread mutex lock error");
193         return NSTACKX_EFAILED;
194     }
195     if (mutexList->size == mutexList->maxSize) {
196         DFILE_LOGE(TAG, "list is full");
197         ret = NSTACKX_EFAILED;
198     } else {
199         if (isFront) {
200             ListInsertHead(&mutexList->head, element);
201         } else {
202             ListInsertTail(&mutexList->head, element);
203         }
204         ret = NSTACKX_EOK;
205         mutexList->size++;
206     }
207     if (PthreadMutexUnlock(&mutexList->lock) != 0) {
208         DFILE_LOGE(TAG, "pthread mutex unlock error");
209         return NSTACKX_EFAILED;
210     }
211     return ret;
212 }
213 
MutexListPopFront(MutexList * mutexList,List ** curFront,uint8_t * isPoped)214 int32_t MutexListPopFront(MutexList *mutexList, List **curFront, uint8_t *isPoped)
215 {
216     int32_t ret;
217     *isPoped = NSTACKX_FALSE;
218     if (PthreadMutexLock(&mutexList->lock) != 0) {
219         DFILE_LOGE(TAG, "pthread mutex lock error");
220         return NSTACKX_EFAILED;
221     }
222     if (mutexList->size == 0) {
223         ret = NSTACKX_EFAILED;
224     } else {
225         *curFront = ListPopFront(&mutexList->head);
226         mutexList->size--;
227         *isPoped = NSTACKX_TRUE;
228         ret = NSTACKX_EOK;
229     }
230     if (PthreadMutexUnlock(&mutexList->lock) != 0) {
231         DFILE_LOGE(TAG, "pthread mutex unlock error");
232         return NSTACKX_EFAILED;
233     }
234     return ret;
235 }
236 
PrepareOneTaskByStatus(FileManager * fileManager,uint32_t runStatus,uint8_t * isErrorOccurred)237 static FileListTask *PrepareOneTaskByStatus(FileManager *fileManager, uint32_t runStatus, uint8_t *isErrorOccurred)
238 {
239     List *pos = NULL;
240     List *tmp = NULL;
241     FileListTask *fileList = NULL;
242     uint8_t isFound = NSTACKX_FALSE;
243     *isErrorOccurred = NSTACKX_FALSE;
244 
245     if (fileManager == NULL) {
246         return NULL;
247     }
248     if (PthreadMutexLock(&fileManager->taskList.lock) != 0) {
249         DFILE_LOGE(TAG, "pthread mutex lock error");
250         *isErrorOccurred = NSTACKX_TRUE;
251         return NULL;
252     }
253     LIST_FOR_EACH_SAFE(pos, tmp, &fileManager->taskList.head) {
254         fileList = (FileListTask *)pos;
255         if (fileList->runStatus == runStatus) {
256             if (fileList->isOccupied == NSTACKX_TRUE) {
257                 continue;
258             }
259             if (runStatus == FILE_LIST_STATUS_IDLE) {
260                 fileList->runStatus = FILE_LIST_STATUS_RUN;
261                 fileList->isOccupied = NSTACKX_TRUE;
262             } else if (runStatus == FILE_LIST_STATUS_STOP) {
263                 ListRemoveNode(&fileList->list);
264                 fileManager->taskList.size--;
265             } else {
266             }
267             isFound = NSTACKX_TRUE;
268             break;
269         }
270     }
271     if (PthreadMutexUnlock(&fileManager->taskList.lock) != 0) {
272         DFILE_LOGE(TAG, "pthread mutex unlock error");
273         *isErrorOccurred = NSTACKX_TRUE;
274         if (runStatus != FILE_LIST_STATUS_STOP) {
275             return NULL;
276         }
277     }
278 
279     if (isFound) {
280         return fileList;
281     }
282     return NULL;
283 }
284 
SetFileOffset(FileInfo * fileInfo,uint64_t fileOffset)285 int32_t SetFileOffset(FileInfo *fileInfo, uint64_t fileOffset)
286 {
287     if (fileInfo->fileOffset == fileOffset) {
288         return NSTACKX_EOK;
289     }
290 #ifdef BUILD_FOR_WINDOWS
291     if (fseek(fileInfo->fd, (int64_t)fileOffset, SEEK_SET) != 0) {
292         DFILE_LOGE(TAG, "fseek error");
293         return NSTACKX_EFAILED;
294     }
295 #else
296 #endif
297     fileInfo->fileOffset = fileOffset;
298     return NSTACKX_EOK;
299 }
CloseFile(FileInfo * fileInfo)300 void CloseFile(FileInfo *fileInfo)
301 {
302     if (fileInfo == NULL) {
303         return;
304     }
305     if (fileInfo->fd != NSTACKX_INVALID_FD) {
306 #ifdef BUILD_FOR_WINDOWS
307         if (fclose(fileInfo->fd) != 0) {
308             DFILE_LOGE(TAG, "fclose error");
309         }
310 #else
311         if (close(fileInfo->fd) != 0) {
312             DFILE_LOGE(TAG, "close error");
313         }
314 #endif
315         fileInfo->fileOffset = 0;
316         fileInfo->fd = NSTACKX_INVALID_FD;
317     }
318 }
319 
FileGetBytesTransferred(const FileInfo * fileInfo,uint8_t isSender)320 static uint64_t FileGetBytesTransferred(const FileInfo *fileInfo, uint8_t isSender)
321 {
322     uint64_t lastBlockSize;
323     uint64_t ret;
324     if (fileInfo == NULL || fileInfo->fileSize == 0) {
325         return 0;
326     }
327     if (isSender) {
328         if (fileInfo->maxSequenceSend < 0) {
329             return 0;
330         }
331         if (fileInfo->maxSequenceSend + 1 == fileInfo->totalBlockNum) {
332             ret = fileInfo->fileSize;
333         } else {
334             ret = ((uint64_t)fileInfo->standardBlockSize) * ((uint64_t)fileInfo->maxSequenceSend + 1);
335         }
336     } else {
337         if (!fileInfo->isEndBlockReceived) {
338             ret = ((uint64_t)fileInfo->standardBlockSize) * ((uint64_t)fileInfo->receivedBlockNum);
339         } else {
340             lastBlockSize = fileInfo->fileSize % ((uint64_t)fileInfo->standardBlockSize);
341             ret = ((uint64_t)fileInfo->standardBlockSize) * ((uint64_t)fileInfo->receivedBlockNum - 1) + lastBlockSize;
342         }
343     }
344 
345     if (ret > fileInfo->fileSize) {
346         ret = fileInfo->fileSize;
347     }
348     return ret;
349 }
350 
FileListGetBytesTransferred(const FileListTask * fileList,uint8_t isSender)351 uint64_t FileListGetBytesTransferred(const FileListTask *fileList, uint8_t isSender)
352 {
353     uint32_t i;
354     uint64_t ret = 0;
355     if ((fileList->tarFlag == NSTACKX_TRUE) && (isSender == NSTACKX_TRUE)) {
356         if (fileList->tarFileInfo.maxSequenceSend < 0) {
357             return 0;
358         }
359         if ((fileList->tarFileInfo.maxSequenceSend + 1) == (int32_t)fileList->tarFileInfo.totalBlockNum) {
360             ret = fileList->tarFileInfo.fileSize;
361         } else {
362             ret = ((uint64_t)fileList->tarFileInfo.standardBlockSize) *
363                   ((uint64_t)fileList->tarFileInfo.maxSequenceSend + 1);
364         }
365         return ret;
366     }
367 
368     for (i = 0; i < fileList->fileNum; i++) {
369         ret += FileGetBytesTransferred(&fileList->fileInfo[i], isSender);
370     }
371     return ret;
372 }
373 
ClearRecvFileList(FileListTask * fileList)374 static void ClearRecvFileList(FileListTask *fileList)
375 {
376     BlockFrame *blockFrame = NULL;
377     for (uint32_t i = 0; i < fileList->fileNum; i++) {
378         CloseFile(&fileList->fileInfo[i]);
379         free(fileList->fileInfo[i].fileName);
380         fileList->fileInfo[i].fileName = NULL;
381     }
382     SemDestroy(&fileList->semStop);
383     if (PthreadMutexLock(&fileList->recvBlockList.lock) != 0) {
384         DFILE_LOGE(TAG, "pthread mutex lock error");
385     }
386     while (fileList->recvBlockList.size > 0) {
387         blockFrame = (BlockFrame *)ListPopFront(&fileList->recvBlockList.head);
388         fileList->recvBlockList.size--;
389         if (blockFrame != NULL) {
390             free(blockFrame->fileDataFrame);
391             free(blockFrame);
392             blockFrame = NULL;
393         }
394     }
395     if (PthreadMutexUnlock(&fileList->recvBlockList.lock) != 0) {
396         DFILE_LOGE(TAG, "pthread mutex unlock error");
397     }
398     MutexListDestory(&fileList->recvBlockList);
399     while (!ListIsEmpty(&fileList->innerRecvBlockHead)) {
400         blockFrame = (BlockFrame *)ListPopFront(&fileList->innerRecvBlockHead);
401         if (blockFrame == NULL) {
402             continue;
403         }
404         free(blockFrame->fileDataFrame);
405         free(blockFrame);
406         blockFrame = NULL;
407     }
408     ClearCryptCtx(fileList->cryptPara.ctx);
409     (void)memset_s(fileList, sizeof(FileListTask), 0, sizeof(FileListTask));
410     free(fileList);
411 }
412 
GetFullFilePath(const char * path,const char * fileName)413 char *GetFullFilePath(const char *path, const char *fileName)
414 {
415     int32_t ret;
416     char *fullPath = NULL;
417     uint32_t fullPathLength;
418     if (path == NULL || fileName == NULL) {
419         return NULL;
420     }
421 
422     if ((CheckPathSeprator(path) == NSTACKX_TRUE) || (CheckFilenameSeprator(fileName) == NSTACKX_TRUE)) {
423         fullPathLength = (uint32_t)(strlen(path) + strlen(fileName) + sizeof('\0'));
424     } else {
425         fullPathLength = (uint32_t)(strlen(path) + sizeof(PATH_SEPARATOR) + strlen(fileName) + sizeof('\0'));
426     }
427 
428     fullPath = (char *)calloc(fullPathLength, sizeof(char));
429     if (fullPath == NULL) {
430         DFILE_LOGE(TAG, "full path calloc error");
431         return NULL;
432     }
433 
434     if ((CheckPathSeprator(path) == NSTACKX_TRUE) || (CheckFilenameSeprator(fileName) == NSTACKX_TRUE)) {
435         ret = sprintf_s(fullPath, fullPathLength, "%s%s", path, fileName);
436     } else {
437         ret = sprintf_s(fullPath, fullPathLength, "%s%c%s", path, PATH_SEPARATOR, fileName);
438     }
439 
440     if (ret == -1) {
441         DFILE_LOGE(TAG, "splice path and file name error");
442         free(fullPath);
443         return NULL;
444     }
445     return fullPath;
446 }
447 
ClearIncompleteRecvFiles(const char * path,FileListTask * fileList)448 static void ClearIncompleteRecvFiles(const char *path, FileListTask *fileList)
449 {
450     char *fullPath = NULL;
451     for (uint32_t i = 0; i < fileList->fileNum; i++) {
452         if (fileList->fileInfo[i].errCode == FILE_MANAGER_EOK &&
453             fileList->fileInfo[i].receivedBlockNum == fileList->fileInfo[i].totalBlockNum &&
454             fileList->stopType == FILE_LIST_TRANSFER_FINISH) {
455             continue;
456         }
457         CloseFile(&fileList->fileInfo[i]);
458         fullPath = GetFullFilePath(path, fileList->fileInfo[i].fileName);
459         if (fullPath != NULL) {
460             DFILE_LOGE(TAG, "going to remove incomplete file %s", fileList->fileInfo[i].fileName);
461             if (remove(fullPath) != 0) {
462                 DFILE_LOGE(TAG, "remove file failed. errno %d", errno);
463             }
464             free(fullPath);
465         }
466     }
467     return;
468 }
469 
FileInfoWriteInit(FileInfo * fileInfo,const char * path,uint8_t isTruncate)470 static void FileInfoWriteInit(FileInfo *fileInfo, const char *path, uint8_t isTruncate)
471 {
472     char *fullPath = GetFullFilePath(path, fileInfo->fileName);
473     if (fullPath == NULL) {
474         DFILE_LOGE(TAG, "Can't get full path");
475         fileInfo->errCode = FILE_MANAGER_ENOMEM;
476         return;
477     }
478     if (TestAndCreateDirectory(fullPath) != NSTACKX_EOK) {
479         free(fullPath);
480         fileInfo->errCode = FILE_MANAGER_FILE_EOTHER;
481         DFILE_LOGE(TAG, "create directory failed");
482         return;
483     }
484 #ifdef BUILD_FOR_WINDOWS
485     fileInfo->fd = fopen(fullPath, "wb");
486 #else
487     if (isTruncate) {
488         fileInfo->fd = open(fullPath, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
489     } else {
490         fileInfo->fd = open(fullPath, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
491     }
492 #endif
493     free(fullPath);
494     if (fileInfo->fd == NSTACKX_INVALID_FD) {
495         fileInfo->errCode = ConvertErrCode(errno);
496         DFILE_LOGE(TAG, "can't open file, error(%d)", errno);
497         return;
498     }
499     fileInfo->fileOffset = 0;
500 }
501 
WriteToFile(FileInfo * fileInfo,uint32_t blockSequence,uint16_t length,uint8_t * payLoad,FileListTask * fileList)502 static int32_t WriteToFile(FileInfo *fileInfo, uint32_t blockSequence, uint16_t length, uint8_t *payLoad,
503     FileListTask *fileList)
504 {
505     uint64_t fileOffset;
506     uint16_t ret = 0;
507     int32_t pRet = 0;
508     DFileSession *session = fileList->context;
509     if (fileInfo->fd == NSTACKX_INVALID_FD) {
510         FileInfoWriteInit(fileInfo, fileList->storagePath, NSTACKX_TRUE);
511         if (fileInfo->fd == NSTACKX_INVALID_FD) {
512             return NSTACKX_EFAILED;
513         }
514     }
515     if (fileInfo->fileSize == 0 || payLoad == NULL || length == 0) {
516         return NSTACKX_EOK;
517     }
518     fileOffset = ((uint64_t)fileInfo->standardBlockSize) * ((uint64_t)blockSequence);
519     fileOffset += fileInfo->startOffset;
520     if (SetFileOffset(fileInfo, fileOffset) != NSTACKX_EOK) {
521         fileInfo->errCode = FILE_MANAGER_FILE_EOTHER;
522         DFILE_LOGE(TAG, "set file offset failed");
523         return NSTACKX_EFAILED;
524     }
525     if (CapsNoRW(session)) {
526         ret = length;
527     } else {
528 #ifdef BUILD_FOR_WINDOWS
529         ret = (uint16_t)fwrite(payLoad, 1, length, fileInfo->fd);
530 #else
531         /* use pwrite because fseek have multi-thread issue in case of multi-path handle same file scenario */
532         pRet = (int32_t)pwrite(fileInfo->fd, payLoad, length, (int64_t)fileOffset);
533         if (pRet >= 0) {
534             ret = (uint16_t)pRet;
535         }
536 #endif
537     }
538     if ((pRet < 0) || (ret < length)) {
539         DFILE_LOGE(TAG, "fwrite error %d write %hu target %hu pRet:%d", GetErrno(), ret, length, pRet);
540         fileInfo->errCode = FILE_MANAGER_FILE_EOTHER;
541         return NSTACKX_EFAILED;
542     }
543     fileInfo->fileOffset += ret;
544     if (++fileInfo->receivedBlockNum == fileInfo->totalBlockNum) {
545         fileInfo->isEndBlockReceived = NSTACKX_TRUE;
546     }
547     return NSTACKX_EOK;
548 }
549 
GetFrameHearderInfo(FileListTask * fileList,BlockFrame * blockFrame,uint16_t * fileId,uint32_t * blockSequence,uint16_t * payloadLength)550 static int32_t GetFrameHearderInfo(FileListTask *fileList, BlockFrame *blockFrame, uint16_t *fileId,
551     uint32_t *blockSequence, uint16_t *payloadLength)
552 {
553     uint16_t transId, length;
554     transId = ntohs(blockFrame->fileDataFrame->header.transId);
555     *fileId = ntohs(blockFrame->fileDataFrame->fileId);
556     *blockSequence = ntohl(blockFrame->fileDataFrame->blockSequence);
557     length = ntohs(blockFrame->fileDataFrame->header.length);
558     if (transId != fileList->transId || *fileId > fileList->fileNum || *fileId == 0) {
559         DFILE_LOGE(TAG, "illegal transId (%hu) or fileId (%hu)", transId, *fileId);
560         return NSTACKX_EFAILED;
561     } else {
562         FileInfo *info = &fileList->fileInfo[*fileId - 1];
563         if (info->receivedBlockNum == info->totalBlockNum) {
564             DFILE_LOGI(TAG, "fileId (%hu) has already finished written totalBlockNum %u", *fileId, info->totalBlockNum);
565             *payloadLength = 0;
566             return NSTACKX_EOK;
567         }
568     }
569 
570     if (*blockSequence >= fileList->fileInfo[*fileId - 1].totalBlockNum ||
571         length <= sizeof(FileDataFrame) - sizeof(DFileFrameHeader) || length > NSTACKX_MAX_FRAME_SIZE) {
572         DFILE_LOGE(TAG, "block sequence or length is illegal");
573         fileList->errCode = FILE_MANAGER_LIST_EBLOCK;
574         return NSTACKX_EFAILED;
575     }
576 
577     *payloadLength = length + sizeof(DFileFrameHeader) - sizeof(FileDataFrame);
578     return NSTACKX_EOK;
579 }
580 
UpdateFileListRecvStatus(FileManager * fileManager,FileListTask * fileList,FileInfo * fileInfo,int32_t ret)581 static void UpdateFileListRecvStatus(FileManager *fileManager, FileListTask *fileList, FileInfo *fileInfo, int32_t ret)
582 {
583     if (ret != NSTACKX_EOK) {
584         DFILE_LOGE(TAG, "WriteToFile error:transId %u, fileId %u", fileList->transId, fileInfo->fileId);
585         CloseFile(fileInfo);
586         fileList->recvFileProcessed++;
587         NotifyFileMsg(fileList, fileInfo->fileId, FILE_MANAGER_RECEIVE_FAIL);
588         return;
589     }
590     if (fileInfo->receivedBlockNum < fileInfo->totalBlockNum) {
591         return;
592     }
593     CloseFile(fileInfo);
594     fileList->recvFileProcessed++;
595     if (fileList->recvFileProcessed == fileList->fileNum) {
596         NotifyFileManagerMsg(fileManager, FILE_MANAGER_IN_PROGRESS);
597     }
598     NotifyFileMsg(fileList, fileInfo->fileId, FILE_MANAGER_RECEIVE_SUCCESS);
599 }
600 
WriteSingleBlockFrame(FileManager * fileManager,FileListTask * fileList,BlockFrame * blockFrame)601 static int32_t WriteSingleBlockFrame(FileManager *fileManager, FileListTask *fileList, BlockFrame *blockFrame)
602 {
603     FileInfo *fileInfo = NULL;
604     uint16_t fileId, payloadLength;
605     uint32_t blockSequence;
606     uint8_t *payLoad = NULL;
607     uint8_t *buffer = NULL;
608     int32_t ret = NSTACKX_EFAILED;
609 
610     if (GetFrameHearderInfo(fileList, blockFrame, &fileId, &blockSequence, &payloadLength) != NSTACKX_EOK) {
611         fileList->errCode = FILE_MANAGER_LIST_EBLOCK;
612         return NSTACKX_EFAILED;
613     }
614 
615     if (payloadLength == 0) {
616         return NSTACKX_EOK;
617     }
618 
619     fileInfo = &fileList->fileInfo[fileId - 1];
620     if (fileInfo->errCode != FILE_MANAGER_EOK) {
621         return NSTACKX_EOK;
622     }
623 
624     payLoad = blockFrame->fileDataFrame->blockPayload;
625     uint32_t dataLen;
626     if (fileList->cryptPara.keylen > 0) {
627         buffer = (uint8_t *)calloc(payloadLength, 1);
628         if (buffer == NULL) {
629             fileList->errCode = FILE_MANAGER_ENOMEM;
630             return NSTACKX_EFAILED;
631         }
632         dataLen = AesGcmDecrypt(payLoad, payloadLength, &fileList->cryptPara, buffer, payloadLength);
633         if (dataLen == 0) {
634             fileInfo->errCode = FILE_MANAGER_FILE_EOTHER;
635             payLoad = NULL;
636             DFILE_LOGE(TAG, "data decrypt error");
637         } else {
638             payLoad = buffer;
639             payloadLength = (uint16_t)dataLen;
640         }
641     }
642     if (payLoad != NULL) {
643         ret = WriteToFile(fileInfo, blockSequence, payloadLength, payLoad, fileList);
644         if (ret == NSTACKX_EOK) {
645             fileManager->iowBytes += (uint64_t)payloadLength;
646         }
647     }
648     /*
649      * When all blocks are received, fsync should be called before refreshing the receivedBlockNum.
650      */
651     if (fileList->noSyncFlag == NSTACKX_FALSE && fileInfo->isEndBlockReceived) {
652         FileSync(fileInfo);
653     }
654     free(buffer);
655     UpdateFileListRecvStatus(fileManager, fileList, fileInfo, ret);
656     return ret;
657 }
658 
WriteBlockFrame(FileManager * fileManager,FileListTask * fileList)659 static int32_t WriteBlockFrame(FileManager *fileManager, FileListTask *fileList)
660 {
661     BlockFrame *blockFrame = NULL;
662     while (!ListIsEmpty(&fileList->innerRecvBlockHead)) {
663         if (CheckManager(fileManager) != NSTACKX_EOK || CheckFilelist(fileList) != NSTACKX_EOK) {
664             break;
665         }
666         blockFrame = (BlockFrame *)ListPopFront(&fileList->innerRecvBlockHead);
667         if (blockFrame == NULL) {
668             DFILE_LOGE(TAG, "get a null block");
669             continue;
670         }
671         if (WriteSingleBlockFrame(fileManager, fileList, blockFrame) != NSTACKX_EOK) {
672             DFILE_LOGE(TAG, "write block frame failed");
673             if (fileList->errCode != NSTACKX_EOK) {
674                 goto L_ERR_FILE_MANAGER;
675             }
676         }
677 
678         free(blockFrame->fileDataFrame);
679         free(blockFrame);
680         blockFrame = NULL;
681 
682         if (fileList->innerRecvSize > 0) {
683             fileList->innerRecvSize--;
684         }
685     }
686     return NSTACKX_EOK;
687 L_ERR_FILE_MANAGER:
688     free(blockFrame->fileDataFrame);
689     free(blockFrame);
690     return NSTACKX_EFAILED;
691 }
692 
SwapRecvBlockListHead(MutexList * mutexList,uint8_t * isEmpty,List * newHead,uint32_t * size)693 static int32_t SwapRecvBlockListHead(MutexList *mutexList, uint8_t *isEmpty, List *newHead, uint32_t *size)
694 {
695     List *front = NULL;
696     List *back = NULL;
697     *isEmpty = NSTACKX_FALSE;
698     if (PthreadMutexLock(&mutexList->lock) != 0) {
699         DFILE_LOGE(TAG, "pthread mutex lock error");
700         return NSTACKX_EFAILED;
701     }
702     if (mutexList->size == 0) {
703         *isEmpty = NSTACKX_TRUE;
704     } else {
705         front = mutexList->head.next;
706         back = mutexList->head.prev;
707         newHead->next = front;
708         newHead->prev = back;
709         front->prev = newHead;
710         back->next = newHead;
711         ListInitHead(&mutexList->head);
712         *size = mutexList->size;
713         mutexList->size = 0;
714     }
715     if (PthreadMutexUnlock(&mutexList->lock) != 0) {
716         DFILE_LOGE(TAG, "pthread mutex unlock error");
717         return NSTACKX_EFAILED;
718     }
719     return NSTACKX_EOK;
720 }
721 
GenerateAllEmptyFiles(FileListTask * fileList)722 static void GenerateAllEmptyFiles(FileListTask *fileList)
723 {
724     FileInfo *fileInfo = NULL;
725     int32_t ret;
726     for (uint32_t i = 0; i < fileList->fileNum; i++) {
727         if (fileList->fileInfo[i].fileSize > 0) {
728             continue;
729         }
730         fileInfo = &fileList->fileInfo[i];
731         ret = WriteToFile(fileInfo, 0, 0, NULL, fileList);
732         CloseFile(fileInfo);
733         fileList->recvFileProcessed++;
734 
735         if (ret != NSTACKX_EOK) {
736             DFILE_LOGE(TAG, "Create empty file error: transId %u, fileId %u", fileList->transId, fileInfo->fileId);
737             NotifyFileMsg(fileList, fileInfo->fileId, FILE_MANAGER_RECEIVE_FAIL);
738         } else {
739             DFILE_LOGI(TAG, "Create empty file successfully: transId %u, fileId %u", fileList->transId,
740                     fileInfo->fileId);
741             NotifyFileMsg(fileList, fileList->fileInfo[i].fileId, FILE_MANAGER_RECEIVE_SUCCESS);
742         }
743     }
744 }
745 
FileListRefreshFileRecvStatus(FileListTask * fileList)746 static void FileListRefreshFileRecvStatus(FileListTask *fileList)
747 {
748     if (fileList->recvFileProcessed >= fileList->fileNum) {
749         return;
750     }
751 
752     for (uint16_t i = 0; i < fileList->fileNum; i++) {
753         if (FileGetRecvStatus(&fileList->fileInfo[i]) == STATE_RECEIVE_ONGOING) {
754             fileList->fileInfo[i].errCode = FILE_MANAGER_FILE_EOTHER;
755             DFILE_LOGE(TAG, "file list will be stopped and set incompleted file %u to fail",
756                     fileList->fileInfo[i].fileId);
757             NotifyFileMsg(fileList, fileList->fileInfo[i].fileId, FILE_MANAGER_RECEIVE_FAIL);
758         }
759     }
760     fileList->recvFileProcessed = fileList->fileNum;
761 }
762 
RecvTaskProcess(FileManager * fileManager,FileListTask * fileList)763 static void RecvTaskProcess(FileManager *fileManager, FileListTask *fileList)
764 {
765     uint8_t isEmpty = NSTACKX_FALSE;
766 
767     while (NSTACKX_TRUE) {
768         if (CheckManager(fileManager) != NSTACKX_EOK || CheckFilelist(fileList) != NSTACKX_EOK ||
769             fileList->recvFileProcessed >= fileList->fileNum) {
770             break;
771         }
772 
773         if (!fileList->isRecvEmptyFilesCreated) {
774             GenerateAllEmptyFiles(fileList);
775             fileList->isRecvEmptyFilesCreated = NSTACKX_TRUE;
776             continue;
777         }
778 
779         SemWait(&fileList->semStop);
780         if (CheckManager(fileManager) != NSTACKX_EOK || CheckFilelist(fileList) != NSTACKX_EOK) {
781             break;
782         }
783         if (SwapRecvBlockListHead(&fileList->recvBlockList, &isEmpty, &fileList->innerRecvBlockHead,
784             &(fileList->innerRecvSize)) != NSTACKX_EOK) {
785             DFILE_LOGE(TAG, "Swap receive block list head error:transId %u", fileList->transId);
786             fileList->errCode = FILE_MANAGER_EMUTEX;
787             break;
788         }
789         if (isEmpty) {
790             if (fileList->allFileDataReceived) {
791                 fileList->dataWriteTimeoutCnt++;
792             }
793             if (fileList->dataWriteTimeoutCnt > NSTACKX_MAX_DATA_FWRITE_TIMEOUT_COUNT) {
794                 DFILE_LOGE(TAG, "some frames may lost or illegal and stop this file list");
795                 break;
796             }
797             continue;
798         } else {
799             fileList->dataWriteTimeoutCnt = 0;
800         }
801         if (WriteBlockFrame(fileManager, fileList) != NSTACKX_EOK) {
802             DFILE_LOGE(TAG, "WriteBlockFrame error");
803             continue;
804         }
805     }
806     FileListRefreshFileRecvStatus(fileList);
807     if (fileList->errCode != FILE_MANAGER_EOK) {
808         NotifyFileListMsg(fileList, FILE_MANAGER_RECEIVE_FAIL);
809         DFILE_LOGE(TAG, "recv task process failed");
810     }
811 }
812 
ClearFileList(FileManager * fileManager,FileListTask * fileList)813 static void ClearFileList(FileManager *fileManager, FileListTask *fileList)
814 {
815     if (fileManager->isSender) {
816         ClearSendFileList(fileManager, fileList);
817     } else {
818         ClearIncompleteRecvFiles(fileList->storagePath, fileList);
819         ClearRecvFileList(fileList);
820     }
821 }
822 
BindFileManagerThreadToTargetCpu(FileManager * fileManager,uint32_t idx)823 static void BindFileManagerThreadToTargetCpu(FileManager *fileManager, uint32_t idx)
824 {
825     int32_t cpu;
826     int32_t cpus = GetCpuNum();
827     if (cpus >= FIRST_CPU_NUM_LEVEL) {
828         return;
829     } else if (cpus >= SECOND_CPU_NUM_LEVEL) {
830         if (fileManager->isSender) {
831             cpu = CPU_IDX_0;
832         } else {
833             cpu = CPU_IDX_2 + (int32_t)idx % FILE_MANAGER_THREADS_BINDED_CPU_NUM;
834         }
835     } else if (cpus >= THIRD_CPU_NUM_LEVEL) {
836         if (fileManager->isSender) {
837             cpu = CPU_IDX_0;
838         } else {
839             cpu = CPU_IDX_1;
840         }
841     } else {
842         return;
843     }
844     StartThreadBindCore(cpu);
845 }
846 
847 typedef struct {
848     FileManager *fileManager;
849     uint32_t threadIdx;
850 } FileManagerThreadCtx;
851 
SetIOThreadName(uint32_t threadIdx)852 static void SetIOThreadName(uint32_t threadIdx)
853 {
854     char name[MAX_THREAD_NAME_LEN] = {0};
855     if (sprintf_s(name, sizeof(name), "%s%u", DFFILE_IO_THREAD_NAME_PREFIX, threadIdx) < 0) {
856         DFILE_LOGE(TAG, "sprintf io thead name failed");
857     }
858     SetThreadName(name);
859     DFILE_LOGI(TAG, "IO thread %u start", threadIdx);
860 }
861 
DoTaskProcess(FileManager * fileManager,FileListTask * fileList)862 static void DoTaskProcess(FileManager *fileManager, FileListTask *fileList)
863 {
864     if (fileManager->isSender) {
865         SendTaskProcess(fileManager, fileList);
866     } else {
867         RecvTaskProcess(fileManager, fileList);
868     }
869 }
870 
FileManagerPre(FileManager * fileManager,uint32_t threadIdx)871 static void FileManagerPre(FileManager *fileManager, uint32_t threadIdx)
872 {
873     SetIOThreadName(threadIdx);
874     SetMaximumPriorityForThread();
875     SetTidToBindInfo(fileManager->context, threadIdx);
876 }
877 
AfterTaskProcess(FileManager * fileManager,FileListTask * fileList)878 static void AfterTaskProcess(FileManager *fileManager, FileListTask *fileList)
879 {
880     fileList->isOccupied = NSTACKX_FALSE;
881     SemPost(&fileManager->semTaskListNotEmpty);
882 }
883 
FileManagerThread(void * arg)884 static void *FileManagerThread(void *arg)
885 {
886     FileManagerThreadCtx *ctx = (FileManagerThreadCtx *)arg;
887     FileManager *fileManager = ctx->fileManager;
888     uint32_t threadIdx = ctx->threadIdx;
889     free(ctx);
890     uint8_t isErrorOccurred = NSTACKX_FALSE;
891     FileListTask *fileList = NULL;
892     uint8_t isBind = NSTACKX_FALSE;
893     FileManagerPre(fileManager, threadIdx);
894     while (fileManager->runStatus == FILE_MANAGE_RUN) {
895         SemWait(&fileManager->semTaskListNotEmpty);
896         if (fileManager->runStatus != FILE_MANAGE_RUN) {
897             break;
898         }
899         uint8_t isStopTaskDetached = NSTACKX_FALSE;
900         fileList = PrepareOneTaskByStatus(fileManager, FILE_LIST_STATUS_STOP, &isErrorOccurred);
901         if (isErrorOccurred) {
902             fileManager->errCode = FILE_MANAGER_EMUTEX;
903             NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
904             DFILE_LOGE(TAG, "error occuerd when get stop file list");
905         }
906         if (fileList != NULL) {
907             isStopTaskDetached = NSTACKX_TRUE;
908             DFILE_LOGI(TAG, "Thread %u is clearing fileList %u", threadIdx, fileList->transId);
909             ClearFileList(fileManager, fileList);
910         }
911         if (isErrorOccurred || isStopTaskDetached) {
912             continue;
913         }
914 
915         fileList = PrepareOneTaskByStatus(fileManager, FILE_LIST_STATUS_IDLE, &isErrorOccurred);
916         if (isErrorOccurred) {
917             fileManager->errCode = FILE_MANAGER_EMUTEX;
918             NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
919             DFILE_LOGE(TAG, "error occuerd when get idle file list");
920             continue;
921         }
922         if (fileList == NULL || fileList->errCode != FILE_MANAGER_EOK) {
923             continue;
924         }
925         DFILE_LOGI(TAG, "Thread %u is processing for fileList %u", threadIdx, fileList->transId);
926         if (isBind == NSTACKX_FALSE && fileManager->transFlag == NSTACKX_TRUE) {
927             BindFileManagerThreadToTargetCpu(fileManager, threadIdx);
928             isBind = NSTACKX_TRUE;
929         }
930         DoTaskProcess(fileManager, fileList);
931         AfterTaskProcess(fileManager, fileList);
932     }
933     return NULL;
934 }
935 
WakeAllThread(FileManager * fileManager)936 static void WakeAllThread(FileManager *fileManager)
937 {
938     uint32_t i;
939     List *list = NULL;
940     FileListTask *fileList = NULL;
941     SendBlockFrameListPara *para = NULL;
942     if (PthreadMutexLock(&fileManager->taskList.lock) != 0) {
943         DFILE_LOGE(TAG, "pthread mutex lock error");
944         return;
945     }
946     LIST_FOR_EACH(list, &fileManager->taskList.head) {
947         fileList = (FileListTask *)list;
948         SemPost(&fileList->semStop);
949         para = &fileManager->sendBlockFrameListPara[fileList->bindedSendBlockListIdx];
950         SemPost(&para->semBlockListNotFull);
951     }
952     if (PthreadMutexUnlock(&fileManager->taskList.lock) != 0) {
953         DFILE_LOGE(TAG, "pthread mutex unlock error");
954         return;
955     }
956     for (i = 0; i < NSTACKX_FILE_MANAGER_THREAD_NUM; i++) {
957         SemPost(&fileManager->semTaskListNotEmpty);
958     }
959 }
960 
StopFileManagerThreads(FileManager * fileManager)961 void StopFileManagerThreads(FileManager *fileManager)
962 {
963     uint32_t i;
964     uint32_t tryNum;
965 
966     if (fileManager == NULL || fileManager->runStatus == FILE_MANAGE_DESTROY) {
967         return;
968     }
969 
970     fileManager->runStatus = FILE_MANAGE_DESTROY;
971     for (tryNum = 0; tryNum < THREAD_QUIT_TRY_TIMES; tryNum++) {
972         WakeAllThread(fileManager);
973     }
974 
975     for (i = 0; i < NSTACKX_FILE_MANAGER_THREAD_NUM; i++) {
976         PthreadJoin(fileManager->fileManagerTid[i], NULL);
977         DFILE_LOGI(TAG, "Total thread %u: %u quit", NSTACKX_FILE_MANAGER_THREAD_NUM, i + 1);
978         fileManager->fileManagerTid[i] = INVALID_TID;
979     }
980 }
981 
CreateFMThread(FileManager * fileManager)982 static int32_t CreateFMThread(FileManager *fileManager)
983 {
984     uint32_t i;
985     FileManagerThreadCtx *ctx = NULL;
986 
987     for (i = 0; i < NSTACKX_FILE_MANAGER_THREAD_NUM; i++) {
988         ctx = (FileManagerThreadCtx *)calloc(1, sizeof(FileManagerThreadCtx));
989         if (ctx == NULL) {
990             DFILE_LOGE(TAG, "the %u ctx create failed", i + 1);
991             goto L_ERR_FILEMANAGER;
992         }
993         ctx->fileManager = fileManager;
994         ctx->threadIdx = i;
995         if ((PthreadCreate(&fileManager->fileManagerTid[i], NULL, FileManagerThread, ctx)) != 0) {
996             DFILE_LOGE(TAG, "the %u thread create failed", i + 1);
997             free(ctx);
998             goto L_ERR_FILEMANAGER;
999         }
1000     }
1001     return NSTACKX_EOK;
1002 
1003 L_ERR_FILEMANAGER:
1004     fileManager->runStatus = FILE_MANAGE_DESTROY;
1005     for (int32_t j = 0; j < NSTACKX_FILE_MANAGER_THREAD_NUM; j++) {
1006         SemPost(&fileManager->semTaskListNotEmpty);
1007     }
1008     while (i > 0) {
1009         PthreadJoin(fileManager->fileManagerTid[i - 1], NULL);
1010         i--;
1011     }
1012     return NSTACKX_EFAILED;
1013 }
1014 
GetStandardBlockSize(const FileManager * fileManager)1015 uint16_t GetStandardBlockSize(const FileManager *fileManager)
1016 {
1017     uint32_t standardBlockSize;
1018 
1019     if (fileManager->maxFrameLength <= offsetof(FileDataFrame, blockPayload)) {
1020         return 0;
1021     }
1022 
1023     standardBlockSize = fileManager->maxFrameLength - offsetof(FileDataFrame, blockPayload);
1024 
1025     if (fileManager->keyLen > 0) {
1026         if (standardBlockSize <= GCM_ADDED_LEN) {
1027             return 0;
1028         }
1029         standardBlockSize -= GCM_ADDED_LEN;
1030     }
1031     return (uint16_t)standardBlockSize;
1032 }
1033 
SetCryptPara(FileListTask * fileList,const uint8_t key[],uint32_t keyLen)1034 int32_t SetCryptPara(FileListTask *fileList, const uint8_t key[], uint32_t keyLen)
1035 {
1036     uint32_t aadLen;
1037 
1038     if (CapsChaCha(fileList->context)) {
1039         fileList->cryptPara.cipherType = CIPHER_CHACHA;
1040     } else {
1041         fileList->cryptPara.cipherType = CIPHER_AES_GCM;
1042         keyLen = AES_128_KEY_LENGTH;
1043     }
1044 
1045     if (memcpy_s(fileList->cryptPara.key, sizeof(fileList->cryptPara.key), key, keyLen) != EOK) {
1046         DFILE_LOGE(TAG, "memcpy key failed");
1047         return NSTACKX_EFAILED;
1048     }
1049     fileList->cryptPara.keylen = keyLen;
1050 
1051     aadLen = sizeof(fileList->cryptPara.aad);
1052     if (memset_s(fileList->cryptPara.aad, aadLen, GCM_AAD_CHAR, aadLen) != EOK) {
1053         DFILE_LOGE(TAG, "memset aad failed");
1054         return NSTACKX_EFAILED;
1055     }
1056     fileList->cryptPara.aadLen = aadLen;
1057     fileList->cryptPara.ctx = CreateCryptCtx();
1058     if (fileList->cryptPara.ctx == NULL) {
1059         DFILE_LOGE(TAG, "failed to create crypt ctx");
1060         return NSTACKX_EFAILED;
1061     }
1062     DFILE_LOGI(TAG, "set encrypt/decrypt type is %d", fileList->cryptPara.cipherType);
1063     return NSTACKX_EOK;
1064 }
1065 
1066 /*
1067  * Note that this interface is only called by dfile main thread now. If other thread wants to call it, must be very
1068  * careful about thread-safety.
1069  */
GetFileListById(MutexList * taskList,uint16_t transId,uint8_t * isErrorOccurred)1070 FileListTask *GetFileListById(MutexList *taskList, uint16_t transId, uint8_t *isErrorOccurred)
1071 {
1072     List *list = NULL;
1073     FileListTask *fileList = NULL;
1074     uint8_t isFound = NSTACKX_FALSE;
1075     if (isErrorOccurred != NULL) {
1076         *isErrorOccurred = NSTACKX_FALSE;
1077     }
1078     if (taskList == NULL) {
1079         return NULL;
1080     }
1081     if (PthreadMutexLock(&taskList->lock) != 0) {
1082         DFILE_LOGE(TAG, "pthread mutex lock error");
1083         goto L_ERR_FILE_MANAGER;
1084     }
1085     LIST_FOR_EACH(list, &taskList->head) {
1086         fileList = (FileListTask *)list;
1087         /* If the target filelist has been stopped, it will not be accessible by other thread. */
1088         if (fileList->transId == transId && fileList->runStatus != FILE_LIST_STATUS_STOP) {
1089             isFound = NSTACKX_TRUE;
1090             break;
1091         }
1092     }
1093     if (PthreadMutexUnlock(&taskList->lock) != 0) {
1094         DFILE_LOGE(TAG, "pthread mutex unlock error");
1095         goto L_ERR_FILE_MANAGER;
1096     }
1097     if (isFound) {
1098         return fileList;
1099     }
1100     return NULL;
1101 L_ERR_FILE_MANAGER:
1102     if (isErrorOccurred != NULL) {
1103         *isErrorOccurred = NSTACKX_TRUE;
1104     }
1105     return NULL;
1106 }
1107 
GetFileBlockListSize(MutexList * taskList,uint32_t * recvListAllSize,uint32_t * recvInnerAllSize)1108 int32_t GetFileBlockListSize(MutexList *taskList, uint32_t *recvListAllSize, uint32_t *recvInnerAllSize)
1109 {
1110     List *list = NULL;
1111     FileListTask *fileList = NULL;
1112     uint32_t sum = 0;
1113     uint32_t innerSum = 0;
1114 
1115     if (taskList == NULL) {
1116         *recvListAllSize = 0;
1117         *recvInnerAllSize = 0;
1118         return NSTACKX_EOK;
1119     }
1120     if (PthreadMutexLock(&taskList->lock) != 0) {
1121         DFILE_LOGE(TAG, "pthread mutex lock error");
1122         goto L_ERR_FILE_MANAGER;
1123     }
1124     LIST_FOR_EACH(list, &taskList->head) {
1125         fileList = (FileListTask *)list;
1126         /* If the target filelist has been stopped, it will not be accessible by other thread. */
1127         if (fileList->runStatus != FILE_LIST_STATUS_STOP) {
1128             sum += fileList->recvBlockList.size;
1129             innerSum += fileList->innerRecvSize;
1130         }
1131     }
1132     if (PthreadMutexUnlock(&taskList->lock) != 0) {
1133         DFILE_LOGE(TAG, "pthread mutex unlock error");
1134         goto L_ERR_FILE_MANAGER;
1135     }
1136     *recvListAllSize = sum;
1137     *recvInnerAllSize = innerSum;
1138     return NSTACKX_EOK;
1139 L_ERR_FILE_MANAGER:
1140     return NSTACKX_EFAILED;
1141 }
1142 
RefreshBytesTransFerred(FileManager * fileManager,BlockFrame * block)1143 void RefreshBytesTransFerred(FileManager *fileManager, BlockFrame *block)
1144 {
1145     uint32_t len = 0;
1146     DFileFrameHeader *header = NULL;
1147 
1148     while (block) {
1149         header = (DFileFrameHeader *)(void *)block->fileDataFrame;
1150         len += ntohs(header->length) + sizeof(DFileFrameHeader);
1151         len -= sizeof(FileDataFrame);
1152         block = (BlockFrame *)(void *)(block->list.next);
1153     }
1154     if (len == 0) {
1155         return;
1156     }
1157     if (NSTACKX_ATOM_ADD_RETURN(&fileManager->bytesTransferredInCurPeriod, (int32_t)len) >=
1158         (NSTACKX_MEGA_BYTES * MEGA_BYTES_TRANSFER_NOTICE_THRESHOLD)) {
1159         NSTACKX_ATOM_SET(&(fileManager->bytesTransferredInCurPeriod), 0);
1160         NotifyFileManagerMsg(fileManager, FILE_MANAGER_IN_PROGRESS);
1161     }
1162 }
1163 
FileManagerStopTask(FileManager * fileManager,uint16_t transId,TaskStopType stopType)1164 int32_t FileManagerStopTask(FileManager *fileManager, uint16_t transId, TaskStopType stopType)
1165 {
1166     FileListTask *fileList = NULL;
1167     List *list = NULL;
1168     uint8_t isFound = NSTACKX_FALSE;
1169     if (fileManager == NULL) {
1170         return NSTACKX_EINVAL;
1171     }
1172     if (PthreadMutexLock(&fileManager->taskList.lock) != 0) {
1173         DFILE_LOGE(TAG, "pthread mutex lock error");
1174         goto L_ERR_FILE_MANAGER;
1175     }
1176     LIST_FOR_EACH(list, &fileManager->taskList.head) {
1177         fileList = (FileListTask *)list;
1178         if (fileList != NULL && fileList->transId == transId) {
1179             isFound = NSTACKX_TRUE;
1180             break;
1181         }
1182     }
1183     if (isFound) {
1184         if (stopType == FILE_LIST_TRANSFER_FINISH) {
1185             fileManager->stoppedTasksBytesTransferred += fileList->totalBytes;
1186         } else {
1187             fileManager->stoppedTasksBytesTransferred += FileListGetBytesTransferred(fileList, fileManager->isSender);
1188         }
1189         if (fileManager->isSender && fileList->bindedSendBlockListIdx < NSTACKX_MAX_CLIENT_SEND_THREAD_NUM) {
1190             if (fileManager->sendBlockFrameListPara[fileList->bindedSendBlockListIdx].bandingTransNum > 0) {
1191                 fileManager->sendBlockFrameListPara[fileList->bindedSendBlockListIdx].bandingTransNum--;
1192             }
1193         }
1194         fileList->stopType = stopType;
1195         fileList->runStatus = FILE_LIST_STATUS_STOP;
1196         SemPost(&fileList->semStop);
1197         SemPost(&fileManager->semTaskListNotEmpty);
1198     }
1199 
1200     if (PthreadMutexUnlock(&fileManager->taskList.lock) != 0) {
1201         DFILE_LOGE(TAG, "pthread mutex unlock error");
1202         goto L_ERR_FILE_MANAGER;
1203     }
1204 
1205     if (isFound) {
1206         return NSTACKX_EOK;
1207     }
1208     DFILE_LOGE(TAG, "can't find target trans %u to stop", transId);
1209     return NSTACKX_EFAILED;
1210 L_ERR_FILE_MANAGER:
1211     fileManager->errCode = FILE_MANAGER_EMUTEX;
1212     NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1213     return NSTACKX_EFAILED;
1214 }
1215 
FileManagerSetMaxFrameLength(FileManager * fileManager,uint16_t maxFrameLength)1216 int32_t FileManagerSetMaxFrameLength(FileManager *fileManager, uint16_t maxFrameLength)
1217 {
1218     uint32_t standardDataLength;
1219     if (CheckManager(fileManager) != NSTACKX_EOK) {
1220         DFILE_LOGE(TAG, "Invalid input");
1221         return NSTACKX_EINVAL;
1222     }
1223     if (maxFrameLength <= offsetof(FileDataFrame, blockPayload) || maxFrameLength > NSTACKX_MAX_FRAME_SIZE) {
1224         DFILE_LOGE(TAG, "max frame length is illegal");
1225         return NSTACKX_EINVAL;
1226     }
1227     if (fileManager->keyLen > 0) {
1228         standardDataLength = maxFrameLength - offsetof(FileDataFrame, blockPayload);
1229         if (standardDataLength <= GCM_ADDED_LEN) {
1230             DFILE_LOGE(TAG, "max frame length is too small");
1231             return NSTACKX_EINVAL;
1232         }
1233     }
1234 
1235     /* different peerInfo->dataFrameSize in two connection, choose a small one for fileManager */
1236     if (fileManager->maxFrameLength == 0) {
1237         fileManager->maxFrameLength = maxFrameLength;
1238         return NSTACKX_EOK;
1239     }
1240 
1241     if (fileManager->maxFrameLength > maxFrameLength) {
1242         fileManager->maxFrameLength = maxFrameLength;
1243     }
1244 
1245     return NSTACKX_EOK;
1246 }
1247 
FileManagerSetRecvParaWithConnType(FileManager * fileManager,uint16_t connectType)1248 int32_t FileManagerSetRecvParaWithConnType(FileManager *fileManager, uint16_t connectType)
1249 {
1250     int32_t ret = NSTACKX_EOK;
1251     if (CheckReceiverManager(fileManager) != NSTACKX_EOK) {
1252         DFILE_LOGE(TAG, "Invalid input");
1253         return NSTACKX_EINVAL;
1254     }
1255     if (connectType == CONNECT_TYPE_WLAN) {
1256         fileManager->maxRecvBlockListSize = NSTACKX_WLAN_RECV_BLOCK_QUEUE_MAX_LEN * NSTACKX_FILE_MANAGER_THREAD_NUM;
1257     } else if (connectType == CONNECT_TYPE_P2P) {
1258         fileManager->maxRecvBlockListSize = NSTACKX_P2P_RECV_BLOCK_QUEUE_MAX_LEN * NSTACKX_FILE_MANAGER_THREAD_NUM;
1259     } else {
1260         DFILE_LOGE(TAG, "Invalid connect type");
1261         ret = NSTACKX_EFAILED;
1262     }
1263     DFILE_LOGI(TAG, "connect type is %u and max recv list size is %u", connectType, fileManager->maxRecvBlockListSize);
1264     return ret;
1265 }
1266 
FileManagerSetWritePath(FileManager * fileManager,const char * storagePath)1267 int32_t FileManagerSetWritePath(FileManager *fileManager, const char *storagePath)
1268 {
1269     if (CheckReceiverManager(fileManager) != NSTACKX_EOK || storagePath == NULL) {
1270         DFILE_LOGE(TAG, "Invalid input");
1271         return NSTACKX_EINVAL;
1272     }
1273 
1274     if (fileManager->typedPathNum > 0) {
1275         DFILE_LOGE(TAG, "typed storage paths has been set and can't set the common storage path");
1276         return NSTACKX_EINVAL;
1277     }
1278 
1279     fileManager->commonStoragePath = realpath(storagePath, NULL);
1280     if (fileManager->commonStoragePath == NULL) {
1281         DFILE_LOGE(TAG, "can't get canonicalized absolute pathname, error(%d)", errno);
1282         return NSTACKX_EFAILED;
1283     }
1284 
1285     if (!IsAccessiblePath(storagePath, W_OK, S_IFDIR)) {
1286         DFILE_LOGE(TAG, "storage path is not a valid writable folder");
1287         free(fileManager->commonStoragePath);
1288         fileManager->commonStoragePath = NULL;
1289         return NSTACKX_EFAILED;
1290     }
1291 
1292     return NSTACKX_EOK;
1293 }
1294 
FileManagerSetWritePathList(FileManager * fileManager,char * path[],uint16_t * pathType,uint16_t pathNum)1295 int32_t FileManagerSetWritePathList(FileManager *fileManager, char *path[], uint16_t *pathType, uint16_t pathNum)
1296 {
1297     if (CheckReceiverManager(fileManager) != NSTACKX_EOK || path == NULL || pathType == NULL || pathNum == 0 ||
1298         pathNum > NSTACKX_MAX_STORAGE_PATH_NUM) {
1299         DFILE_LOGE(TAG, "Invalid input");
1300         return NSTACKX_EINVAL;
1301     }
1302 
1303     if (fileManager->commonStoragePath != NULL) {
1304         DFILE_LOGE(TAG, "common storage paths has been set and can't set the typed storage path");
1305         return NSTACKX_EFAILED;
1306     }
1307 
1308     for (uint16_t i = 0; i < pathNum; i++) {
1309         fileManager->pathList[i].storagePath = path[i];
1310         fileManager->pathList[i].pathType = pathType[i];
1311         DFILE_LOGI(TAG, "the %uth path, type %u", i, fileManager->pathList[i].pathType);
1312     }
1313     fileManager->typedPathNum = pathNum;
1314     return NSTACKX_EOK;
1315 }
1316 
AtomicParameterInit(FileManager * fileManager)1317 static int32_t AtomicParameterInit(FileManager *fileManager)
1318 {
1319     uint32_t i = 0;
1320     SendBlockFrameListPara *para = NULL;
1321     uint32_t sendListSize = fileManager->maxSendBlockListSize;
1322 
1323     if (SemInit(&fileManager->semTaskListNotEmpty, 0, 0) != 0) {
1324         DFILE_LOGE(TAG, "semTaskListNotEmpty SemInit error");
1325         return NSTACKX_EFAILED;
1326     }
1327 
1328     if (fileManager->isSender) {
1329         for (i = 0; i < fileManager->sendFrameListNum; i++) {
1330             para = &fileManager->sendBlockFrameListPara[i];
1331             if (SemInit(&para->semBlockListNotFull, 0, sendListSize) != 0) {
1332                 DFILE_LOGE(TAG, "semTaskListNotEmpty SemInit error");
1333                 goto L_ERR_FILE_MANAGER;
1334             }
1335         }
1336     }
1337     return NSTACKX_EOK;
1338 L_ERR_FILE_MANAGER:
1339     SemDestroy(&fileManager->semTaskListNotEmpty);
1340     while (i > 0) {
1341         para = &fileManager->sendBlockFrameListPara[i - 1];
1342         SemDestroy(&para->semBlockListNotFull);
1343         i--;
1344     }
1345     return NSTACKX_EFAILED;
1346 }
1347 
AtomicParameterDestory(FileManager * fileManager)1348 static void AtomicParameterDestory(FileManager *fileManager)
1349 {
1350     SemDestroy(&fileManager->semTaskListNotEmpty);
1351     if (fileManager->isSender) {
1352         for (uint32_t i = 0; i < fileManager->sendFrameListNum; i++) {
1353             SemDestroy(&fileManager->sendBlockFrameListPara[i].semBlockListNotFull);
1354         }
1355     }
1356 }
1357 
InitAllCacheList(FileManager * fileManager)1358 static int32_t InitAllCacheList(FileManager *fileManager)
1359 {
1360     if (MutexListInit(&fileManager->taskList, NSTACKX_MAX_PROCESSING_TASK_NUM) != NSTACKX_EOK) {
1361         DFILE_LOGE(TAG, "taskList InitList error");
1362         return NSTACKX_EFAILED;
1363     }
1364 
1365     if (fileManager->isSender) {
1366         if (InitSendBlockLists(fileManager) != NSTACKX_EOK) {
1367             MutexListDestory(&fileManager->taskList);
1368             DFILE_LOGE(TAG, "sendBlockFrameList InitList error");
1369             return NSTACKX_EFAILED;
1370         }
1371     }
1372     return NSTACKX_EOK;
1373 }
1374 
FileManagerInit(FileManager * fileManager,FileManagerMsgPara * msgPara,const uint8_t * key,uint32_t keyLen,uint16_t connType)1375 static int32_t FileManagerInit(FileManager *fileManager, FileManagerMsgPara *msgPara, const uint8_t *key,
1376                                uint32_t keyLen, uint16_t connType)
1377 {
1378     fileManager->runStatus = FILE_MANAGE_RUN;
1379     fileManager->errCode = FILE_MANAGER_EOK;
1380     fileManager->transFlag = NSTACKX_FALSE;
1381     if (fileManager->isSender) {
1382         fileManager->sendFrameListNum = GetSendListNum();
1383         fileManager->maxSendBlockListSize = GetMaxSendListSize(connType);
1384         if (fileManager->maxSendBlockListSize == 0 || fileManager->sendFrameListNum == 0) {
1385             DFILE_LOGE(TAG, "can't get valid send frame list num or size");
1386             return NSTACKX_EFAILED;
1387         }
1388         DFILE_LOGI(TAG, "connect type is %u and send frame list number is %u max send list size is %u",
1389              connType, fileManager->sendFrameListNum, fileManager->maxSendBlockListSize);
1390     }
1391     if (IsEpollDescValid(msgPara->epollfd) && msgPara->msgReceiver != NULL) {
1392         fileManager->msgReceiver = msgPara->msgReceiver;
1393         fileManager->context = msgPara->context;
1394         fileManager->epollfd = msgPara->epollfd;
1395         fileManager->eventNodeChain = msgPara->eventNodeChain;
1396     }
1397 
1398     if (keyLen > 0) {
1399         if ((keyLen != AES_128_KEY_LENGTH && keyLen != CHACHA20_KEY_LENGTH) || key == NULL ||
1400             memcpy_s(fileManager->key, sizeof(fileManager->key), key, keyLen) != EOK) {
1401             DFILE_LOGE(TAG, "can't get valid key info.");
1402             return NSTACKX_EFAILED;
1403         }
1404         fileManager->keyLen = keyLen;
1405     }
1406     return NSTACKX_EOK;
1407 }
1408 
FileManagerCreate(uint8_t isSender,FileManagerMsgPara * msgPara,const uint8_t * key,uint32_t keyLen,uint16_t connType)1409 FileManager *FileManagerCreate(uint8_t isSender, FileManagerMsgPara *msgPara, const uint8_t *key,
1410                                uint32_t keyLen, uint16_t connType)
1411 {
1412     FileManager *fileManager = NULL;
1413     if (isSender && (connType != CONNECT_TYPE_P2P && connType != CONNECT_TYPE_WLAN)) {
1414         DFILE_LOGE(TAG, "connType for sender is illagal");
1415         return NULL;
1416     }
1417     fileManager = (FileManager *)calloc(1, sizeof(FileManager));
1418     if (fileManager == NULL) {
1419         DFILE_LOGE(TAG, "fileManager calloc error");
1420         return NULL;
1421     }
1422     fileManager->isSender = isSender;
1423     if (FileManagerInit(fileManager, msgPara, key, keyLen, connType) != NSTACKX_EOK) {
1424         (void)memset_s(fileManager, sizeof(FileManager), 0, sizeof(FileManager));
1425         free(fileManager);
1426         return NULL;
1427     }
1428 
1429     if (InitAllCacheList(fileManager) != NSTACKX_EOK) {
1430         (void)memset_s(fileManager, sizeof(FileManager), 0, sizeof(FileManager));
1431         free(fileManager);
1432         return NULL;
1433     }
1434 
1435     if (AtomicParameterInit(fileManager) != NSTACKX_EOK) {
1436         goto L_ERR_FILE_MANAGER;
1437     }
1438 
1439     if (CreateFMThread(fileManager) != NSTACKX_EOK) {
1440         AtomicParameterDestory(fileManager);
1441         goto L_ERR_FILE_MANAGER;
1442     }
1443 
1444     return fileManager;
1445 
1446 L_ERR_FILE_MANAGER:
1447     MutexListDestory(&fileManager->taskList);
1448     if (fileManager->isSender) {
1449         for (uint32_t i = 0; i < fileManager->sendFrameListNum; i++) {
1450             MutexListDestory(&fileManager->sendBlockFrameListPara[i].sendBlockFrameList);
1451             fileManager->sendBlockFrameListPara[i].sendRetranListTail = NULL;
1452         }
1453     }
1454     (void)memset_s(fileManager, sizeof(FileManager), 0, sizeof(FileManager));
1455     free(fileManager);
1456     return NULL;
1457 }
1458 
AddRecvFileInfo(FileBaseInfo * fileBasicInfo,FileListTask * fmFileList,uint16_t standardBlockSize)1459 static int32_t AddRecvFileInfo(FileBaseInfo *fileBasicInfo, FileListTask *fmFileList, uint16_t standardBlockSize)
1460 {
1461     uint32_t i;
1462     char *fileName = NULL;
1463     FileInfo *fileInfo = NULL;
1464     for (i = 0; i < fmFileList->fileNum; i++) {
1465         if (fileBasicInfo[i].fileName == NULL || !IsFileNameLegal(fileBasicInfo[i].fileName)) {
1466             DFILE_LOGE(TAG, "the %uth input fileName is NULL", i);
1467             goto L_ERR_FILE_MANAGER;
1468         }
1469         fileName = fileBasicInfo[i].fileName;
1470         fileInfo = &fmFileList->fileInfo[i];
1471         fileInfo->fileName = (char *)calloc(strlen(fileName) + 1, sizeof(char));
1472         if (fileInfo->fileName == NULL) {
1473             DFILE_LOGE(TAG, "fileName calloc error");
1474             goto L_ERR_FILE_MANAGER;
1475         }
1476 
1477         if (strcpy_s(fileInfo->fileName, strlen(fileName) + 1, fileName) != NSTACKX_EOK) {
1478             DFILE_LOGE(TAG, "%uth fileName copy failed", i);
1479             goto L_ERR_FILE_MANAGER;
1480         }
1481 
1482         fileInfo->fileSize = fileBasicInfo[i].fileSize;
1483         fileInfo->startOffset = fileBasicInfo[i].startOffset;
1484         fileInfo->fileId = fileBasicInfo[i].fileId;
1485         fileInfo->standardBlockSize = standardBlockSize;
1486         fileInfo->totalBlockNum = (uint32_t)(fileInfo->fileSize / standardBlockSize);
1487         if (fileInfo->fileSize % standardBlockSize != 0) {
1488             fileInfo->totalBlockNum++;
1489         }
1490         fmFileList->totalBytes += fileInfo->fileSize;
1491         fileInfo->receivedBlockNum = 0;
1492         fileInfo->fd = NSTACKX_INVALID_FD;
1493         fileInfo->errCode = FILE_MANAGER_EOK;
1494         fileInfo->fileOffset = 0;
1495     }
1496     return NSTACKX_EOK;
1497 L_ERR_FILE_MANAGER:
1498     for (i = 0; i < fmFileList->fileNum; i++) {
1499         free(fmFileList->fileInfo[i].fileName);
1500         fmFileList->fileInfo[i].fileName = NULL;
1501     }
1502     return NSTACKX_EFAILED;
1503 }
1504 
CreateRecvFileList(RecvFileListInfo * fileListInfo,const char * storagePath,uint16_t standardBlockSize,FileListMsgPara * msgPara,uint32_t maxRecvBlockListSize)1505 static FileListTask *CreateRecvFileList(RecvFileListInfo *fileListInfo, const char *storagePath,
1506     uint16_t standardBlockSize, FileListMsgPara *msgPara, uint32_t maxRecvBlockListSize)
1507 {
1508     FileListTask *fmFileList = NULL;
1509     fmFileList = (FileListTask *)calloc(1, sizeof(FileListTask));
1510     if (fmFileList == NULL) {
1511         DFILE_LOGE(TAG, "file list calloc error");
1512         return NULL;
1513     }
1514     fmFileList->transId = fileListInfo->transId;
1515     fmFileList->fileNum = fileListInfo->fileNum;
1516     fmFileList->storagePath = storagePath;
1517     fmFileList->noSyncFlag = fileListInfo->noSyncFlag;
1518     if (SemInit(&fmFileList->semStop, 0, 0) != 0) {
1519         DFILE_LOGE(TAG, "SemInit error");
1520         free(fmFileList);
1521         return NULL;
1522     }
1523     fmFileList->runStatus = FILE_LIST_STATUS_IDLE;
1524     fmFileList->stopType = FILE_LIST_TRANSFER_FINISH;
1525     fmFileList->isOccupied = NSTACKX_FALSE;
1526     fmFileList->errCode = FILE_MANAGER_EOK;
1527     ListInitHead(&fmFileList->innerRecvBlockHead);
1528     if (MutexListInit(&fmFileList->recvBlockList, maxRecvBlockListSize) != NSTACKX_EOK) {
1529         DFILE_LOGE(TAG, "receive block list init error");
1530         goto L_ERR_FILE_MANAGER;
1531     }
1532     fmFileList->recvFileProcessed = 0;
1533     fmFileList->isRecvEmptyFilesCreated = NSTACKX_FALSE;
1534     if (AddRecvFileInfo(fileListInfo->fileBasicInfo, fmFileList, standardBlockSize) != NSTACKX_EOK) {
1535         MutexListDestory(&fmFileList->recvBlockList);
1536         goto L_ERR_FILE_MANAGER;
1537     }
1538     if (msgPara != NULL) {
1539         fmFileList->msgReceiver = msgPara->msgReceiver;
1540         fmFileList->context = msgPara->context;
1541     }
1542     return fmFileList;
1543 L_ERR_FILE_MANAGER:
1544     SemDestroy(&fmFileList->semStop);
1545     (void)memset_s(fmFileList, sizeof(FileListTask), 0, sizeof(FileListTask));
1546     free(fmFileList);
1547     return NULL;
1548 }
1549 
GetStoragePathByType(FileManager * fileManager,uint16_t pathType)1550 char *GetStoragePathByType(FileManager *fileManager, uint16_t pathType)
1551 {
1552     if (pathType == 0) {
1553         return fileManager->commonStoragePath;
1554     }
1555     for (uint16_t i = 0; i < fileManager->typedPathNum; i++) {
1556         if (fileManager->pathList[i].pathType == pathType) {
1557             return fileManager->pathList[i].storagePath;
1558         }
1559     }
1560     return NULL;
1561 }
1562 
FileManagerRecvFileTask(FileManager * fileManager,RecvFileListInfo * fileListInfo,FileListMsgPara * msgPara)1563 int32_t FileManagerRecvFileTask(FileManager *fileManager, RecvFileListInfo *fileListInfo, FileListMsgPara *msgPara)
1564 {
1565     FileListTask *fmFileList = NULL;
1566     uint16_t standardBlockSize;
1567     const char *storagePath = NULL;
1568     if (CheckReceiverManager(fileManager) != NSTACKX_EOK || fileManager->maxRecvBlockListSize == 0) {
1569         return NSTACKX_EINVAL;
1570     }
1571 
1572     if (fileManager->taskList.size == fileManager->taskList.maxSize) {
1573         DFILE_LOGE(TAG, "task list is full");
1574         return NSTACKX_EFAILED;
1575     }
1576 
1577     storagePath = GetStoragePathByType(fileManager, fileListInfo->pathType);
1578     if (storagePath == NULL) {
1579         DFILE_LOGE(TAG, "can't get storage path for pathType %u", fileListInfo->pathType);
1580         return NSTACKX_EFAILED;
1581     }
1582 
1583     standardBlockSize = GetStandardBlockSize(fileManager);
1584     if (standardBlockSize == 0) {
1585         DFILE_LOGE(TAG, "max frame length is too small");
1586         return NSTACKX_EFAILED;
1587     }
1588     fmFileList = CreateRecvFileList(fileListInfo, storagePath, standardBlockSize, msgPara,
1589                                     fileManager->maxRecvBlockListSize);
1590     if (fmFileList == NULL) {
1591         DFILE_LOGE(TAG, "Creat file list error");
1592         return NSTACKX_EFAILED;
1593     }
1594     fmFileList->epollfd = fileManager->epollfd;
1595     fmFileList->eventNodeChain = fileManager->eventNodeChain;
1596     fmFileList->maxFrameLength = fileManager->maxFrameLength;
1597     if (fileManager->keyLen > 0 && SetCryptPara(fmFileList, fileManager->key, fileManager->keyLen) != NSTACKX_EOK) {
1598         ClearRecvFileList(fmFileList);
1599         DFILE_LOGE(TAG, "fail to set crypto para");
1600         return NSTACKX_EFAILED;
1601     }
1602 
1603     if (MutexListAddNode(&fileManager->taskList, &fmFileList->list, NSTACKX_FALSE) != NSTACKX_EOK) {
1604         DFILE_LOGE(TAG, "Add task to list error");
1605         ClearRecvFileList(fmFileList);
1606         fileManager->errCode = FILE_MANAGER_EMUTEX;
1607         NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1608         return NSTACKX_EFAILED;
1609     }
1610     fileManager->totalBytes += fmFileList->totalBytes;
1611     SemPost(&fileManager->semTaskListNotEmpty);
1612     return NSTACKX_EOK;
1613 }
1614 
PushRecvBlockFrame(FileListTask * fileList,FileDataFrame * frame)1615 static int32_t PushRecvBlockFrame(FileListTask *fileList, FileDataFrame *frame)
1616 {
1617     BlockFrame *blockFrame = NULL;
1618     int32_t ret;
1619     uint8_t isRetran;
1620 
1621     blockFrame = (BlockFrame *)calloc(1, sizeof(BlockFrame));
1622     if (blockFrame == NULL) {
1623         DFILE_LOGE(TAG, "memory calloc failed");
1624         return FILE_MANAGER_ENOMEM;
1625     }
1626     blockFrame->fileDataFrame = frame;
1627     isRetran = frame->header.flag & NSTACKX_DFILE_DATA_FRAME_RETRAN_FLAG;
1628     if (isRetran) {
1629         ret = MutexListAddNode(&fileList->recvBlockList, &blockFrame->list, NSTACKX_TRUE);
1630     } else {
1631         ret = MutexListAddNode(&fileList->recvBlockList, &blockFrame->list, NSTACKX_FALSE);
1632     }
1633     if (ret != NSTACKX_EOK) {
1634         free(blockFrame);
1635         DFILE_LOGE(TAG, "add node to recv block list failed");
1636         return FILE_MANAGER_EMUTEX;
1637     }
1638     SemPost(&fileList->semStop);
1639     return FILE_MANAGER_EOK;
1640 }
1641 
CheckFileBlockListOverflow(FileManager * fileManager)1642 static int32_t CheckFileBlockListOverflow(FileManager *fileManager)
1643 {
1644     uint32_t recvListAllSize;
1645     uint32_t recvInnerAllSize;
1646 
1647     if (GetFileBlockListSize(&fileManager->taskList, &recvListAllSize, &recvInnerAllSize) != NSTACKX_EOK) {
1648         fileManager->errCode = FILE_MANAGER_EMUTEX;
1649         NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1650         DFILE_LOGE(TAG, "failed to get GetFileBlockListSize");
1651         return NSTACKX_EFAILED;
1652     }
1653     if (recvListAllSize >= fileManager->maxRecvBlockListSize) {
1654         return NSTACKX_EFAILED;
1655     }
1656 
1657     return NSTACKX_EOK;
1658 }
1659 
FileManagerFileWrite(FileManager * fileManager,FileDataFrame * frame)1660 int32_t FileManagerFileWrite(FileManager *fileManager, FileDataFrame *frame)
1661 {
1662     uint16_t transId;
1663     FileListTask *fileList = NULL;
1664     uint8_t isErrorOccurred = NSTACKX_FALSE;
1665     BlockFrame block = {
1666         .list = {NULL, NULL},
1667         .fileDataFrame = frame,
1668     };
1669     if (CheckReceiverManager(fileManager) != NSTACKX_EOK) {
1670         DFILE_LOGE(TAG, "invalid input");
1671         return NSTACKX_EINVAL;
1672     }
1673     transId = ntohs(frame->header.transId);
1674     fileList = GetFileListById(&fileManager->taskList, transId, &isErrorOccurred);
1675     if (isErrorOccurred || fileList == NULL) {
1676         fileManager->errCode = FILE_MANAGER_EMUTEX;
1677         NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1678         DFILE_LOGE(TAG, "failed to get target fileList %u", transId);
1679         return NSTACKX_EFAILED;
1680     }
1681     if (CheckFilelistNotStop(fileList) != NSTACKX_EOK) {
1682         DFILE_LOGE(TAG, "target file list %u is not available", transId);
1683         return NSTACKX_EFAILED;
1684     }
1685 
1686     if (CheckFileBlockListOverflow(fileManager) != NSTACKX_EOK) {
1687         return NSTACKX_EFAILED;
1688     }
1689     RefreshBytesTransFerred(fileManager, &block);
1690     fileList->errCode = PushRecvBlockFrame(fileList, frame);
1691     if (fileList->errCode != FILE_MANAGER_EOK) {
1692         DFILE_LOGE(TAG, "add frame to recv block list failed");
1693         NotifyFileListMsg(fileList, FILE_MANAGER_RECEIVE_FAIL);
1694         return NSTACKX_EFAILED;
1695     }
1696     return NSTACKX_EOK;
1697 }
1698 
ClearTask(FileManager * fileManager)1699 static void ClearTask(FileManager *fileManager)
1700 {
1701     FileListTask *fileList = NULL;
1702 
1703     while (fileManager->taskList.size > 0) {
1704         if (PthreadMutexLock(&fileManager->taskList.lock) != 0) {
1705             DFILE_LOGE(TAG, "pthread mutex lock error");
1706             return;
1707         }
1708         fileList = (FileListTask *)ListPopFront(&fileManager->taskList.head);
1709         fileManager->taskList.size--;
1710         if (PthreadMutexUnlock(&fileManager->taskList.lock) != 0) {
1711             DFILE_LOGE(TAG, "pthread mutex unlock error");
1712         }
1713         if (fileList == NULL) {
1714             continue;
1715         }
1716         ClearFileList(fileManager, fileList);
1717         fileList = NULL;
1718     }
1719     MutexListDestory(&fileManager->taskList);
1720 }
1721 
FileManagerDestroy(FileManager * fileManager)1722 void FileManagerDestroy(FileManager *fileManager)
1723 {
1724     if (fileManager == NULL) {
1725         return;
1726     }
1727     if (fileManager->isSender) {
1728         ClearSendFrameList(fileManager);
1729     }
1730     ClearTask(fileManager);
1731     AtomicParameterDestory(fileManager);
1732     free(fileManager->commonStoragePath);
1733     fileManager->commonStoragePath = NULL;
1734     for (uint16_t i = 0; i < fileManager->typedPathNum; i++) {
1735         free(fileManager->pathList[i].storagePath);
1736         fileManager->pathList[i].storagePath = NULL;
1737     }
1738     (void)memset_s(fileManager, sizeof(FileManager), 0, sizeof(FileManager));
1739     free(fileManager);
1740     fileManager = NULL;
1741     DFILE_LOGI(TAG, "Destroy successfully!");
1742 }
1743 
FileManagerIsRecvBlockWritable(FileManager * fileManager,uint16_t transId)1744 uint8_t FileManagerIsRecvBlockWritable(FileManager *fileManager, uint16_t transId)
1745 {
1746     if (fileManager == NULL || fileManager->isSender || transId == 0) {
1747         return NSTACKX_FALSE;
1748     }
1749 
1750     if (CheckFileBlockListOverflow(fileManager) != NSTACKX_EOK) {
1751         return NSTACKX_FALSE;
1752     }
1753 
1754     return NSTACKX_TRUE;
1755 }
1756 
FileManagerGetTotalBytes(FileManager * fileManager,uint64_t * totalBytes)1757 int32_t FileManagerGetTotalBytes(FileManager *fileManager, uint64_t *totalBytes)
1758 {
1759     if (fileManager == NULL) {
1760         return NSTACKX_EFAILED;
1761     }
1762     *totalBytes = fileManager->totalBytes;
1763     return NSTACKX_EOK;
1764 }
1765 
FileManagerGetBytesTransferred(FileManager * fileManager,uint64_t * bytesTransferred)1766 int32_t FileManagerGetBytesTransferred(FileManager *fileManager, uint64_t *bytesTransferred)
1767 {
1768     FileListTask *fileList = NULL;
1769     uint64_t runningTaskBytesTransferred = 0;
1770     uint64_t ret;
1771     List *list = NULL;
1772     if (fileManager == NULL || bytesTransferred == NULL) {
1773         return 0;
1774     }
1775     if (PthreadMutexLock(&fileManager->taskList.lock) != 0) {
1776         DFILE_LOGE(TAG, "pthread mutex lock error");
1777         goto L_ERR_FILE_MANAGER;
1778     }
1779     LIST_FOR_EACH(list, &fileManager->taskList.head) {
1780         fileList = (FileListTask *)list;
1781         if (fileList == NULL || fileList->runStatus == FILE_LIST_STATUS_STOP) {
1782             continue;
1783         }
1784         runningTaskBytesTransferred += FileListGetBytesTransferred(fileList, fileManager->isSender);
1785     }
1786     if (PthreadMutexUnlock(&fileManager->taskList.lock) != 0) {
1787         DFILE_LOGE(TAG, "pthread mutex unlock error");
1788         goto L_ERR_FILE_MANAGER;
1789     }
1790 
1791     ret = runningTaskBytesTransferred + fileManager->stoppedTasksBytesTransferred;
1792     if (ret > fileManager->totalBytes) {
1793         DFILE_LOGE(TAG, "result is too large");
1794         return NSTACKX_EFAILED;
1795     }
1796     /* for sender, can't return all bytes before there is unstopped task. */
1797     if (ret == fileManager->totalBytes && fileManager->isSender && runningTaskBytesTransferred > 0) {
1798         if (ret > NSTACKX_DEFAULT_FRAME_SIZE) {
1799             ret -= NSTACKX_DEFAULT_FRAME_SIZE;
1800         } else {
1801             ret = 0;
1802         }
1803     }
1804     if (ret <= fileManager->bytesTransferredLastRecord) {
1805         ret = fileManager->bytesTransferredLastRecord;
1806     } else {
1807         fileManager->bytesTransferredLastRecord = ret;
1808     }
1809     *bytesTransferred = ret;
1810     return NSTACKX_EOK;
1811 L_ERR_FILE_MANAGER:
1812     fileManager->errCode = FILE_MANAGER_EMUTEX;
1813     NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1814     return NSTACKX_EFAILED;
1815 }
1816 
FileManagerGetTransUpdateInfo(FileManager * fileManager,uint16_t transId,uint64_t * totalBytes,uint64_t * bytesTransferred)1817 int32_t FileManagerGetTransUpdateInfo(FileManager *fileManager, uint16_t transId, uint64_t *totalBytes,
1818     uint64_t *bytesTransferred)
1819 {
1820     FileListTask *fileList = NULL;
1821     uint8_t isFound = NSTACKX_FALSE;
1822     List *list = NULL;
1823     uint64_t totalBytesPtr, bytesTransPtr;
1824     if (fileManager == NULL || totalBytes == NULL || bytesTransferred == NULL) {
1825         return NSTACKX_EFAILED;
1826     }
1827     if (PthreadMutexLock(&fileManager->taskList.lock) != 0) {
1828         DFILE_LOGE(TAG, "pthread mutex lock error");
1829         goto L_ERR_FILE_MANAGER;
1830     }
1831     LIST_FOR_EACH(list, &fileManager->taskList.head) {
1832         fileList = (FileListTask *)list;
1833         if (fileList != NULL && fileList->transId == transId) {
1834             bytesTransPtr = FileListGetBytesTransferred(fileList, fileManager->isSender);
1835             totalBytesPtr = fileList->totalBytes;
1836             isFound = NSTACKX_TRUE;
1837             break;
1838         }
1839     }
1840     if (PthreadMutexUnlock(&fileManager->taskList.lock) != 0) {
1841         DFILE_LOGE(TAG, "pthread mutex unlock error");
1842         goto L_ERR_FILE_MANAGER;
1843     }
1844 
1845     if (!isFound || bytesTransPtr > totalBytesPtr) {
1846         DFILE_LOGE(TAG, "can't find target trans %u or the result is illegal", transId);
1847         return NSTACKX_EFAILED;
1848     }
1849     *totalBytes = totalBytesPtr;
1850     *bytesTransferred = bytesTransPtr;
1851     return NSTACKX_EOK;
1852 
1853 L_ERR_FILE_MANAGER:
1854     fileManager->errCode = FILE_MANAGER_EMUTEX;
1855     NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1856     return NSTACKX_EFAILED;
1857 }
1858 
GetBlockHeadFlag(uint8_t isStartFrame,uint8_t isEndFrame)1859 uint8_t GetBlockHeadFlag(uint8_t isStartFrame, uint8_t isEndFrame)
1860 {
1861     uint8_t headFlag;
1862 
1863     if (isEndFrame) {
1864         headFlag = NSTACKX_DFILE_DATA_FRAME_END_FLAG;
1865     } else if (isStartFrame) {
1866         headFlag = NSTACKX_DFILE_DATA_FRAME_START_FLAG;
1867     } else {
1868         headFlag = NSTACKX_DFILE_DATA_FRAME_CONTINUE_FLAG;
1869     }
1870     return headFlag;
1871 }
1872 
FileManagerCLearReadOutSet(FileListTask * fileList)1873 void FileManagerCLearReadOutSet(FileListTask *fileList)
1874 {
1875     if (PthreadMutexLock(&fileList->newReadOutSet.lock) != 0) {
1876         DFILE_LOGE(TAG, "pthread mutex lock error");
1877         return;
1878     }
1879 
1880     fileList->newReadOutSet.blockSequence = 0;
1881     fileList->newReadOutSet.fileId = 0;
1882 
1883     if (PthreadMutexUnlock(&fileList->newReadOutSet.lock) != 0) {
1884         DFILE_LOGE(TAG, "pthread mutex unlock error");
1885         return;
1886     }
1887 }
1888 
FileGetRecvStatus(FileInfo * fileInfo)1889 static FileRecvState FileGetRecvStatus(FileInfo *fileInfo)
1890 {
1891     if (fileInfo->errCode != FILE_MANAGER_EOK) {
1892         return STATE_RECEIVE_DONE_FAIL;
1893     } else {
1894         if (fileInfo->fileSize == 0 || fileInfo->receivedBlockNum == fileInfo->totalBlockNum) {
1895             return STATE_RECEIVE_DONE_SUCCESSFULLY;
1896         } else {
1897             return STATE_RECEIVE_ONGOING;
1898         }
1899     }
1900 }
1901 
TaskGetReceivedFiles(FileListTask * fileList,uint16_t fileIdList[],uint8_t fileIdSuccessFlag[],uint32_t * fileNum)1902 static int32_t TaskGetReceivedFiles(FileListTask *fileList, uint16_t fileIdList[],
1903                                     uint8_t fileIdSuccessFlag[], uint32_t *fileNum)
1904 {
1905     uint32_t count = 0;
1906     FileRecvState state;
1907 
1908     if (fileNum == NULL || *fileNum == 0) {
1909         return NSTACKX_EFAILED;
1910     }
1911 
1912     if (fileList == NULL) {
1913         *fileNum = 0;
1914         return NSTACKX_EFAILED;
1915     }
1916 
1917     for (uint32_t i = 0; i < fileList->fileNum; i++) {
1918         state = FileGetRecvStatus(&fileList->fileInfo[i]);
1919         if (state == STATE_RECEIVE_ONGOING) {
1920             continue;
1921         }
1922         fileIdList[count] = fileList->fileInfo[i].fileId;
1923         if (state == STATE_RECEIVE_DONE_SUCCESSFULLY) {
1924             fileIdSuccessFlag[count] = NSTACKX_TRUE;
1925         } else {
1926             fileIdSuccessFlag[count] = NSTACKX_FALSE;
1927         }
1928         count++;
1929         if (count >= *fileNum) {
1930             return NSTACKX_EOK;
1931         }
1932     }
1933     *fileNum = count;
1934     return NSTACKX_EOK;
1935 }
1936 
FileManagerGetReceivedFiles(FileManager * fileManager,uint16_t transId,uint16_t fileIdList[],uint8_t fileIdSuccessFlag[],uint32_t * fileNum)1937 int32_t FileManagerGetReceivedFiles(FileManager *fileManager, uint16_t transId, uint16_t fileIdList[],
1938                                     uint8_t fileIdSuccessFlag[], uint32_t *fileNum)
1939 {
1940     FileListTask *fileList = NULL;
1941     uint8_t isErrorOccurred;
1942 
1943     if (fileNum == NULL || *fileNum == 0) {
1944         return NSTACKX_EFAILED;
1945     }
1946 
1947     if (fileManager == NULL || fileManager->isSender) {
1948         *fileNum = 0;
1949         return NSTACKX_EFAILED;
1950     }
1951 
1952     fileList = GetFileListById(&fileManager->taskList, transId, &isErrorOccurred);
1953     if (isErrorOccurred) {
1954         fileManager->errCode = FILE_MANAGER_EMUTEX;
1955         NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1956         *fileNum = 0;
1957         return NSTACKX_EFAILED;
1958     }
1959     if (fileList == NULL) {
1960         *fileNum = 0;
1961         return NSTACKX_EFAILED;
1962     }
1963     return TaskGetReceivedFiles(fileList, fileIdList, fileIdSuccessFlag, fileNum);
1964 }
1965 
FileManagerSetAllDataReceived(FileManager * fileManager,uint16_t transId)1966 int32_t FileManagerSetAllDataReceived(FileManager *fileManager, uint16_t transId)
1967 {
1968     FileListTask *fileList = NULL;
1969     int32_t ret = NSTACKX_EFAILED;
1970     List *list = NULL;
1971     if (CheckReceiverManager(fileManager) != NSTACKX_EOK) {
1972         DFILE_LOGE(TAG, "invalid input");
1973         return NSTACKX_EINVAL;
1974     }
1975     if (PthreadMutexLock(&fileManager->taskList.lock) != 0) {
1976         DFILE_LOGE(TAG, "pthread mutex lock error");
1977         goto L_ERR_FILE_MANAGER;
1978     }
1979     LIST_FOR_EACH(list, &fileManager->taskList.head) {
1980         fileList = (FileListTask *)list;
1981         if (fileList->transId == transId) {
1982             fileList->allFileDataReceived = NSTACKX_TRUE;
1983             SemPost(&fileList->semStop);
1984             ret = NSTACKX_EOK;
1985             break;
1986         }
1987     }
1988     if (PthreadMutexUnlock(&fileManager->taskList.lock) != 0) {
1989         DFILE_LOGE(TAG, "pthread mutex unlock error");
1990         goto L_ERR_FILE_MANAGER;
1991     }
1992     return ret;
1993 L_ERR_FILE_MANAGER:
1994     fileManager->errCode = FILE_MANAGER_EMUTEX;
1995     NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1996     return NSTACKX_EFAILED;
1997 }
1998 
ClearTransStateList(DFileSession * session)1999 void ClearTransStateList(DFileSession *session)
2000 {
2001     List *tmp = NULL;
2002     List *pos = NULL;
2003     if (session == NULL || ListIsEmpty(&session->tranIdStateList.head))
2004         return;
2005 
2006     if (PthreadMutexLock(&session->tranIdStateList.lock) != 0) {
2007         DFILE_LOGE(TAG, "pthread mutex lock error");
2008         return;
2009     }
2010 
2011     LIST_FOR_EACH_SAFE(pos, tmp, &session->tranIdStateList.head) {
2012         TransStateNode *node = (TransStateNode *)pos;
2013         ListRemoveNode(&node->list);
2014         free(node);
2015         session->tranIdStateList.size--;
2016     }
2017 
2018     if (PthreadMutexUnlock(&session->tranIdStateList.lock) != 0) {
2019         DFILE_LOGE(TAG, "pthread mutex unlock error");
2020         return;
2021     }
2022 
2023     return;
2024 }
2025 
SetTransIdState(DFileSession * session,uint16_t transId,TransIdState state)2026 int32_t SetTransIdState(DFileSession *session, uint16_t transId, TransIdState state)
2027 {
2028     List *curFront = NULL;
2029     uint8_t errorFlag = NSTACKX_FALSE;
2030     uint8_t isPoped;
2031 
2032     if (session == NULL)
2033         return NSTACKX_EFAILED;
2034 
2035     if (session->sessionType == DFILE_SESSION_TYPE_CLIENT) {
2036         return NSTACKX_EOK;
2037     }
2038     TransIdState curState = STATE_TRANS_INIT;
2039     TransStateNode *node = GetTransIdState(session, transId, &curState);
2040     if (node == NULL) {
2041         node = (TransStateNode *)calloc(1, sizeof(TransStateNode));
2042         if (node == NULL) {
2043             return NSTACKX_EFAILED;
2044         }
2045         node->transId = transId;
2046         node->transIdState = state;
2047         if (MutexListAddNode(&session->tranIdStateList, &node->list, 0) != NSTACKX_EOK) {
2048             free(node);
2049             return NSTACKX_EFAILED;
2050         }
2051         if (session->tranIdStateList.size == session->tranIdStateList.maxSize) {
2052             if (MutexListPopFront(&session->tranIdStateList, &curFront, &isPoped) != NSTACKX_EOK) {
2053                 DFILE_LOGE(TAG, "Pop tranIdStateList head error");
2054                 errorFlag = NSTACKX_TRUE;
2055             }
2056             if (isPoped) {
2057                 TransStateNode *tmp = (TransStateNode *)curFront;
2058                 free(tmp);
2059                 tmp = NULL;
2060             }
2061         }
2062         return (errorFlag ? NSTACKX_EFAILED : NSTACKX_EOK);
2063     }
2064 
2065     if (curState == state) {
2066         return NSTACKX_EOK;
2067     }
2068 
2069     node->transIdState = state;
2070     return NSTACKX_EOK;
2071 }
2072 
GetTransIdState(DFileSession * session,uint16_t transId,TransIdState * state)2073 TransStateNode *GetTransIdState(DFileSession *session, uint16_t transId, TransIdState *state)
2074 {
2075     List *pos = NULL;
2076     TransStateNode *node = NULL;
2077     uint8_t find = NSTACKX_FALSE;
2078 
2079     if (session == NULL || ListIsEmpty(&session->tranIdStateList.head))
2080         return NULL;
2081 
2082     if (PthreadMutexLock(&session->tranIdStateList.lock) != 0) {
2083         DFILE_LOGE(TAG, "pthread mutex lock error");
2084         return NULL;
2085     }
2086     LIST_FOR_EACH(pos, &session->tranIdStateList.head) {
2087         node = (TransStateNode *)pos;
2088         if (node->transId == transId) {
2089             *state = node->transIdState;
2090             find = NSTACKX_TRUE;
2091             break;
2092         }
2093     }
2094 
2095     if (PthreadMutexUnlock(&session->tranIdStateList.lock) != 0) {
2096         DFILE_LOGE(TAG, "pthread mutex unlock error");
2097         return NULL;
2098     }
2099     return (find ? node : NULL);
2100 }
2101 
IsTransIdDone(DFileSession * session,uint16_t transId)2102 int32_t IsTransIdDone(DFileSession *session, uint16_t transId)
2103 {
2104     TransIdState state = STATE_TRANS_INIT;
2105     TransStateNode *node = NULL;
2106 
2107     if (session != NULL && session->sessionType == DFILE_SESSION_TYPE_CLIENT) {
2108         return NSTACKX_EOK;
2109     }
2110     node = GetTransIdState(session, transId, &state);
2111     if (node == NULL) {
2112         return NSTACKX_EFAILED;
2113     }
2114 
2115     if (state == STATE_TRANS_DONE) {
2116         DFILE_LOGE(TAG, "trans %u is transfer done already", transId);
2117         return NSTACKX_EOK;
2118     }
2119 
2120     return NSTACKX_EFAILED;
2121 }
2122