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