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(¶->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(¶->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(¶->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