• 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 "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 #ifndef MBEDTLS_INCLUDED
409     ClearCryptCtx(fileList->cryptPara.ctx);
410 #endif
411     (void)memset_s(fileList, sizeof(FileListTask), 0, sizeof(FileListTask));
412     free(fileList);
413 }
414 
GetFullFilePath(const char * path,const char * fileName)415 char *GetFullFilePath(const char *path, const char *fileName)
416 {
417     int32_t ret;
418     char *fullPath = NULL;
419     uint32_t fullPathLength;
420     if (path == NULL || fileName == NULL) {
421         return NULL;
422     }
423 
424     if ((CheckPathSeprator(path) == NSTACKX_TRUE) || (CheckFilenameSeprator(fileName) == NSTACKX_TRUE)) {
425         fullPathLength = (uint32_t)(strlen(path) + strlen(fileName) + sizeof('\0'));
426     } else {
427         fullPathLength = (uint32_t)(strlen(path) + sizeof(PATH_SEPARATOR) + strlen(fileName) + sizeof('\0'));
428     }
429 
430     if (fullPathLength == 0) {
431         return NULL;
432     }
433 
434     fullPath = (char *)calloc(fullPathLength, sizeof(char));
435     if (fullPath == NULL) {
436         DFILE_LOGE(TAG, "full path calloc error");
437         return NULL;
438     }
439 
440     if ((CheckPathSeprator(path) == NSTACKX_TRUE) || (CheckFilenameSeprator(fileName) == NSTACKX_TRUE)) {
441         ret = sprintf_s(fullPath, fullPathLength, "%s%s", path, fileName);
442     } else {
443         ret = sprintf_s(fullPath, fullPathLength, "%s%c%s", path, PATH_SEPARATOR, fileName);
444     }
445 
446     if (ret == -1) {
447         DFILE_LOGE(TAG, "splice path and file name error");
448         free(fullPath);
449         return NULL;
450     }
451     return fullPath;
452 }
453 
ClearIncompleteRecvFiles(const char * path,FileListTask * fileList)454 static void ClearIncompleteRecvFiles(const char *path, FileListTask *fileList)
455 {
456     char *fullPath = NULL;
457     for (uint32_t i = 0; i < fileList->fileNum; i++) {
458         if (fileList->fileInfo[i].errCode == FILE_MANAGER_EOK &&
459             fileList->fileInfo[i].receivedBlockNum == fileList->fileInfo[i].totalBlockNum &&
460             fileList->stopType == FILE_LIST_TRANSFER_FINISH) {
461             continue;
462         }
463         CloseFile(&fileList->fileInfo[i]);
464         fullPath = GetFullFilePath(path, fileList->fileInfo[i].fileName);
465         if (fullPath != NULL) {
466             DFILE_LOGE(TAG, "going to remove incomplete file %s", fileList->fileInfo[i].fileName);
467             if (remove(fullPath) != 0) {
468                 DFILE_LOGE(TAG, "remove file failed. errno %d", errno);
469             }
470             free(fullPath);
471         }
472     }
473     return;
474 }
475 
FileInfoWriteInit(FileInfo * fileInfo,const char * path,uint8_t isTruncate)476 static void FileInfoWriteInit(FileInfo *fileInfo, const char *path, uint8_t isTruncate)
477 {
478     char *fullPath = GetFullFilePath(path, fileInfo->fileName);
479     if (fullPath == NULL) {
480         DFILE_LOGE(TAG, "Can't get full path");
481         fileInfo->errCode = FILE_MANAGER_ENOMEM;
482         return;
483     }
484     if (TestAndCreateDirectory(fullPath) != NSTACKX_EOK) {
485         free(fullPath);
486         fileInfo->errCode = FILE_MANAGER_FILE_EOTHER;
487         DFILE_LOGE(TAG, "create directory failed");
488         return;
489     }
490 #ifdef BUILD_FOR_WINDOWS
491     fileInfo->fd = fopen(fullPath, "wb");
492 #else
493     if (isTruncate) {
494         fileInfo->fd = open(fullPath, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
495     } else {
496         fileInfo->fd = open(fullPath, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
497     }
498 #endif
499     free(fullPath);
500     if (fileInfo->fd == NSTACKX_INVALID_FD) {
501         fileInfo->errCode = ConvertErrCode(errno);
502         DFILE_LOGE(TAG, "can't open file, error(%d)", errno);
503         return;
504     }
505     fileInfo->fileOffset = 0;
506 }
507 
WriteToFile(FileInfo * fileInfo,uint32_t blockSequence,uint16_t length,uint8_t * payLoad,FileListTask * fileList)508 static int32_t WriteToFile(FileInfo *fileInfo, uint32_t blockSequence, uint16_t length, uint8_t *payLoad,
509     FileListTask *fileList)
510 {
511     uint64_t fileOffset;
512     uint16_t ret = 0;
513     int32_t pRet = 0;
514     DFileSession *session = fileList->context;
515     if (fileInfo->fd == NSTACKX_INVALID_FD) {
516         FileInfoWriteInit(fileInfo, fileList->storagePath, NSTACKX_TRUE);
517         if (fileInfo->fd == NSTACKX_INVALID_FD) {
518             return NSTACKX_EFAILED;
519         }
520     }
521     if (fileInfo->fileSize == 0 || payLoad == NULL || length == 0) {
522         return NSTACKX_EOK;
523     }
524     fileOffset = ((uint64_t)fileInfo->standardBlockSize) * ((uint64_t)blockSequence);
525     fileOffset += fileInfo->startOffset;
526     if (SetFileOffset(fileInfo, fileOffset) != NSTACKX_EOK) {
527         fileInfo->errCode = FILE_MANAGER_FILE_EOTHER;
528         DFILE_LOGE(TAG, "set file offset failed");
529         return NSTACKX_EFAILED;
530     }
531     if (CapsNoRW(session)) {
532         ret = length;
533     } else {
534 #ifdef BUILD_FOR_WINDOWS
535         ret = (uint16_t)fwrite(payLoad, 1, length, fileInfo->fd);
536 #else
537         /* use pwrite because fseek have multi-thread issue in case of multi-path handle same file scenario */
538         pRet = (int32_t)pwrite(fileInfo->fd, payLoad, length, (int64_t)fileOffset);
539         if (pRet >= 0) {
540             ret = (uint16_t)pRet;
541         }
542 #endif
543     }
544     if ((pRet < 0) || (ret < length)) {
545         DFILE_LOGE(TAG, "fwrite error %d write %hu target %hu pRet:%d", GetErrno(), ret, length, pRet);
546         fileInfo->errCode = FILE_MANAGER_FILE_EOTHER;
547         return NSTACKX_EFAILED;
548     }
549     fileInfo->fileOffset += ret;
550     if (++fileInfo->receivedBlockNum == fileInfo->totalBlockNum) {
551         fileInfo->isEndBlockReceived = NSTACKX_TRUE;
552     }
553     return NSTACKX_EOK;
554 }
555 
GetFrameHearderInfo(FileListTask * fileList,BlockFrame * blockFrame,uint16_t * fileId,uint32_t * blockSequence,uint16_t * payloadLength)556 static int32_t GetFrameHearderInfo(FileListTask *fileList, BlockFrame *blockFrame, uint16_t *fileId,
557     uint32_t *blockSequence, uint16_t *payloadLength)
558 {
559     uint16_t transId, length;
560     transId = ntohs(blockFrame->fileDataFrame->header.transId);
561     *fileId = ntohs(blockFrame->fileDataFrame->fileId);
562     *blockSequence = ntohl(blockFrame->fileDataFrame->blockSequence);
563     length = ntohs(blockFrame->fileDataFrame->header.length);
564     if (transId != fileList->transId || *fileId > fileList->fileNum || *fileId == 0) {
565         DFILE_LOGE(TAG, "illegal transId (%hu) or fileId (%hu)", transId, *fileId);
566         return NSTACKX_EFAILED;
567     } else {
568         FileInfo *info = &fileList->fileInfo[*fileId - 1];
569         if (info->receivedBlockNum == info->totalBlockNum) {
570             DFILE_LOGI(TAG, "fileId (%hu) has already finished written totalBlockNum %u", *fileId, info->totalBlockNum);
571             *payloadLength = 0;
572             return NSTACKX_EOK;
573         }
574     }
575 
576     if (*blockSequence >= fileList->fileInfo[*fileId - 1].totalBlockNum ||
577         length <= sizeof(FileDataFrame) - sizeof(DFileFrameHeader) || length > NSTACKX_MAX_FRAME_SIZE) {
578         DFILE_LOGE(TAG, "block sequence or length is illegal");
579         fileList->errCode = FILE_MANAGER_LIST_EBLOCK;
580         return NSTACKX_EFAILED;
581     }
582 
583     *payloadLength = length + sizeof(DFileFrameHeader) - sizeof(FileDataFrame);
584     return NSTACKX_EOK;
585 }
586 
UpdateFileListRecvStatus(FileManager * fileManager,FileListTask * fileList,FileInfo * fileInfo,int32_t ret)587 static void UpdateFileListRecvStatus(FileManager *fileManager, FileListTask *fileList, FileInfo *fileInfo, int32_t ret)
588 {
589     if (ret != NSTACKX_EOK) {
590         DFILE_LOGE(TAG, "WriteToFile error:transId %u, fileId %u", fileList->transId, fileInfo->fileId);
591         CloseFile(fileInfo);
592         fileList->recvFileProcessed++;
593         NotifyFileMsg(fileList, fileInfo->fileId, FILE_MANAGER_RECEIVE_FAIL);
594         return;
595     }
596     if (fileInfo->receivedBlockNum < fileInfo->totalBlockNum) {
597         return;
598     }
599     CloseFile(fileInfo);
600     fileList->recvFileProcessed++;
601     if (fileList->recvFileProcessed == fileList->fileNum) {
602         NotifyFileManagerMsg(fileManager, FILE_MANAGER_IN_PROGRESS);
603     }
604     NotifyFileMsg(fileList, fileInfo->fileId, FILE_MANAGER_RECEIVE_SUCCESS);
605 }
606 
WriteSingleBlockFrame(FileManager * fileManager,FileListTask * fileList,BlockFrame * blockFrame)607 static int32_t WriteSingleBlockFrame(FileManager *fileManager, FileListTask *fileList, BlockFrame *blockFrame)
608 {
609     FileInfo *fileInfo = NULL;
610     uint16_t fileId, payloadLength;
611     uint32_t blockSequence;
612     uint8_t *payLoad = NULL;
613     uint8_t *buffer = NULL;
614     int32_t ret = NSTACKX_EFAILED;
615 
616     if (GetFrameHearderInfo(fileList, blockFrame, &fileId, &blockSequence, &payloadLength) != NSTACKX_EOK) {
617         fileList->errCode = FILE_MANAGER_LIST_EBLOCK;
618         return NSTACKX_EFAILED;
619     }
620 
621     if (payloadLength == 0) {
622         return NSTACKX_EOK;
623     }
624 
625     fileInfo = &fileList->fileInfo[fileId - 1];
626     if (fileInfo->errCode != FILE_MANAGER_EOK) {
627         return NSTACKX_EOK;
628     }
629 
630     payLoad = blockFrame->fileDataFrame->blockPayload;
631     uint32_t dataLen;
632     if (fileList->cryptPara.keylen > 0) {
633         buffer = (uint8_t *)calloc(payloadLength, 1);
634         if (buffer == NULL) {
635             fileList->errCode = FILE_MANAGER_ENOMEM;
636             return NSTACKX_EFAILED;
637         }
638         dataLen = AesGcmDecrypt(payLoad, payloadLength, &fileList->cryptPara, buffer, payloadLength);
639         if (dataLen == 0) {
640             fileInfo->errCode = FILE_MANAGER_FILE_EOTHER;
641             payLoad = NULL;
642             DFILE_LOGE(TAG, "data decrypt error");
643         } else {
644             payLoad = buffer;
645             payloadLength = (uint16_t)dataLen;
646         }
647     }
648     if (payLoad != NULL) {
649         ret = WriteToFile(fileInfo, blockSequence, payloadLength, payLoad, fileList);
650         if (ret == NSTACKX_EOK) {
651             fileManager->iowBytes += (uint64_t)payloadLength;
652         }
653     }
654     /*
655      * When all blocks are received, fsync should be called before refreshing the receivedBlockNum.
656      */
657     if (fileList->noSyncFlag == NSTACKX_FALSE && fileInfo->isEndBlockReceived) {
658         FileSync(fileInfo);
659     }
660     free(buffer);
661     UpdateFileListRecvStatus(fileManager, fileList, fileInfo, ret);
662     return ret;
663 }
664 
WriteBlockFrame(FileManager * fileManager,FileListTask * fileList)665 static int32_t WriteBlockFrame(FileManager *fileManager, FileListTask *fileList)
666 {
667     BlockFrame *blockFrame = NULL;
668     while (!ListIsEmpty(&fileList->innerRecvBlockHead)) {
669         if (CheckManager(fileManager) != NSTACKX_EOK || CheckFilelist(fileList) != NSTACKX_EOK) {
670             break;
671         }
672         blockFrame = (BlockFrame *)ListPopFront(&fileList->innerRecvBlockHead);
673         if (blockFrame == NULL) {
674             DFILE_LOGE(TAG, "get a null block");
675             continue;
676         }
677         if (WriteSingleBlockFrame(fileManager, fileList, blockFrame) != NSTACKX_EOK) {
678             DFILE_LOGE(TAG, "write block frame failed");
679             if (fileList->errCode != NSTACKX_EOK) {
680                 goto L_ERR_FILE_MANAGER;
681             }
682         }
683 
684         free(blockFrame->fileDataFrame);
685         free(blockFrame);
686         blockFrame = NULL;
687 
688         if (fileList->innerRecvSize > 0) {
689             fileList->innerRecvSize--;
690         }
691     }
692     return NSTACKX_EOK;
693 L_ERR_FILE_MANAGER:
694     free(blockFrame->fileDataFrame);
695     free(blockFrame);
696     return NSTACKX_EFAILED;
697 }
698 
SwapRecvBlockListHead(MutexList * mutexList,uint8_t * isEmpty,List * newHead,uint32_t * size)699 static int32_t SwapRecvBlockListHead(MutexList *mutexList, uint8_t *isEmpty, List *newHead, uint32_t *size)
700 {
701     List *front = NULL;
702     List *back = NULL;
703     *isEmpty = NSTACKX_FALSE;
704     if (PthreadMutexLock(&mutexList->lock) != 0) {
705         DFILE_LOGE(TAG, "pthread mutex lock error");
706         return NSTACKX_EFAILED;
707     }
708     if (mutexList->size == 0) {
709         *isEmpty = NSTACKX_TRUE;
710     } else {
711         front = mutexList->head.next;
712         back = mutexList->head.prev;
713         newHead->next = front;
714         newHead->prev = back;
715         front->prev = newHead;
716         back->next = newHead;
717         ListInitHead(&mutexList->head);
718         *size = mutexList->size;
719         mutexList->size = 0;
720     }
721     if (PthreadMutexUnlock(&mutexList->lock) != 0) {
722         DFILE_LOGE(TAG, "pthread mutex unlock error");
723         return NSTACKX_EFAILED;
724     }
725     return NSTACKX_EOK;
726 }
727 
GenerateAllEmptyFiles(FileListTask * fileList)728 static void GenerateAllEmptyFiles(FileListTask *fileList)
729 {
730     FileInfo *fileInfo = NULL;
731     int32_t ret;
732     for (uint32_t i = 0; i < fileList->fileNum; i++) {
733         if (fileList->fileInfo[i].fileSize > 0) {
734             continue;
735         }
736         fileInfo = &fileList->fileInfo[i];
737         ret = WriteToFile(fileInfo, 0, 0, NULL, fileList);
738         CloseFile(fileInfo);
739         fileList->recvFileProcessed++;
740 
741         if (ret != NSTACKX_EOK) {
742             DFILE_LOGE(TAG, "Create empty file error: transId %u, fileId %u", fileList->transId, fileInfo->fileId);
743             NotifyFileMsg(fileList, fileInfo->fileId, FILE_MANAGER_RECEIVE_FAIL);
744         } else {
745             DFILE_LOGI(TAG, "Create empty file successfully: transId %u, fileId %u", fileList->transId,
746                 fileInfo->fileId);
747             NotifyFileMsg(fileList, fileList->fileInfo[i].fileId, FILE_MANAGER_RECEIVE_SUCCESS);
748         }
749     }
750 }
751 
FileListRefreshFileRecvStatus(FileListTask * fileList)752 static void FileListRefreshFileRecvStatus(FileListTask *fileList)
753 {
754     if (fileList->recvFileProcessed >= fileList->fileNum) {
755         return;
756     }
757 
758     for (uint16_t i = 0; i < fileList->fileNum; i++) {
759         if (FileGetRecvStatus(&fileList->fileInfo[i]) == STATE_RECEIVE_ONGOING) {
760             fileList->fileInfo[i].errCode = FILE_MANAGER_FILE_EOTHER;
761             DFILE_LOGE(TAG, "file list will be stopped and set incompleted file %u to fail",
762                 fileList->fileInfo[i].fileId);
763             NotifyFileMsg(fileList, fileList->fileInfo[i].fileId, FILE_MANAGER_RECEIVE_FAIL);
764         }
765     }
766     fileList->recvFileProcessed = fileList->fileNum;
767 }
768 
RecvTaskProcess(FileManager * fileManager,FileListTask * fileList)769 static void RecvTaskProcess(FileManager *fileManager, FileListTask *fileList)
770 {
771     uint8_t isEmpty = NSTACKX_FALSE;
772 
773     while (NSTACKX_TRUE) {
774         if (CheckManager(fileManager) != NSTACKX_EOK || CheckFilelist(fileList) != NSTACKX_EOK ||
775             fileList->recvFileProcessed >= fileList->fileNum) {
776             break;
777         }
778 
779         if (!fileList->isRecvEmptyFilesCreated) {
780             GenerateAllEmptyFiles(fileList);
781             fileList->isRecvEmptyFilesCreated = NSTACKX_TRUE;
782             continue;
783         }
784 
785         SemWait(&fileList->semStop);
786         if (CheckManager(fileManager) != NSTACKX_EOK || CheckFilelist(fileList) != NSTACKX_EOK) {
787             break;
788         }
789         if (SwapRecvBlockListHead(&fileList->recvBlockList, &isEmpty, &fileList->innerRecvBlockHead,
790             &(fileList->innerRecvSize)) != NSTACKX_EOK) {
791             DFILE_LOGE(TAG, "Swap receive block list head error:transId %u", fileList->transId);
792             fileList->errCode = FILE_MANAGER_EMUTEX;
793             break;
794         }
795         if (isEmpty) {
796             if (fileList->allFileDataReceived) {
797                 fileList->dataWriteTimeoutCnt++;
798             }
799             if (fileList->dataWriteTimeoutCnt > NSTACKX_MAX_DATA_FWRITE_TIMEOUT_COUNT) {
800                 DFILE_LOGE(TAG, "some frames may lost or illegal and stop this file list");
801                 break;
802             }
803             continue;
804         } else {
805             fileList->dataWriteTimeoutCnt = 0;
806         }
807         if (WriteBlockFrame(fileManager, fileList) != NSTACKX_EOK) {
808             DFILE_LOGE(TAG, "WriteBlockFrame error");
809             continue;
810         }
811     }
812     FileListRefreshFileRecvStatus(fileList);
813     if (fileList->errCode != FILE_MANAGER_EOK) {
814         NotifyFileListMsg(fileList, FILE_MANAGER_RECEIVE_FAIL);
815         DFILE_LOGE(TAG, "recv task process failed");
816     }
817 }
818 
ClearFileList(FileManager * fileManager,FileListTask * fileList)819 static void ClearFileList(FileManager *fileManager, FileListTask *fileList)
820 {
821     if (fileManager->isSender) {
822         ClearSendFileList(fileManager, fileList);
823     } else {
824         ClearIncompleteRecvFiles(fileList->storagePath, fileList);
825         ClearRecvFileList(fileList);
826     }
827 }
828 
BindFileManagerThreadToTargetCpu(FileManager * fileManager,uint32_t idx)829 static void BindFileManagerThreadToTargetCpu(FileManager *fileManager, uint32_t idx)
830 {
831     int32_t cpu;
832     int32_t cpus = GetCpuNum();
833     if (cpus >= FIRST_CPU_NUM_LEVEL) {
834         return;
835     } else if (cpus >= SECOND_CPU_NUM_LEVEL) {
836         if (fileManager->isSender) {
837             cpu = CPU_IDX_0;
838         } else {
839             cpu = CPU_IDX_2 + (int32_t)idx % FILE_MANAGER_THREADS_BINDED_CPU_NUM;
840         }
841     } else if (cpus >= THIRD_CPU_NUM_LEVEL) {
842         if (fileManager->isSender) {
843             cpu = CPU_IDX_0;
844         } else {
845             cpu = CPU_IDX_1;
846         }
847     } else {
848         return;
849     }
850     StartThreadBindCore(cpu);
851 }
852 
853 typedef struct {
854     FileManager *fileManager;
855     uint32_t threadIdx;
856 } FileManagerThreadCtx;
857 
SetIOThreadName(uint32_t threadIdx)858 static void SetIOThreadName(uint32_t threadIdx)
859 {
860     char name[MAX_THREAD_NAME_LEN] = {0};
861     if (sprintf_s(name, sizeof(name), "%s%u", DFFILE_IO_THREAD_NAME_PREFIX, threadIdx) < 0) {
862         DFILE_LOGE(TAG, "sprintf io thead name failed");
863     }
864     SetThreadName(name);
865     DFILE_LOGI(TAG, "IO thread %u start", threadIdx);
866 }
867 
DoTaskProcess(FileManager * fileManager,FileListTask * fileList)868 static void DoTaskProcess(FileManager *fileManager, FileListTask *fileList)
869 {
870     if (fileManager->isSender) {
871         SendTaskProcess(fileManager, fileList);
872     } else {
873         RecvTaskProcess(fileManager, fileList);
874     }
875 }
876 
FileManagerPre(FileManager * fileManager,uint32_t threadIdx)877 static void FileManagerPre(FileManager *fileManager, uint32_t threadIdx)
878 {
879     SetIOThreadName(threadIdx);
880     SetMaximumPriorityForThread();
881     SetTidToBindInfo(fileManager->context, threadIdx);
882 }
883 
AfterTaskProcess(FileManager * fileManager,FileListTask * fileList)884 static void AfterTaskProcess(FileManager *fileManager, FileListTask *fileList)
885 {
886     fileList->isOccupied = NSTACKX_FALSE;
887     SemPost(&fileManager->semTaskListNotEmpty);
888 }
889 
FileManagerThread(void * arg)890 static void *FileManagerThread(void *arg)
891 {
892     FileManagerThreadCtx *ctx = (FileManagerThreadCtx *)arg;
893     FileManager *fileManager = ctx->fileManager;
894     uint32_t threadIdx = ctx->threadIdx;
895     free(ctx);
896     uint8_t isErrorOccurred = NSTACKX_FALSE;
897     FileListTask *fileList = NULL;
898     uint8_t isBind = NSTACKX_FALSE;
899     FileManagerPre(fileManager, threadIdx);
900     while (fileManager->runStatus == FILE_MANAGE_RUN) {
901         SemWait(&fileManager->semTaskListNotEmpty);
902         if (fileManager->runStatus != FILE_MANAGE_RUN) {
903             break;
904         }
905         uint8_t isStopTaskDetached = NSTACKX_FALSE;
906         fileList = PrepareOneTaskByStatus(fileManager, FILE_LIST_STATUS_STOP, &isErrorOccurred);
907         if (isErrorOccurred) {
908             fileManager->errCode = FILE_MANAGER_EMUTEX;
909             NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
910             DFILE_LOGE(TAG, "error occuerd when get stop file list");
911         }
912         if (fileList != NULL) {
913             isStopTaskDetached = NSTACKX_TRUE;
914             DFILE_LOGI(TAG, "Thread %u is clearing fileList %u", threadIdx, fileList->transId);
915             ClearFileList(fileManager, fileList);
916         }
917         if (isErrorOccurred || isStopTaskDetached) {
918             continue;
919         }
920 
921         fileList = PrepareOneTaskByStatus(fileManager, FILE_LIST_STATUS_IDLE, &isErrorOccurred);
922         if (isErrorOccurred) {
923             fileManager->errCode = FILE_MANAGER_EMUTEX;
924             NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
925             DFILE_LOGE(TAG, "error occuerd when get idle file list");
926             continue;
927         }
928         if (fileList == NULL || fileList->errCode != FILE_MANAGER_EOK) {
929             continue;
930         }
931         DFILE_LOGI(TAG, "Thread %u is processing for fileList %u", threadIdx, fileList->transId);
932         if (isBind == NSTACKX_FALSE && fileManager->transFlag == NSTACKX_TRUE) {
933             BindFileManagerThreadToTargetCpu(fileManager, threadIdx);
934             isBind = NSTACKX_TRUE;
935         }
936         DoTaskProcess(fileManager, fileList);
937         AfterTaskProcess(fileManager, fileList);
938     }
939     return NULL;
940 }
941 
WakeAllThread(FileManager * fileManager)942 static void WakeAllThread(FileManager *fileManager)
943 {
944     uint32_t i;
945     List *list = NULL;
946     FileListTask *fileList = NULL;
947     SendBlockFrameListPara *para = NULL;
948     if (PthreadMutexLock(&fileManager->taskList.lock) != 0) {
949         DFILE_LOGE(TAG, "pthread mutex lock error");
950         return;
951     }
952     LIST_FOR_EACH(list, &fileManager->taskList.head) {
953         fileList = (FileListTask *)list;
954         SemPost(&fileList->semStop);
955         para = &fileManager->sendBlockFrameListPara[fileList->bindedSendBlockListIdx];
956         SemPost(&para->semBlockListNotFull);
957     }
958     if (PthreadMutexUnlock(&fileManager->taskList.lock) != 0) {
959         DFILE_LOGE(TAG, "pthread mutex unlock error");
960         return;
961     }
962     for (i = 0; i < NSTACKX_FILE_MANAGER_THREAD_NUM; i++) {
963         SemPost(&fileManager->semTaskListNotEmpty);
964     }
965 }
966 
StopFileManagerThreads(FileManager * fileManager)967 void StopFileManagerThreads(FileManager *fileManager)
968 {
969     uint32_t i;
970     uint32_t tryNum;
971 
972     if (fileManager == NULL || fileManager->runStatus == FILE_MANAGE_DESTROY) {
973         return;
974     }
975 
976     fileManager->runStatus = FILE_MANAGE_DESTROY;
977     for (tryNum = 0; tryNum < THREAD_QUIT_TRY_TIMES; tryNum++) {
978         WakeAllThread(fileManager);
979     }
980 
981     for (i = 0; i < NSTACKX_FILE_MANAGER_THREAD_NUM; i++) {
982         PthreadJoin(fileManager->fileManagerTid[i], NULL);
983         DFILE_LOGI(TAG, "Total thread %u: %u quit", NSTACKX_FILE_MANAGER_THREAD_NUM, i + 1);
984         fileManager->fileManagerTid[i] = INVALID_TID;
985     }
986 }
987 
CreateFMThread(FileManager * fileManager)988 static int32_t CreateFMThread(FileManager *fileManager)
989 {
990     uint32_t i;
991     FileManagerThreadCtx *ctx = NULL;
992 
993     for (i = 0; i < NSTACKX_FILE_MANAGER_THREAD_NUM; i++) {
994         ctx = (FileManagerThreadCtx *)calloc(1, sizeof(FileManagerThreadCtx));
995         if (ctx == NULL) {
996             DFILE_LOGE(TAG, "the %u ctx create failed", i + 1);
997             goto L_ERR_FILEMANAGER;
998         }
999         ctx->fileManager = fileManager;
1000         ctx->threadIdx = i;
1001         if ((PthreadCreate(&fileManager->fileManagerTid[i], NULL, FileManagerThread, ctx)) != 0) {
1002             DFILE_LOGE(TAG, "the %u thread create failed", i + 1);
1003             free(ctx);
1004             goto L_ERR_FILEMANAGER;
1005         }
1006     }
1007     return NSTACKX_EOK;
1008 
1009 L_ERR_FILEMANAGER:
1010     fileManager->runStatus = FILE_MANAGE_DESTROY;
1011     for (int32_t j = 0; j < NSTACKX_FILE_MANAGER_THREAD_NUM; j++) {
1012         SemPost(&fileManager->semTaskListNotEmpty);
1013     }
1014     while (i > 0) {
1015         PthreadJoin(fileManager->fileManagerTid[i - 1], NULL);
1016         i--;
1017     }
1018     return NSTACKX_EFAILED;
1019 }
1020 
GetStandardBlockSize(const FileManager * fileManager)1021 uint16_t GetStandardBlockSize(const FileManager *fileManager)
1022 {
1023     uint32_t standardBlockSize;
1024 
1025     if (fileManager->maxFrameLength <= offsetof(FileDataFrame, blockPayload)) {
1026         return 0;
1027     }
1028 
1029     standardBlockSize = fileManager->maxFrameLength - offsetof(FileDataFrame, blockPayload);
1030 
1031     if (fileManager->keyLen > 0) {
1032         if (standardBlockSize <= GCM_ADDED_LEN) {
1033             return 0;
1034         }
1035         standardBlockSize -= GCM_ADDED_LEN;
1036     }
1037     return (uint16_t)standardBlockSize;
1038 }
1039 
SetCryptPara(FileListTask * fileList,const uint8_t key[],uint32_t keyLen)1040 int32_t SetCryptPara(FileListTask *fileList, const uint8_t key[], uint32_t keyLen)
1041 {
1042     uint32_t aadLen;
1043 
1044     if (CapsChaCha(fileList->context)) {
1045         fileList->cryptPara.cipherType = CIPHER_CHACHA;
1046     } else {
1047         fileList->cryptPara.cipherType = CIPHER_AES_GCM;
1048         keyLen = AES_128_KEY_LENGTH;
1049     }
1050 
1051     if (memcpy_s(fileList->cryptPara.key, sizeof(fileList->cryptPara.key), key, keyLen) != EOK) {
1052         DFILE_LOGE(TAG, "memcpy key failed");
1053         return NSTACKX_EFAILED;
1054     }
1055     fileList->cryptPara.keylen = keyLen;
1056 
1057     aadLen = sizeof(fileList->cryptPara.aad);
1058     if (memset_s(fileList->cryptPara.aad, aadLen, GCM_AAD_CHAR, aadLen) != EOK) {
1059         DFILE_LOGE(TAG, "memset aad failed");
1060         return NSTACKX_EFAILED;
1061     }
1062     fileList->cryptPara.aadLen = aadLen;
1063 #ifndef MBEDTLS_INCLUDED
1064     fileList->cryptPara.ctx = CreateCryptCtx();
1065     if (fileList->cryptPara.ctx == NULL) {
1066         DFILE_LOGE(TAG, "failed to create crypt ctx");
1067         return NSTACKX_EFAILED;
1068     }
1069 #endif
1070     DFILE_LOGI(TAG, "set encrypt/decrypt type is %d", fileList->cryptPara.cipherType);
1071     return NSTACKX_EOK;
1072 }
1073 
1074 /*
1075  * Note that this interface is only called by dfile main thread now. If other thread wants to call it, must be very
1076  * careful about thread-safety.
1077  */
GetFileListById(MutexList * taskList,uint16_t transId,uint8_t * isErrorOccurred)1078 FileListTask *GetFileListById(MutexList *taskList, uint16_t transId, uint8_t *isErrorOccurred)
1079 {
1080     List *list = NULL;
1081     FileListTask *fileList = NULL;
1082     uint8_t isFound = NSTACKX_FALSE;
1083     if (isErrorOccurred != NULL) {
1084         *isErrorOccurred = NSTACKX_FALSE;
1085     }
1086     if (taskList == NULL) {
1087         return NULL;
1088     }
1089     if (PthreadMutexLock(&taskList->lock) != 0) {
1090         DFILE_LOGE(TAG, "pthread mutex lock error");
1091         goto L_ERR_FILE_MANAGER;
1092     }
1093     LIST_FOR_EACH(list, &taskList->head) {
1094         fileList = (FileListTask *)list;
1095         /* If the target filelist has been stopped, it will not be accessible by other thread. */
1096         if (fileList->transId == transId && fileList->runStatus != FILE_LIST_STATUS_STOP) {
1097             isFound = NSTACKX_TRUE;
1098             break;
1099         }
1100     }
1101     if (PthreadMutexUnlock(&taskList->lock) != 0) {
1102         DFILE_LOGE(TAG, "pthread mutex unlock error");
1103         goto L_ERR_FILE_MANAGER;
1104     }
1105     if (isFound) {
1106         return fileList;
1107     }
1108     return NULL;
1109 L_ERR_FILE_MANAGER:
1110     if (isErrorOccurred != NULL) {
1111         *isErrorOccurred = NSTACKX_TRUE;
1112     }
1113     return NULL;
1114 }
1115 
GetFileBlockListSize(MutexList * taskList,uint32_t * recvListAllSize,uint32_t * recvInnerAllSize)1116 int32_t GetFileBlockListSize(MutexList *taskList, uint32_t *recvListAllSize, uint32_t *recvInnerAllSize)
1117 {
1118     List *list = NULL;
1119     FileListTask *fileList = NULL;
1120     uint32_t sum = 0;
1121     uint32_t innerSum = 0;
1122 
1123     if (taskList == NULL) {
1124         *recvListAllSize = 0;
1125         *recvInnerAllSize = 0;
1126         return NSTACKX_EOK;
1127     }
1128     if (PthreadMutexLock(&taskList->lock) != 0) {
1129         DFILE_LOGE(TAG, "pthread mutex lock error");
1130         goto L_ERR_FILE_MANAGER;
1131     }
1132     LIST_FOR_EACH(list, &taskList->head) {
1133         fileList = (FileListTask *)list;
1134         /* If the target filelist has been stopped, it will not be accessible by other thread. */
1135         if (fileList->runStatus != FILE_LIST_STATUS_STOP) {
1136             sum += fileList->recvBlockList.size;
1137             innerSum += fileList->innerRecvSize;
1138         }
1139     }
1140     if (PthreadMutexUnlock(&taskList->lock) != 0) {
1141         DFILE_LOGE(TAG, "pthread mutex unlock error");
1142         goto L_ERR_FILE_MANAGER;
1143     }
1144     *recvListAllSize = sum;
1145     *recvInnerAllSize = innerSum;
1146     return NSTACKX_EOK;
1147 L_ERR_FILE_MANAGER:
1148     return NSTACKX_EFAILED;
1149 }
1150 
RefreshBytesTransFerred(FileManager * fileManager,BlockFrame * block)1151 void RefreshBytesTransFerred(FileManager *fileManager, BlockFrame *block)
1152 {
1153     uint32_t len = 0;
1154     DFileFrameHeader *header = NULL;
1155 
1156     while (block) {
1157         header = (DFileFrameHeader *)(void *)block->fileDataFrame;
1158         len += ntohs(header->length) + sizeof(DFileFrameHeader);
1159         len -= sizeof(FileDataFrame);
1160         block = (BlockFrame *)(void *)(block->list.next);
1161     }
1162     if (len == 0) {
1163         return;
1164     }
1165     if (NSTACKX_ATOM_ADD_RETURN(&fileManager->bytesTransferredInCurPeriod, (int32_t)len) >=
1166         (NSTACKX_MEGA_BYTES * MEGA_BYTES_TRANSFER_NOTICE_THRESHOLD)) {
1167         NSTACKX_ATOM_SET(&(fileManager->bytesTransferredInCurPeriod), 0);
1168         NotifyFileManagerMsg(fileManager, FILE_MANAGER_IN_PROGRESS);
1169     }
1170 }
1171 
FileManagerStopTask(FileManager * fileManager,uint16_t transId,TaskStopType stopType)1172 int32_t FileManagerStopTask(FileManager *fileManager, uint16_t transId, TaskStopType stopType)
1173 {
1174     FileListTask *fileList = NULL;
1175     List *list = NULL;
1176     uint8_t isFound = NSTACKX_FALSE;
1177     if (fileManager == NULL) {
1178         return NSTACKX_EINVAL;
1179     }
1180     if (PthreadMutexLock(&fileManager->taskList.lock) != 0) {
1181         DFILE_LOGE(TAG, "pthread mutex lock error");
1182         goto L_ERR_FILE_MANAGER;
1183     }
1184     LIST_FOR_EACH(list, &fileManager->taskList.head) {
1185         fileList = (FileListTask *)list;
1186         if (fileList != NULL && fileList->transId == transId) {
1187             isFound = NSTACKX_TRUE;
1188             break;
1189         }
1190     }
1191     if (isFound) {
1192         if (stopType == FILE_LIST_TRANSFER_FINISH) {
1193             fileManager->stoppedTasksBytesTransferred += fileList->totalBytes;
1194         } else {
1195             fileManager->stoppedTasksBytesTransferred += FileListGetBytesTransferred(fileList, fileManager->isSender);
1196         }
1197         if (fileManager->isSender && fileList->bindedSendBlockListIdx < NSTACKX_MAX_CLIENT_SEND_THREAD_NUM) {
1198             if (fileManager->sendBlockFrameListPara[fileList->bindedSendBlockListIdx].bandingTransNum > 0) {
1199                 fileManager->sendBlockFrameListPara[fileList->bindedSendBlockListIdx].bandingTransNum--;
1200             }
1201         }
1202         fileList->stopType = stopType;
1203         fileList->runStatus = FILE_LIST_STATUS_STOP;
1204         SemPost(&fileList->semStop);
1205         SemPost(&fileManager->semTaskListNotEmpty);
1206     }
1207 
1208     if (PthreadMutexUnlock(&fileManager->taskList.lock) != 0) {
1209         DFILE_LOGE(TAG, "pthread mutex unlock error");
1210         goto L_ERR_FILE_MANAGER;
1211     }
1212 
1213     if (isFound) {
1214         return NSTACKX_EOK;
1215     }
1216     DFILE_LOGE(TAG, "can't find target trans %u to stop", transId);
1217     return NSTACKX_EFAILED;
1218 L_ERR_FILE_MANAGER:
1219     fileManager->errCode = FILE_MANAGER_EMUTEX;
1220     NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1221     return NSTACKX_EFAILED;
1222 }
1223 
FileManagerSetMaxFrameLength(FileManager * fileManager,uint16_t maxFrameLength)1224 int32_t FileManagerSetMaxFrameLength(FileManager *fileManager, uint16_t maxFrameLength)
1225 {
1226     uint32_t standardDataLength;
1227     if (CheckManager(fileManager) != NSTACKX_EOK) {
1228         DFILE_LOGE(TAG, "Invalid input");
1229         return NSTACKX_EINVAL;
1230     }
1231     if (maxFrameLength <= offsetof(FileDataFrame, blockPayload) || maxFrameLength > NSTACKX_MAX_FRAME_SIZE) {
1232         DFILE_LOGE(TAG, "max frame length is illegal");
1233         return NSTACKX_EINVAL;
1234     }
1235     if (fileManager->keyLen > 0) {
1236         standardDataLength = maxFrameLength - offsetof(FileDataFrame, blockPayload);
1237         if (standardDataLength <= GCM_ADDED_LEN) {
1238             DFILE_LOGE(TAG, "max frame length is too small");
1239             return NSTACKX_EINVAL;
1240         }
1241     }
1242 
1243     /* different peerInfo->dataFrameSize in two connection, choose a small one for fileManager */
1244     if (fileManager->maxFrameLength == 0) {
1245         fileManager->maxFrameLength = maxFrameLength;
1246         return NSTACKX_EOK;
1247     }
1248 
1249     if (fileManager->maxFrameLength > maxFrameLength) {
1250         fileManager->maxFrameLength = maxFrameLength;
1251     }
1252 
1253     return NSTACKX_EOK;
1254 }
1255 
FileManagerSetRecvParaWithConnType(FileManager * fileManager,uint16_t connectType)1256 int32_t FileManagerSetRecvParaWithConnType(FileManager *fileManager, uint16_t connectType)
1257 {
1258     int32_t ret = NSTACKX_EOK;
1259     if (CheckReceiverManager(fileManager) != NSTACKX_EOK) {
1260         DFILE_LOGE(TAG, "Invalid input");
1261         return NSTACKX_EINVAL;
1262     }
1263     if (connectType == CONNECT_TYPE_WLAN) {
1264         fileManager->maxRecvBlockListSize = NSTACKX_WLAN_RECV_BLOCK_QUEUE_MAX_LEN * NSTACKX_FILE_MANAGER_THREAD_NUM;
1265     } else if (connectType == CONNECT_TYPE_P2P) {
1266         fileManager->maxRecvBlockListSize = NSTACKX_P2P_RECV_BLOCK_QUEUE_MAX_LEN * NSTACKX_FILE_MANAGER_THREAD_NUM;
1267     } else {
1268         DFILE_LOGE(TAG, "Invalid connect type");
1269         ret = NSTACKX_EFAILED;
1270     }
1271     DFILE_LOGI(TAG, "connect type is %u and max recv list size is %u", connectType, fileManager->maxRecvBlockListSize);
1272     return ret;
1273 }
1274 
FileManagerSetWritePath(FileManager * fileManager,const char * storagePath)1275 int32_t FileManagerSetWritePath(FileManager *fileManager, const char *storagePath)
1276 {
1277     if (CheckReceiverManager(fileManager) != NSTACKX_EOK || storagePath == NULL) {
1278         DFILE_LOGE(TAG, "Invalid input");
1279         return NSTACKX_EINVAL;
1280     }
1281 
1282     if (fileManager->typedPathNum > 0) {
1283         DFILE_LOGE(TAG, "typed storage paths has been set and can't set the common storage path");
1284         return NSTACKX_EINVAL;
1285     }
1286 
1287     fileManager->commonStoragePath = realpath(storagePath, NULL);
1288     if (fileManager->commonStoragePath == NULL) {
1289         DFILE_LOGE(TAG, "can't get canonicalized absolute pathname, error(%d)", errno);
1290         return NSTACKX_EFAILED;
1291     }
1292 
1293     if (!IsAccessiblePath(storagePath, W_OK, S_IFDIR)) {
1294         DFILE_LOGE(TAG, "storage path is not a valid writable folder");
1295         free(fileManager->commonStoragePath);
1296         fileManager->commonStoragePath = NULL;
1297         return NSTACKX_EFAILED;
1298     }
1299 
1300     return NSTACKX_EOK;
1301 }
1302 
FileManagerSetWritePathList(FileManager * fileManager,char * path[],uint16_t * pathType,uint16_t pathNum)1303 int32_t FileManagerSetWritePathList(FileManager *fileManager, char *path[], uint16_t *pathType, uint16_t pathNum)
1304 {
1305     if (CheckReceiverManager(fileManager) != NSTACKX_EOK || path == NULL || pathType == NULL || pathNum == 0 ||
1306         pathNum > NSTACKX_MAX_STORAGE_PATH_NUM) {
1307         DFILE_LOGE(TAG, "Invalid input");
1308         return NSTACKX_EINVAL;
1309     }
1310 
1311     if (fileManager->commonStoragePath != NULL) {
1312         DFILE_LOGE(TAG, "common storage paths has been set and can't set the typed storage path");
1313         return NSTACKX_EFAILED;
1314     }
1315 
1316     for (uint16_t i = 0; i < pathNum; i++) {
1317         fileManager->pathList[i].storagePath = path[i];
1318         fileManager->pathList[i].pathType = pathType[i];
1319         DFILE_LOGI(TAG, "the %uth path, type %u", i, fileManager->pathList[i].pathType);
1320     }
1321     fileManager->typedPathNum = pathNum;
1322     return NSTACKX_EOK;
1323 }
1324 
AtomicParameterInit(FileManager * fileManager)1325 static int32_t AtomicParameterInit(FileManager *fileManager)
1326 {
1327     uint32_t i = 0;
1328     SendBlockFrameListPara *para = NULL;
1329     uint32_t sendListSize = fileManager->maxSendBlockListSize;
1330 
1331     if (SemInit(&fileManager->semTaskListNotEmpty, 0, 0) != 0) {
1332         DFILE_LOGE(TAG, "semTaskListNotEmpty SemInit error");
1333         return NSTACKX_EFAILED;
1334     }
1335 
1336     if (fileManager->isSender) {
1337         for (i = 0; i < fileManager->sendFrameListNum; i++) {
1338             para = &fileManager->sendBlockFrameListPara[i];
1339             if (SemInit(&para->semBlockListNotFull, 0, sendListSize) != 0) {
1340                 DFILE_LOGE(TAG, "semTaskListNotEmpty SemInit error");
1341                 goto L_ERR_FILE_MANAGER;
1342             }
1343         }
1344     }
1345     return NSTACKX_EOK;
1346 L_ERR_FILE_MANAGER:
1347     SemDestroy(&fileManager->semTaskListNotEmpty);
1348     while (i > 0) {
1349         para = &fileManager->sendBlockFrameListPara[i - 1];
1350         SemDestroy(&para->semBlockListNotFull);
1351         i--;
1352     }
1353     return NSTACKX_EFAILED;
1354 }
1355 
AtomicParameterDestory(FileManager * fileManager)1356 static void AtomicParameterDestory(FileManager *fileManager)
1357 {
1358     SemDestroy(&fileManager->semTaskListNotEmpty);
1359     if (fileManager->isSender) {
1360         for (uint32_t i = 0; i < fileManager->sendFrameListNum; i++) {
1361             SemDestroy(&fileManager->sendBlockFrameListPara[i].semBlockListNotFull);
1362         }
1363     }
1364 }
1365 
InitAllCacheList(FileManager * fileManager)1366 static int32_t InitAllCacheList(FileManager *fileManager)
1367 {
1368     if (MutexListInit(&fileManager->taskList, NSTACKX_MAX_PROCESSING_TASK_NUM) != NSTACKX_EOK) {
1369         DFILE_LOGE(TAG, "taskList InitList error");
1370         return NSTACKX_EFAILED;
1371     }
1372 
1373     if (fileManager->isSender) {
1374         if (InitSendBlockLists(fileManager) != NSTACKX_EOK) {
1375             MutexListDestory(&fileManager->taskList);
1376             DFILE_LOGE(TAG, "sendBlockFrameList InitList error");
1377             return NSTACKX_EFAILED;
1378         }
1379     }
1380     return NSTACKX_EOK;
1381 }
1382 
FileManagerInit(FileManager * fileManager,FileManagerMsgPara * msgPara,const uint8_t * key,uint32_t keyLen,uint16_t connType)1383 static int32_t FileManagerInit(FileManager *fileManager, FileManagerMsgPara *msgPara, const uint8_t *key,
1384                                uint32_t keyLen, uint16_t connType)
1385 {
1386     fileManager->runStatus = FILE_MANAGE_RUN;
1387     fileManager->errCode = FILE_MANAGER_EOK;
1388     fileManager->transFlag = NSTACKX_FALSE;
1389     if (fileManager->isSender) {
1390         fileManager->sendFrameListNum = GetSendListNum();
1391         fileManager->maxSendBlockListSize = GetMaxSendListSize(connType);
1392         if (fileManager->maxSendBlockListSize == 0 || fileManager->sendFrameListNum == 0) {
1393             DFILE_LOGE(TAG, "can't get valid send frame list num or size");
1394             return NSTACKX_EFAILED;
1395         }
1396         DFILE_LOGI(TAG, "connect type is %u and send frame list number is %u max send list size is %u",
1397             connType, fileManager->sendFrameListNum, fileManager->maxSendBlockListSize);
1398     }
1399     if (IsEpollDescValid(msgPara->epollfd) && msgPara->msgReceiver != NULL) {
1400         fileManager->msgReceiver = msgPara->msgReceiver;
1401         fileManager->context = msgPara->context;
1402         fileManager->epollfd = msgPara->epollfd;
1403         fileManager->eventNodeChain = msgPara->eventNodeChain;
1404     }
1405 
1406     if (keyLen > 0) {
1407         if ((keyLen != AES_128_KEY_LENGTH && keyLen != CHACHA20_KEY_LENGTH) || key == NULL ||
1408             memcpy_s(fileManager->key, sizeof(fileManager->key), key, keyLen) != EOK) {
1409             DFILE_LOGE(TAG, "can't get valid key info.");
1410             return NSTACKX_EFAILED;
1411         }
1412         fileManager->keyLen = keyLen;
1413     }
1414     return NSTACKX_EOK;
1415 }
1416 
FileManagerCreate(uint8_t isSender,FileManagerMsgPara * msgPara,const uint8_t * key,uint32_t keyLen,uint16_t connType)1417 FileManager *FileManagerCreate(uint8_t isSender, FileManagerMsgPara *msgPara, const uint8_t *key,
1418                                uint32_t keyLen, uint16_t connType)
1419 {
1420     FileManager *fileManager = NULL;
1421     if (isSender && (connType != CONNECT_TYPE_P2P && connType != CONNECT_TYPE_WLAN)) {
1422         DFILE_LOGE(TAG, "connType for sender is illagal");
1423         return NULL;
1424     }
1425     fileManager = (FileManager *)calloc(1, sizeof(FileManager));
1426     if (fileManager == NULL) {
1427         DFILE_LOGE(TAG, "fileManager calloc error");
1428         return NULL;
1429     }
1430     fileManager->isSender = isSender;
1431     if (FileManagerInit(fileManager, msgPara, key, keyLen, connType) != NSTACKX_EOK) {
1432         (void)memset_s(fileManager, sizeof(FileManager), 0, sizeof(FileManager));
1433         free(fileManager);
1434         return NULL;
1435     }
1436 
1437     if (InitAllCacheList(fileManager) != NSTACKX_EOK) {
1438         (void)memset_s(fileManager, sizeof(FileManager), 0, sizeof(FileManager));
1439         free(fileManager);
1440         return NULL;
1441     }
1442 
1443     if (AtomicParameterInit(fileManager) != NSTACKX_EOK) {
1444         goto L_ERR_FILE_MANAGER;
1445     }
1446 
1447     if (CreateFMThread(fileManager) != NSTACKX_EOK) {
1448         AtomicParameterDestory(fileManager);
1449         goto L_ERR_FILE_MANAGER;
1450     }
1451 
1452     return fileManager;
1453 
1454 L_ERR_FILE_MANAGER:
1455     MutexListDestory(&fileManager->taskList);
1456     if (fileManager->isSender) {
1457         for (uint32_t i = 0; i < fileManager->sendFrameListNum; i++) {
1458             MutexListDestory(&fileManager->sendBlockFrameListPara[i].sendBlockFrameList);
1459             fileManager->sendBlockFrameListPara[i].sendRetranListTail = NULL;
1460         }
1461     }
1462     (void)memset_s(fileManager, sizeof(FileManager), 0, sizeof(FileManager));
1463     free(fileManager);
1464     return NULL;
1465 }
1466 
AddRecvFileInfo(FileBaseInfo * fileBasicInfo,FileListTask * fmFileList,uint16_t standardBlockSize)1467 static int32_t AddRecvFileInfo(FileBaseInfo *fileBasicInfo, FileListTask *fmFileList, uint16_t standardBlockSize)
1468 {
1469     uint32_t i;
1470     char *fileName = NULL;
1471     FileInfo *fileInfo = NULL;
1472     for (i = 0; i < fmFileList->fileNum; i++) {
1473         if (fileBasicInfo[i].fileName == NULL || !IsFileNameLegal(fileBasicInfo[i].fileName)) {
1474             DFILE_LOGE(TAG, "the %uth input fileName is NULL", i);
1475             goto L_ERR_FILE_MANAGER;
1476         }
1477         fileName = fileBasicInfo[i].fileName;
1478         fileInfo = &fmFileList->fileInfo[i];
1479         fileInfo->fileName = (char *)calloc(strlen(fileName) + 1, sizeof(char));
1480         if (fileInfo->fileName == NULL) {
1481             DFILE_LOGE(TAG, "fileName calloc error");
1482             goto L_ERR_FILE_MANAGER;
1483         }
1484 
1485         if (strcpy_s(fileInfo->fileName, strlen(fileName) + 1, fileName) != NSTACKX_EOK) {
1486             DFILE_LOGE(TAG, "%uth fileName copy failed", i);
1487             goto L_ERR_FILE_MANAGER;
1488         }
1489 
1490         fileInfo->fileSize = fileBasicInfo[i].fileSize;
1491         fileInfo->startOffset = fileBasicInfo[i].startOffset;
1492         fileInfo->fileId = fileBasicInfo[i].fileId;
1493         fileInfo->standardBlockSize = standardBlockSize;
1494         fileInfo->totalBlockNum = (uint32_t)(fileInfo->fileSize / standardBlockSize);
1495         if (fileInfo->fileSize % standardBlockSize != 0) {
1496             fileInfo->totalBlockNum++;
1497         }
1498         fmFileList->totalBytes += fileInfo->fileSize;
1499         fileInfo->receivedBlockNum = 0;
1500         fileInfo->fd = NSTACKX_INVALID_FD;
1501         fileInfo->errCode = FILE_MANAGER_EOK;
1502         fileInfo->fileOffset = 0;
1503     }
1504     return NSTACKX_EOK;
1505 L_ERR_FILE_MANAGER:
1506     for (i = 0; i < fmFileList->fileNum; i++) {
1507         free(fmFileList->fileInfo[i].fileName);
1508         fmFileList->fileInfo[i].fileName = NULL;
1509     }
1510     return NSTACKX_EFAILED;
1511 }
1512 
CreateRecvFileList(RecvFileListInfo * fileListInfo,const char * storagePath,uint16_t standardBlockSize,FileListMsgPara * msgPara,uint32_t maxRecvBlockListSize)1513 static FileListTask *CreateRecvFileList(RecvFileListInfo *fileListInfo, const char *storagePath,
1514     uint16_t standardBlockSize, FileListMsgPara *msgPara, uint32_t maxRecvBlockListSize)
1515 {
1516     FileListTask *fmFileList = NULL;
1517     fmFileList = (FileListTask *)calloc(1, sizeof(FileListTask));
1518     if (fmFileList == NULL) {
1519         DFILE_LOGE(TAG, "file list calloc error");
1520         return NULL;
1521     }
1522     fmFileList->transId = fileListInfo->transId;
1523     fmFileList->fileNum = fileListInfo->fileNum;
1524     fmFileList->storagePath = storagePath;
1525     fmFileList->noSyncFlag = fileListInfo->noSyncFlag;
1526     if (SemInit(&fmFileList->semStop, 0, 0) != 0) {
1527         DFILE_LOGE(TAG, "SemInit error");
1528         free(fmFileList);
1529         return NULL;
1530     }
1531     fmFileList->runStatus = FILE_LIST_STATUS_IDLE;
1532     fmFileList->stopType = FILE_LIST_TRANSFER_FINISH;
1533     fmFileList->isOccupied = NSTACKX_FALSE;
1534     fmFileList->errCode = FILE_MANAGER_EOK;
1535     ListInitHead(&fmFileList->innerRecvBlockHead);
1536     if (MutexListInit(&fmFileList->recvBlockList, maxRecvBlockListSize) != NSTACKX_EOK) {
1537         DFILE_LOGE(TAG, "receive block list init error");
1538         goto L_ERR_FILE_MANAGER;
1539     }
1540     fmFileList->recvFileProcessed = 0;
1541     fmFileList->isRecvEmptyFilesCreated = NSTACKX_FALSE;
1542     if (AddRecvFileInfo(fileListInfo->fileBasicInfo, fmFileList, standardBlockSize) != NSTACKX_EOK) {
1543         MutexListDestory(&fmFileList->recvBlockList);
1544         goto L_ERR_FILE_MANAGER;
1545     }
1546     if (msgPara != NULL) {
1547         fmFileList->msgReceiver = msgPara->msgReceiver;
1548         fmFileList->context = msgPara->context;
1549     }
1550     return fmFileList;
1551 L_ERR_FILE_MANAGER:
1552     SemDestroy(&fmFileList->semStop);
1553     (void)memset_s(fmFileList, sizeof(FileListTask), 0, sizeof(FileListTask));
1554     free(fmFileList);
1555     return NULL;
1556 }
1557 
GetStoragePathByType(FileManager * fileManager,uint16_t pathType)1558 char *GetStoragePathByType(FileManager *fileManager, uint16_t pathType)
1559 {
1560     if (pathType == 0) {
1561         return fileManager->commonStoragePath;
1562     }
1563     for (uint16_t i = 0; i < fileManager->typedPathNum; i++) {
1564         if (fileManager->pathList[i].pathType == pathType) {
1565             return fileManager->pathList[i].storagePath;
1566         }
1567     }
1568     return NULL;
1569 }
1570 
FileManagerRecvFileTask(FileManager * fileManager,RecvFileListInfo * fileListInfo,FileListMsgPara * msgPara)1571 int32_t FileManagerRecvFileTask(FileManager *fileManager, RecvFileListInfo *fileListInfo, FileListMsgPara *msgPara)
1572 {
1573     FileListTask *fmFileList = NULL;
1574     uint16_t standardBlockSize;
1575     const char *storagePath = NULL;
1576     if (CheckReceiverManager(fileManager) != NSTACKX_EOK || fileManager->maxRecvBlockListSize == 0) {
1577         return NSTACKX_EINVAL;
1578     }
1579 
1580     if (fileManager->taskList.size == fileManager->taskList.maxSize) {
1581         DFILE_LOGE(TAG, "task list is full");
1582         return NSTACKX_EFAILED;
1583     }
1584 
1585     storagePath = GetStoragePathByType(fileManager, fileListInfo->pathType);
1586     if (storagePath == NULL) {
1587         DFILE_LOGE(TAG, "can't get storage path for pathType %u", fileListInfo->pathType);
1588         return NSTACKX_EFAILED;
1589     }
1590 
1591     standardBlockSize = GetStandardBlockSize(fileManager);
1592     if (standardBlockSize == 0) {
1593         DFILE_LOGE(TAG, "max frame length is too small");
1594         return NSTACKX_EFAILED;
1595     }
1596     fmFileList = CreateRecvFileList(fileListInfo, storagePath, standardBlockSize, msgPara,
1597                                     fileManager->maxRecvBlockListSize);
1598     if (fmFileList == NULL) {
1599         DFILE_LOGE(TAG, "Creat file list error");
1600         return NSTACKX_EFAILED;
1601     }
1602     fmFileList->epollfd = fileManager->epollfd;
1603     fmFileList->eventNodeChain = fileManager->eventNodeChain;
1604     fmFileList->maxFrameLength = fileManager->maxFrameLength;
1605     if (fileManager->keyLen > 0 && SetCryptPara(fmFileList, fileManager->key, fileManager->keyLen) != NSTACKX_EOK) {
1606         ClearRecvFileList(fmFileList);
1607         DFILE_LOGE(TAG, "fail to set crypto para");
1608         return NSTACKX_EFAILED;
1609     }
1610 
1611     if (MutexListAddNode(&fileManager->taskList, &fmFileList->list, NSTACKX_FALSE) != NSTACKX_EOK) {
1612         DFILE_LOGE(TAG, "Add task to list error");
1613         ClearRecvFileList(fmFileList);
1614         fileManager->errCode = FILE_MANAGER_EMUTEX;
1615         NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1616         return NSTACKX_EFAILED;
1617     }
1618     fileManager->totalBytes += fmFileList->totalBytes;
1619     SemPost(&fileManager->semTaskListNotEmpty);
1620     return NSTACKX_EOK;
1621 }
1622 
PushRecvBlockFrame(FileListTask * fileList,FileDataFrame * frame)1623 static int32_t PushRecvBlockFrame(FileListTask *fileList, FileDataFrame *frame)
1624 {
1625     BlockFrame *blockFrame = NULL;
1626     int32_t ret;
1627     uint8_t isRetran;
1628 
1629     blockFrame = (BlockFrame *)calloc(1, sizeof(BlockFrame));
1630     if (blockFrame == NULL) {
1631         DFILE_LOGE(TAG, "memory calloc failed");
1632         return FILE_MANAGER_ENOMEM;
1633     }
1634     blockFrame->fileDataFrame = frame;
1635     isRetran = frame->header.flag & NSTACKX_DFILE_DATA_FRAME_RETRAN_FLAG;
1636     if (isRetran) {
1637         ret = MutexListAddNode(&fileList->recvBlockList, &blockFrame->list, NSTACKX_TRUE);
1638     } else {
1639         ret = MutexListAddNode(&fileList->recvBlockList, &blockFrame->list, NSTACKX_FALSE);
1640     }
1641     if (ret != NSTACKX_EOK) {
1642         free(blockFrame);
1643         DFILE_LOGE(TAG, "add node to recv block list failed");
1644         return FILE_MANAGER_EMUTEX;
1645     }
1646     SemPost(&fileList->semStop);
1647     return FILE_MANAGER_EOK;
1648 }
1649 
CheckFileBlockListOverflow(FileManager * fileManager)1650 static int32_t CheckFileBlockListOverflow(FileManager *fileManager)
1651 {
1652     uint32_t recvListAllSize;
1653     uint32_t recvInnerAllSize;
1654 
1655     if (GetFileBlockListSize(&fileManager->taskList, &recvListAllSize, &recvInnerAllSize) != NSTACKX_EOK) {
1656         fileManager->errCode = FILE_MANAGER_EMUTEX;
1657         NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1658         DFILE_LOGE(TAG, "failed to get GetFileBlockListSize");
1659         return NSTACKX_EFAILED;
1660     }
1661     if (recvListAllSize >= fileManager->maxRecvBlockListSize) {
1662         return NSTACKX_EFAILED;
1663     }
1664 
1665     return NSTACKX_EOK;
1666 }
1667 
FileManagerFileWrite(FileManager * fileManager,FileDataFrame * frame)1668 int32_t FileManagerFileWrite(FileManager *fileManager, FileDataFrame *frame)
1669 {
1670     uint16_t transId;
1671     FileListTask *fileList = NULL;
1672     uint8_t isErrorOccurred = NSTACKX_FALSE;
1673     BlockFrame block = {
1674         .list = {NULL, NULL},
1675         .fileDataFrame = frame,
1676     };
1677     if (CheckReceiverManager(fileManager) != NSTACKX_EOK) {
1678         DFILE_LOGE(TAG, "invalid input");
1679         return NSTACKX_EINVAL;
1680     }
1681     transId = ntohs(frame->header.transId);
1682     fileList = GetFileListById(&fileManager->taskList, transId, &isErrorOccurred);
1683     if (isErrorOccurred || fileList == NULL) {
1684         fileManager->errCode = FILE_MANAGER_EMUTEX;
1685         NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1686         DFILE_LOGE(TAG, "failed to get target fileList %u", transId);
1687         return NSTACKX_EFAILED;
1688     }
1689     if (CheckFilelistNotStop(fileList) != NSTACKX_EOK) {
1690         DFILE_LOGE(TAG, "target file list %u is not available", transId);
1691         return NSTACKX_EFAILED;
1692     }
1693 
1694     if (CheckFileBlockListOverflow(fileManager) != NSTACKX_EOK) {
1695         return NSTACKX_EFAILED;
1696     }
1697     RefreshBytesTransFerred(fileManager, &block);
1698     fileList->errCode = PushRecvBlockFrame(fileList, frame);
1699     if (fileList->errCode != FILE_MANAGER_EOK) {
1700         DFILE_LOGE(TAG, "add frame to recv block list failed");
1701         NotifyFileListMsg(fileList, FILE_MANAGER_RECEIVE_FAIL);
1702         return NSTACKX_EFAILED;
1703     }
1704     return NSTACKX_EOK;
1705 }
1706 
ClearTask(FileManager * fileManager)1707 static void ClearTask(FileManager *fileManager)
1708 {
1709     FileListTask *fileList = NULL;
1710 
1711     while (fileManager->taskList.size > 0) {
1712         if (PthreadMutexLock(&fileManager->taskList.lock) != 0) {
1713             DFILE_LOGE(TAG, "pthread mutex lock error");
1714             return;
1715         }
1716         fileList = (FileListTask *)ListPopFront(&fileManager->taskList.head);
1717         fileManager->taskList.size--;
1718         if (PthreadMutexUnlock(&fileManager->taskList.lock) != 0) {
1719             DFILE_LOGE(TAG, "pthread mutex unlock error");
1720         }
1721         if (fileList == NULL) {
1722             continue;
1723         }
1724         ClearFileList(fileManager, fileList);
1725         fileList = NULL;
1726     }
1727     MutexListDestory(&fileManager->taskList);
1728 }
1729 
FileManagerDestroy(FileManager * fileManager)1730 void FileManagerDestroy(FileManager *fileManager)
1731 {
1732     if (fileManager == NULL) {
1733         return;
1734     }
1735     if (fileManager->isSender) {
1736         ClearSendFrameList(fileManager);
1737     }
1738     ClearTask(fileManager);
1739     AtomicParameterDestory(fileManager);
1740     free(fileManager->commonStoragePath);
1741     fileManager->commonStoragePath = NULL;
1742     for (uint16_t i = 0; i < fileManager->typedPathNum; i++) {
1743         free(fileManager->pathList[i].storagePath);
1744         fileManager->pathList[i].storagePath = NULL;
1745     }
1746     (void)memset_s(fileManager, sizeof(FileManager), 0, sizeof(FileManager));
1747     free(fileManager);
1748     fileManager = NULL;
1749     DFILE_LOGI(TAG, "Destroy successfully!");
1750 }
1751 
FileManagerIsRecvBlockWritable(FileManager * fileManager,uint16_t transId)1752 uint8_t FileManagerIsRecvBlockWritable(FileManager *fileManager, uint16_t transId)
1753 {
1754     if (fileManager == NULL || fileManager->isSender || transId == 0) {
1755         return NSTACKX_FALSE;
1756     }
1757 
1758     if (CheckFileBlockListOverflow(fileManager) != NSTACKX_EOK) {
1759         return NSTACKX_FALSE;
1760     }
1761 
1762     return NSTACKX_TRUE;
1763 }
1764 
FileManagerGetTotalBytes(FileManager * fileManager,uint64_t * totalBytes)1765 int32_t FileManagerGetTotalBytes(FileManager *fileManager, uint64_t *totalBytes)
1766 {
1767     if (fileManager == NULL) {
1768         return NSTACKX_EFAILED;
1769     }
1770     *totalBytes = fileManager->totalBytes;
1771     return NSTACKX_EOK;
1772 }
1773 
FileManagerGetBytesTransferred(FileManager * fileManager,uint64_t * bytesTransferred)1774 int32_t FileManagerGetBytesTransferred(FileManager *fileManager, uint64_t *bytesTransferred)
1775 {
1776     FileListTask *fileList = NULL;
1777     uint64_t runningTaskBytesTransferred = 0;
1778     uint64_t ret;
1779     List *list = NULL;
1780     if (fileManager == NULL || bytesTransferred == NULL) {
1781         return 0;
1782     }
1783     if (PthreadMutexLock(&fileManager->taskList.lock) != 0) {
1784         DFILE_LOGE(TAG, "pthread mutex lock error");
1785         goto L_ERR_FILE_MANAGER;
1786     }
1787     LIST_FOR_EACH(list, &fileManager->taskList.head) {
1788         fileList = (FileListTask *)list;
1789         if (fileList == NULL || fileList->runStatus == FILE_LIST_STATUS_STOP) {
1790             continue;
1791         }
1792         runningTaskBytesTransferred += FileListGetBytesTransferred(fileList, fileManager->isSender);
1793     }
1794     if (PthreadMutexUnlock(&fileManager->taskList.lock) != 0) {
1795         DFILE_LOGE(TAG, "pthread mutex unlock error");
1796         goto L_ERR_FILE_MANAGER;
1797     }
1798 
1799     ret = runningTaskBytesTransferred + fileManager->stoppedTasksBytesTransferred;
1800     if (ret > fileManager->totalBytes) {
1801         DFILE_LOGE(TAG, "result is too large");
1802         return NSTACKX_EFAILED;
1803     }
1804     /* for sender, can't return all bytes before there is unstopped task. */
1805     if (ret == fileManager->totalBytes && fileManager->isSender && runningTaskBytesTransferred > 0) {
1806         if (ret > NSTACKX_DEFAULT_FRAME_SIZE) {
1807             ret -= NSTACKX_DEFAULT_FRAME_SIZE;
1808         } else {
1809             ret = 0;
1810         }
1811     }
1812     if (ret <= fileManager->bytesTransferredLastRecord) {
1813         ret = fileManager->bytesTransferredLastRecord;
1814     } else {
1815         fileManager->bytesTransferredLastRecord = ret;
1816     }
1817     *bytesTransferred = ret;
1818     return NSTACKX_EOK;
1819 L_ERR_FILE_MANAGER:
1820     fileManager->errCode = FILE_MANAGER_EMUTEX;
1821     NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1822     return NSTACKX_EFAILED;
1823 }
1824 
FileManagerGetTransUpdateInfo(FileManager * fileManager,uint16_t transId,uint64_t * totalBytes,uint64_t * bytesTransferred)1825 int32_t FileManagerGetTransUpdateInfo(FileManager *fileManager, uint16_t transId, uint64_t *totalBytes,
1826     uint64_t *bytesTransferred)
1827 {
1828     FileListTask *fileList = NULL;
1829     uint8_t isFound = NSTACKX_FALSE;
1830     List *list = NULL;
1831     uint64_t totalBytesPtr, bytesTransPtr;
1832     if (fileManager == NULL || totalBytes == NULL || bytesTransferred == NULL) {
1833         return NSTACKX_EFAILED;
1834     }
1835     if (PthreadMutexLock(&fileManager->taskList.lock) != 0) {
1836         DFILE_LOGE(TAG, "pthread mutex lock error");
1837         goto L_ERR_FILE_MANAGER;
1838     }
1839     LIST_FOR_EACH(list, &fileManager->taskList.head) {
1840         fileList = (FileListTask *)list;
1841         if (fileList != NULL && fileList->transId == transId) {
1842             bytesTransPtr = FileListGetBytesTransferred(fileList, fileManager->isSender);
1843             totalBytesPtr = fileList->totalBytes;
1844             isFound = NSTACKX_TRUE;
1845             break;
1846         }
1847     }
1848     if (PthreadMutexUnlock(&fileManager->taskList.lock) != 0) {
1849         DFILE_LOGE(TAG, "pthread mutex unlock error");
1850         goto L_ERR_FILE_MANAGER;
1851     }
1852 
1853     if (!isFound || bytesTransPtr > totalBytesPtr) {
1854         DFILE_LOGE(TAG, "can't find target trans %u or the result is illegal", transId);
1855         return NSTACKX_EFAILED;
1856     }
1857     *totalBytes = totalBytesPtr;
1858     *bytesTransferred = bytesTransPtr;
1859     return NSTACKX_EOK;
1860 
1861 L_ERR_FILE_MANAGER:
1862     fileManager->errCode = FILE_MANAGER_EMUTEX;
1863     NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1864     return NSTACKX_EFAILED;
1865 }
1866 
GetBlockHeadFlag(uint8_t isStartFrame,uint8_t isEndFrame)1867 uint8_t GetBlockHeadFlag(uint8_t isStartFrame, uint8_t isEndFrame)
1868 {
1869     uint8_t headFlag;
1870 
1871     if (isEndFrame) {
1872         headFlag = NSTACKX_DFILE_DATA_FRAME_END_FLAG;
1873     } else if (isStartFrame) {
1874         headFlag = NSTACKX_DFILE_DATA_FRAME_START_FLAG;
1875     } else {
1876         headFlag = NSTACKX_DFILE_DATA_FRAME_CONTINUE_FLAG;
1877     }
1878     return headFlag;
1879 }
1880 
FileManagerCLearReadOutSet(FileListTask * fileList)1881 void FileManagerCLearReadOutSet(FileListTask *fileList)
1882 {
1883     if (PthreadMutexLock(&fileList->newReadOutSet.lock) != 0) {
1884         DFILE_LOGE(TAG, "pthread mutex lock error");
1885         return;
1886     }
1887 
1888     fileList->newReadOutSet.blockSequence = 0;
1889     fileList->newReadOutSet.fileId = 0;
1890 
1891     if (PthreadMutexUnlock(&fileList->newReadOutSet.lock) != 0) {
1892         DFILE_LOGE(TAG, "pthread mutex unlock error");
1893         return;
1894     }
1895 }
1896 
FileGetRecvStatus(FileInfo * fileInfo)1897 static FileRecvState FileGetRecvStatus(FileInfo *fileInfo)
1898 {
1899     if (fileInfo->errCode != FILE_MANAGER_EOK) {
1900         return STATE_RECEIVE_DONE_FAIL;
1901     } else {
1902         if (fileInfo->fileSize == 0 || fileInfo->receivedBlockNum == fileInfo->totalBlockNum) {
1903             return STATE_RECEIVE_DONE_SUCCESSFULLY;
1904         } else {
1905             return STATE_RECEIVE_ONGOING;
1906         }
1907     }
1908 }
1909 
TaskGetReceivedFiles(FileListTask * fileList,uint16_t fileIdList[],uint8_t fileIdSuccessFlag[],uint32_t * fileNum)1910 static int32_t TaskGetReceivedFiles(FileListTask *fileList, uint16_t fileIdList[],
1911                                     uint8_t fileIdSuccessFlag[], uint32_t *fileNum)
1912 {
1913     uint32_t count = 0;
1914     FileRecvState state;
1915 
1916     if (fileNum == NULL || *fileNum == 0) {
1917         return NSTACKX_EFAILED;
1918     }
1919 
1920     if (fileList == NULL) {
1921         *fileNum = 0;
1922         return NSTACKX_EFAILED;
1923     }
1924 
1925     for (uint32_t i = 0; i < fileList->fileNum; i++) {
1926         state = FileGetRecvStatus(&fileList->fileInfo[i]);
1927         if (state == STATE_RECEIVE_ONGOING) {
1928             continue;
1929         }
1930         fileIdList[count] = fileList->fileInfo[i].fileId;
1931         if (state == STATE_RECEIVE_DONE_SUCCESSFULLY) {
1932             fileIdSuccessFlag[count] = NSTACKX_TRUE;
1933         } else {
1934             fileIdSuccessFlag[count] = NSTACKX_FALSE;
1935         }
1936         count++;
1937         if (count >= *fileNum) {
1938             return NSTACKX_EOK;
1939         }
1940     }
1941     *fileNum = count;
1942     return NSTACKX_EOK;
1943 }
1944 
FileManagerGetReceivedFiles(FileManager * fileManager,uint16_t transId,uint16_t fileIdList[],uint8_t fileIdSuccessFlag[],uint32_t * fileNum)1945 int32_t FileManagerGetReceivedFiles(FileManager *fileManager, uint16_t transId, uint16_t fileIdList[],
1946                                     uint8_t fileIdSuccessFlag[], uint32_t *fileNum)
1947 {
1948     FileListTask *fileList = NULL;
1949     uint8_t isErrorOccurred;
1950 
1951     if (fileNum == NULL || *fileNum == 0) {
1952         return NSTACKX_EFAILED;
1953     }
1954 
1955     if (fileManager == NULL || fileManager->isSender) {
1956         *fileNum = 0;
1957         return NSTACKX_EFAILED;
1958     }
1959 
1960     fileList = GetFileListById(&fileManager->taskList, transId, &isErrorOccurred);
1961     if (isErrorOccurred) {
1962         fileManager->errCode = FILE_MANAGER_EMUTEX;
1963         NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1964         *fileNum = 0;
1965         return NSTACKX_EFAILED;
1966     }
1967     if (fileList == NULL) {
1968         *fileNum = 0;
1969         return NSTACKX_EFAILED;
1970     }
1971     return TaskGetReceivedFiles(fileList, fileIdList, fileIdSuccessFlag, fileNum);
1972 }
1973 
FileManagerSetAllDataReceived(FileManager * fileManager,uint16_t transId)1974 int32_t FileManagerSetAllDataReceived(FileManager *fileManager, uint16_t transId)
1975 {
1976     FileListTask *fileList = NULL;
1977     int32_t ret = NSTACKX_EFAILED;
1978     List *list = NULL;
1979     if (CheckReceiverManager(fileManager) != NSTACKX_EOK) {
1980         DFILE_LOGE(TAG, "invalid input");
1981         return NSTACKX_EINVAL;
1982     }
1983     if (PthreadMutexLock(&fileManager->taskList.lock) != 0) {
1984         DFILE_LOGE(TAG, "pthread mutex lock error");
1985         goto L_ERR_FILE_MANAGER;
1986     }
1987     LIST_FOR_EACH(list, &fileManager->taskList.head) {
1988         fileList = (FileListTask *)list;
1989         if (fileList->transId == transId) {
1990             fileList->allFileDataReceived = NSTACKX_TRUE;
1991             SemPost(&fileList->semStop);
1992             ret = NSTACKX_EOK;
1993             break;
1994         }
1995     }
1996     if (PthreadMutexUnlock(&fileManager->taskList.lock) != 0) {
1997         DFILE_LOGE(TAG, "pthread mutex unlock error");
1998         goto L_ERR_FILE_MANAGER;
1999     }
2000     return ret;
2001 L_ERR_FILE_MANAGER:
2002     fileManager->errCode = FILE_MANAGER_EMUTEX;
2003     NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
2004     return NSTACKX_EFAILED;
2005 }
2006 
ClearTransStateList(DFileSession * session)2007 void ClearTransStateList(DFileSession *session)
2008 {
2009     List *tmp = NULL;
2010     List *pos = NULL;
2011     if (session == NULL || ListIsEmpty(&session->tranIdStateList.head)) {
2012         return;
2013     }
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