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