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