• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "nstackx_file_manager_client.h"
17 
18 #include "securec.h"
19 
20 #include "nstackx_dev.h"
21 #include "nstackx_dfile_mp.h"
22 #include "nstackx_dfile_session.h"
23 #include "nstackx_error.h"
24 #include "nstackx_event.h"
25 #include "nstackx_dfile_log.h"
26 #ifdef MBEDTLS_INCLUDED
27 #include "nstackx_mbedtls.h"
28 #else
29 #include "nstackx_openssl.h"
30 #endif
31 #include "nstackx_util.h"
32 
33 #define TAG "nStackXDFile"
34 
CheckSendListFullAndWait(FileManager * fileManager,sem_t * sem)35 static void CheckSendListFullAndWait(FileManager *fileManager, sem_t *sem)
36 {
37     int32_t semValue;
38     SemGetValue(sem, &semValue);
39     if (semValue == 0) {
40         fileManager->sendListFullTimes++;
41     }
42     SemWait(sem);
43 }
44 
ReadFromFile(FileManager * fileManager,FileInfo * fileInfo,uint64_t offset,uint8_t * buffer,uint32_t bufferLength)45 static int32_t ReadFromFile(FileManager *fileManager, FileInfo *fileInfo, uint64_t offset, uint8_t *buffer,
46     uint32_t bufferLength)
47 {
48     uint32_t readLength;
49     DFileSession *session = fileManager->context;
50 
51     offset += fileInfo->startOffset;
52     if (fileInfo->tarData != NULL) {
53         if (offset + bufferLength > fileInfo->writeOffset ||
54             memcpy_s(buffer, bufferLength, fileInfo->tarData + offset, bufferLength) != EOK) {
55             DFILE_LOGE(TAG, "memcpy_s failed");
56             return NSTACKX_EFAILED;
57         }
58         fileInfo->fileOffset = offset + bufferLength;
59         return NSTACKX_EOK;
60     }
61     if (fileInfo->fd == NSTACKX_INVALID_FD) {
62 #ifdef BUILD_FOR_WINDOWS
63         fileInfo->fd = fopen(fileInfo->fileName, "rb");
64 #else
65         fileInfo->fd = open(fileInfo->fileName, O_RDONLY);
66 #endif
67         if (fileInfo->fd == NSTACKX_INVALID_FD) {
68             fileInfo->errCode = ConvertErrCode(errno);
69             DFILE_LOGE(TAG, "file open failed, path %s errno %d", fileInfo->fileName, errno);
70             return NSTACKX_EFAILED;
71         }
72         fileInfo->fileOffset = 0;
73     }
74 
75     if (SetFileOffset(fileInfo, offset) != NSTACKX_EOK) {
76         fileInfo->errCode = FILE_MANAGER_FILE_EOTHER;
77         DFILE_LOGE(TAG, "set file offset failed");
78         return NSTACKX_EFAILED;
79     }
80 
81     if (CapsNoRW(session)) {
82         readLength = bufferLength;
83     } else {
84 #ifdef BUILD_FOR_WINDOWS
85         readLength = (uint32_t)fread(buffer, 1, bufferLength, fileInfo->fd);
86 #else
87         /* use pread because fseek have multi-thread issue in case of multi-path handle same file scenario */
88         readLength = (uint32_t)pread(fileInfo->fd, buffer, bufferLength, (int64_t)offset);
89 #endif
90     }
91 
92     if (readLength != bufferLength) {
93         DFILE_LOGE(TAG, "fread error %d read %u target %hu", GetErrno(), readLength, bufferLength);
94         fileInfo->errCode = FILE_MANAGER_FILE_EOTHER;
95         return NSTACKX_EFAILED;
96     }
97 
98     fileInfo->fileOffset += readLength;
99     return NSTACKX_EOK;
100 }
101 
GetEncryptedDataFrame(FileManager * fileManager,CryptPara * cryptPara,FileInfo * fileInfo,uint32_t targetSequence)102 static FileDataFrame *GetEncryptedDataFrame(FileManager *fileManager, CryptPara *cryptPara, FileInfo *fileInfo,
103                                             uint32_t targetSequence)
104 {
105     uint8_t *buffer = NULL;
106     uint16_t frameOffset, targetLenth;
107     FileDataFrame *fileDataFrame = NULL;
108     uint64_t fileOffset;
109     uint32_t payLoadLen;
110     fileOffset = ((uint64_t)fileInfo->standardBlockSize) * ((uint64_t)targetSequence);
111     if (targetSequence == fileInfo->totalBlockNum - 1) {
112         targetLenth = (uint16_t)(fileInfo->fileSize - fileOffset);
113     } else {
114         targetLenth = fileInfo->standardBlockSize;
115     }
116     if (targetLenth == 0) {
117         DFILE_LOGE(TAG, "target length is zero");
118         fileInfo->errCode = FILE_MANAGER_FILE_EOTHER;
119         return NULL;
120     }
121     buffer = (uint8_t *)calloc(targetLenth, 1);
122     if (buffer == NULL) {
123         fileInfo->errCode = FILE_MANAGER_ENOMEM;
124         return NULL;
125     }
126     if (ReadFromFile(fileManager, fileInfo, fileOffset, buffer, targetLenth) != NSTACKX_EOK) {
127         goto L_END;
128     }
129     fileManager->iorBytes += (uint64_t)targetLenth;
130     payLoadLen = targetLenth + GCM_ADDED_LEN;
131     frameOffset = offsetof(FileDataFrame, blockPayload);
132     fileDataFrame = (FileDataFrame *)calloc(1, frameOffset + payLoadLen);
133     if (fileDataFrame == NULL) {
134         fileInfo->errCode = FILE_MANAGER_ENOMEM;
135         goto L_END;
136     }
137     fileDataFrame->header.length = htons(frameOffset + payLoadLen - sizeof(DFileFrameHeader));
138     fileDataFrame->fileId = htons(fileInfo->fileId);
139     fileDataFrame->blockSequence = htonl(targetSequence);
140     if (AesGcmEncrypt(buffer, targetLenth, cryptPara, (uint8_t *)fileDataFrame + frameOffset, payLoadLen) == 0) {
141         fileInfo->errCode = FILE_MANAGER_FILE_EOTHER;
142         free(fileDataFrame);
143         fileDataFrame = NULL;
144         DFILE_LOGE(TAG, "data encrypt failed");
145     }
146 
147 L_END:
148     free(buffer);
149     return fileDataFrame;
150 }
151 
GetNoEncryptedDataFrame(FileManager * fileManager,FileInfo * fileInfo,uint32_t targetSequence)152 static FileDataFrame *GetNoEncryptedDataFrame(FileManager *fileManager, FileInfo *fileInfo, uint32_t targetSequence)
153 {
154     uint16_t frameOffset, targetLenth;
155     FileDataFrame *fileDataFrame = NULL;
156     uint64_t fileOffset;
157     uint8_t *buffer = NULL;
158 
159     fileOffset = ((uint64_t)fileInfo->standardBlockSize) * ((uint64_t)targetSequence);
160     if (targetSequence == fileInfo->totalBlockNum - 1) {
161         targetLenth = (uint16_t)(fileInfo->fileSize - fileOffset);
162     } else {
163         targetLenth = fileInfo->standardBlockSize;
164     }
165     frameOffset = offsetof(FileDataFrame, blockPayload);
166     fileDataFrame = (FileDataFrame *)calloc(1, frameOffset + targetLenth);
167     if (fileDataFrame == NULL) {
168         fileInfo->errCode = FILE_MANAGER_ENOMEM;
169         DFILE_LOGE(TAG, "fileDataFrame calloc failed");
170         return NULL;
171     }
172     buffer = (uint8_t *)fileDataFrame + frameOffset;
173     if (ReadFromFile(fileManager, fileInfo, fileOffset, buffer, targetLenth) != NSTACKX_EOK) {
174         free(fileDataFrame);
175         DFILE_LOGE(TAG, "read file failed");
176         return NULL;
177     }
178     fileManager->iorBytes += (uint64_t)targetLenth;
179     fileDataFrame->header.length = htons(frameOffset + targetLenth - sizeof(DFileFrameHeader));
180     fileDataFrame->fileId = htons(fileInfo->fileId);
181     fileDataFrame->blockSequence = htonl(targetSequence);
182     return fileDataFrame;
183 }
184 
GetEncryptedDataTarFrame(CryptPara * cryptPara,uint16_t fileId,FileListTask * fileList,uint16_t targetLenth)185 int32_t GetEncryptedDataTarFrame(CryptPara *cryptPara, uint16_t fileId, FileListTask *fileList, uint16_t targetLenth)
186 {
187     uint16_t frameOffset;
188     FileDataFrame *fileDataFrame = NULL;
189     uint32_t payLoadLen;
190     int32_t errCode = FILE_MANAGER_EOK;
191     uint32_t targetSequence = (uint32_t)(fileList->tarFileInfo.maxSequenceSend);
192     FileDataFrame *buffer = fileList->tarFrame;
193 
194     frameOffset = offsetof(FileDataFrame, blockPayload);
195     payLoadLen = targetLenth + GCM_ADDED_LEN;
196     fileDataFrame = (FileDataFrame *)calloc(1, frameOffset + payLoadLen);
197     if (fileDataFrame == NULL) {
198         errCode = FILE_MANAGER_ENOMEM;
199         return errCode;
200     }
201     fileDataFrame->header.length = htons(frameOffset + payLoadLen - sizeof(DFileFrameHeader));
202     fileDataFrame->fileId = htons(fileId);
203     fileDataFrame->blockSequence = htonl(targetSequence);
204     if (AesGcmEncrypt(buffer->blockPayload, targetLenth, cryptPara, fileDataFrame->blockPayload, payLoadLen) == 0) {
205         DFILE_LOGE(TAG, "AesGcmEncrypt failed, %d-%d", targetLenth, payLoadLen);
206         errCode = FILE_MANAGER_FILE_EOTHER;
207     }
208 
209     if (memcpy_s(buffer, fileList->maxFrameLength, fileDataFrame, frameOffset + payLoadLen) != EOK) {
210         DFILE_LOGE(TAG, "memcpy error");
211         errCode = FILE_MANAGER_FILE_EOTHER;
212     }
213     free(fileDataFrame);
214 
215     return errCode;
216 }
217 
GetNoEncryptedDataTarFrame(uint16_t fileId,FileListTask * fileList,uint16_t targetLenth)218 int32_t GetNoEncryptedDataTarFrame(uint16_t fileId, FileListTask *fileList, uint16_t targetLenth)
219 {
220     FileDataFrame *fileDataFrame = fileList->tarFrame;
221     if (fileDataFrame == NULL) {
222         return FILE_MANAGER_ENOMEM;
223     }
224 
225     fileDataFrame->header.length = htons(targetLenth + sizeof(FileDataFrame) - sizeof(DFileFrameHeader));
226     fileDataFrame->fileId = htons(fileId);
227     fileDataFrame->blockSequence = htonl((uint32_t)fileList->tarFileInfo.maxSequenceSend);
228     return FILE_MANAGER_EOK;
229 }
230 
GetRetranBlockInfo(FileListTask * fileList,uint16_t * fileId,uint32_t * blockSeq,uint32_t * linkSeq)231 static int32_t GetRetranBlockInfo(FileListTask *fileList, uint16_t *fileId, uint32_t *blockSeq, uint32_t *linkSeq)
232 {
233     List *curFront = NULL;
234     uint8_t isPoped;
235     SendRetranRequestNode *retranNode = NULL;
236     if (MutexListPopFront(&fileList->sendRetranList, &curFront, &isPoped) != NSTACKX_EOK) {
237         if (isPoped) {
238             retranNode = (SendRetranRequestNode *)curFront;
239             free(retranNode);
240         }
241         DFILE_LOGE(TAG, "Pop sendRetranList's head error");
242         fileList->errCode = FILE_MANAGER_EMUTEX;
243         return NSTACKX_EFAILED;
244     }
245     retranNode = (SendRetranRequestNode *)curFront;
246     *fileId = retranNode->fileId;
247     *blockSeq = retranNode->blockSequence;
248     *linkSeq = retranNode->linkSequence;
249     free(retranNode);
250     if (*fileId == 0 || *fileId > fileList->fileNum) {
251         DFILE_LOGE(TAG, "The file ID %u is illegal: totalBlockNum %u", *fileId, fileList->fileNum);
252         return NSTACKX_EFAILED;
253     }
254     return NSTACKX_EOK;
255 }
256 
CreateRetranBlockFrame(FileManager * fileManager,FileListTask * fileList)257 FileDataFrame *CreateRetranBlockFrame(FileManager *fileManager, FileListTask *fileList)
258 {
259     FileInfo *fileInfo = NULL;
260     uint16_t fileId;
261     uint32_t blockSequence, linkSequence;
262     FileDataFrame *fileDataFrame = NULL;
263 
264     if (GetRetranBlockInfo(fileList, &fileId, &blockSequence, &linkSequence) != NSTACKX_EOK) {
265         return NULL;
266     }
267 
268     if (fileList->tarFlag != NSTACKX_TRUE) {
269         fileInfo = &fileList->fileInfo[fileId - 1];
270     } else {
271         fileInfo = &fileList->tarFileInfo;
272     }
273     if (blockSequence >= fileInfo->totalBlockNum) {
274         DFILE_LOGE(TAG, "The retryBlock %u is larger than totalBlockNum %u", blockSequence, fileInfo->totalBlockNum);
275         return NULL;
276     }
277     if (fileInfo->errCode != FILE_MANAGER_EOK) {
278         DFILE_LOGE(TAG, "The processing file is error transId: %u fileId: %u", fileList->transId, fileInfo->fileId);
279         return NULL;
280     }
281 
282     if (fileList->cryptPara.keylen > 0) {
283         fileDataFrame = GetEncryptedDataFrame(fileManager, &fileList->cryptPara, fileInfo, blockSequence);
284     } else {
285         fileDataFrame = GetNoEncryptedDataFrame(fileManager, fileInfo, blockSequence);
286     }
287 
288     if (fileDataFrame == NULL) {
289         CloseFile(fileInfo);
290         NotifyFileMsg(fileList, fileInfo->fileId, FILE_MANAGER_SEND_FAIL);
291         return NULL;
292     }
293     fileList->hasUnInsetFrame = NSTACKX_TRUE;
294     fileDataFrame->header.flag |= NSTACKX_DFILE_DATA_FRAME_RETRAN_FLAG;
295     if (blockSequence == fileInfo->totalBlockNum - 1) {
296         fileDataFrame->header.flag |= NSTACKX_DFILE_DATA_FRAME_END_FLAG;
297     }
298     fileDataFrame->header.transId = htons(fileList->transId);
299     fileDataFrame->header.type = NSTACKX_DFILE_FILE_DATA_FRAME;
300 
301     /* The files with smaller file id should be closed to match the limit of the number. */
302     if (MAX_SEND_FILE_OPENED_PER_LIST <= 1 ||
303         (!fileList->tarFlag && fileList->sendFileProcessed >= MAX_SEND_FILE_OPENED_PER_LIST + fileInfo->fileId - 1)) {
304         CloseFile(fileInfo);
305     }
306     return fileDataFrame;
307 }
308 
GetTarFileInfo(FileListTask * fileList)309 static FileInfo *GetTarFileInfo(FileListTask *fileList)
310 {
311     (void)fileList;
312     return NULL;
313 }
314 
GetFileInfo(FileListTask * fileList)315 static FileInfo *GetFileInfo(FileListTask *fileList)
316 {
317     uint16_t fileId;
318     uint32_t blockSequence;
319     FileInfo *fileInfo = NULL;
320     if (fileList->tarFlag == NSTACKX_TRUE) {
321         return GetTarFileInfo(fileList);
322     }
323     if (fileList->newReadOutSet.fileId > 0) {
324         if (PthreadMutexLock(&fileList->newReadOutSet.lock) != 0) {
325             DFILE_LOGE(TAG, "pthread mutex lock error");
326             fileList->errCode = FILE_MANAGER_EMUTEX;
327             return NULL;
328         }
329         fileId = fileList->newReadOutSet.fileId;
330         blockSequence = fileList->newReadOutSet.blockSequence;
331         fileList->newReadOutSet.fileId = 0;
332         fileList->newReadOutSet.blockSequence = 0;
333         if (PthreadMutexUnlock(&fileList->newReadOutSet.lock) != 0) {
334             DFILE_LOGE(TAG, "pthread mutex unlock error");
335             fileList->errCode = FILE_MANAGER_EMUTEX;
336             return NULL;
337         }
338         if (fileId > 0 && fileId <= fileList->fileNum && blockSequence < fileList->fileInfo[fileId - 1].totalBlockNum) {
339             fileList->sendFileProcessed = (uint16_t)(fileId - 1);
340             fileList->fileInfo[fileId - 1].maxSequenceSend = (int64_t)blockSequence - 1;
341             for (uint16_t i = fileId + 1; i <= fileList->fileNum; i++) {
342                 fileList->fileInfo[i - 1].maxSequenceSend = -1;
343                 /* Close all files with larger fileId than new outset. */
344                 CloseFile(&fileList->fileInfo[i - 1]);
345             }
346             /* new outset has been set and bytesTransferred of fileList should be reset */
347             fileList->bytesTransferred = FileListGetBytesTransferred(fileList, NSTACKX_TRUE);
348         }
349     }
350     if (fileList->sendFileProcessed >= fileList->fileNum) {
351         return NULL;
352     }
353 
354     fileInfo = &fileList->fileInfo[fileList->sendFileProcessed];
355     if (fileInfo->errCode != FILE_MANAGER_EOK || fileInfo->fileSize == 0) {
356         fileList->sendFileProcessed++;
357         /* error ouccred and bytesTransferred of fileList should be reset */
358         fileList->bytesTransferred = FileListGetBytesTransferred(fileList, NSTACKX_TRUE);
359         return NULL;
360     }
361     return fileInfo;
362 }
363 
UpdateFileLisSendStatus(FileListTask * fileList,FileInfo * fileInfo,uint8_t * isEnd)364 static void UpdateFileLisSendStatus(FileListTask *fileList, FileInfo *fileInfo, uint8_t *isEnd)
365 {
366     if (fileList->bytesTransferred >=
367         fileList->bytesTransferredLastRecord + NSTACKX_KILO_BYTES * KILO_BYTES_TRANSFER_NOTICE_THRESHOLD) {
368         fileList->bytesTransferredLastRecord = fileList->bytesTransferred;
369         NotifyFileListMsg(fileList, FILE_MANAGER_TRANS_IN_PROGRESS);
370     }
371     if (fileInfo->maxSequenceSend == (int32_t)(fileInfo->totalBlockNum - 1)) {
372         /* The files with smaller file id should be closed to match the limit of the number of opened files */
373         if (fileInfo->fileId >= MAX_SEND_FILE_OPENED_PER_LIST) {
374             CloseFile(&fileList->fileInfo[fileInfo->fileId - MAX_SEND_FILE_OPENED_PER_LIST]);
375             if (!fileList->tarFlag) {
376                 /* error ouccred and bytesTransferred of fileList should be reset */
377                 fileList->bytesTransferred = FileListGetBytesTransferred(fileList, NSTACKX_TRUE);
378             }
379         }
380 
381         fileList->sendFileProcessed++;
382         *isEnd = NSTACKX_TRUE;
383     }
384 }
385 
UpdateTarFileListSendStatus(FileListTask * fileList)386 void UpdateTarFileListSendStatus(FileListTask *fileList)
387 {
388     uint64_t bytesTransFerred;
389     bytesTransFerred = FileListGetBytesTransferred(fileList, NSTACKX_TRUE);
390     if (bytesTransFerred >=
391         fileList->bytesTransferredLastRecord + NSTACKX_KILO_BYTES * KILO_BYTES_TRANSFER_NOTICE_THRESHOLD) {
392         fileList->bytesTransferredLastRecord = bytesTransFerred;
393         NotifyFileListMsg(fileList, FILE_MANAGER_TRANS_IN_PROGRESS);
394     }
395     if (fileList->tarFileInfo.maxSequenceSend == (int32_t)(fileList->tarFileInfo.totalBlockNum - 1)) {
396         fileList->sendFileProcessed = fileList->fileNum;
397         if (MAX_SEND_FILE_OPENED_PER_LIST <= 1) { // Macro maybe changed
398             FileInfo *fileInfo = GetFileInfo(fileList);
399             if (fileInfo != NULL) {
400                 CloseFile(fileInfo);
401             }
402         }
403     }
404 }
405 
CreateSendBlockFrame(FileManager * fileManager,FileListTask * fileList)406 static FileDataFrame *CreateSendBlockFrame(FileManager *fileManager, FileListTask *fileList)
407 {
408     FileInfo *fileInfo = NULL;
409     uint8_t isStartFrame = NSTACKX_FALSE;
410     uint8_t isEndFrame = NSTACKX_FALSE;
411     FileDataFrame *fileDataFrame = NULL;
412     fileInfo = GetFileInfo(fileList);
413     if (fileInfo == NULL) {
414         return NULL;
415     }
416     if (fileInfo->maxSequenceSend == -1) {
417         isStartFrame = NSTACKX_TRUE;
418     }
419     if (fileList->cryptPara.keylen > 0) {
420         fileDataFrame = GetEncryptedDataFrame(fileManager, &fileList->cryptPara, fileInfo,
421                                               (uint32_t)(fileInfo->maxSequenceSend + 1));
422     } else {
423         fileDataFrame = GetNoEncryptedDataFrame(fileManager, fileInfo, (uint32_t)(fileInfo->maxSequenceSend + 1));
424     }
425     if (fileDataFrame == NULL) {
426         DFILE_LOGE(TAG, "Can't get data from file");
427         fileList->sendFileProcessed++;
428         CloseFile(fileInfo);
429         NotifyFileMsg(fileList, fileInfo->fileId, FILE_MANAGER_SEND_FAIL);
430         return NULL;
431     }
432     fileList->hasUnInsetFrame = NSTACKX_TRUE;
433     fileInfo->maxSequenceSend++;
434     if (fileList->tarFlag != NSTACKX_TRUE) {
435         fileList->bytesTransferred += fileInfo->standardBlockSize;
436         UpdateFileLisSendStatus(fileList, fileInfo, &isEndFrame);
437     } else {
438         UpdateTarFileListSendStatus(fileList);
439     }
440     fileDataFrame->header.transId = htons(fileList->transId);
441     fileDataFrame->header.type = NSTACKX_DFILE_FILE_DATA_FRAME;
442     if (isEndFrame) {
443         fileDataFrame->header.flag |= NSTACKX_DFILE_DATA_FRAME_END_FLAG;
444     } else if (isStartFrame) {
445         fileDataFrame->header.flag |= NSTACKX_DFILE_DATA_FRAME_START_FLAG;
446     } else {
447         fileDataFrame->header.flag |= NSTACKX_DFILE_DATA_FRAME_CONTINUE_FLAG;
448     }
449     return fileDataFrame;
450 }
451 
PushFileBlockFrame(FileManager * fileManager,const FileListTask * fileList,const FileDataFrame * fileDataFrame,uint8_t isRetran,uint8_t * isAdded)452 static int32_t PushFileBlockFrame(FileManager *fileManager, const FileListTask *fileList,
453                                   const FileDataFrame *fileDataFrame,
454                                   uint8_t isRetran, uint8_t *isAdded)
455 {
456     BlockFrame *blockFrame = NULL;
457     SendBlockFrameListPara *para = &fileManager->sendBlockFrameListPara[fileList->bindedSendBlockListIdx];
458     *isAdded = NSTACKX_FALSE;
459     blockFrame = (BlockFrame *)calloc(1, sizeof(BlockFrame));
460     if (blockFrame == NULL) {
461         DFILE_LOGE(TAG, "calloc error");
462         fileManager->errCode = FILE_MANAGER_ENOMEM;
463         NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
464         return NSTACKX_EFAILED;
465     }
466     blockFrame->sendLen = 0;
467     blockFrame->fileDataFrame = (FileDataFrame *)fileDataFrame;
468     blockFrame->socketIndex = fileList->socketIndex;
469 
470     if (PthreadMutexLock(&para->sendBlockFrameList.lock) != 0) {
471         free(blockFrame);
472         DFILE_LOGE(TAG, "pthread mutex lock error");
473         fileManager->errCode = FILE_MANAGER_EMUTEX;
474         goto L_ERR_FILE_MANAGER;
475     }
476     if (isRetran) {
477         ListInsertHead(para->sendRetranListTail, &blockFrame->list);
478         para->sendRetranListTail = &blockFrame->list;
479     } else {
480         ListInsertTail(&para->sendBlockFrameList.head, &blockFrame->list);
481     }
482     *isAdded = NSTACKX_TRUE;
483     para->sendBlockFrameList.size++;
484     if (PthreadMutexUnlock(&para->sendBlockFrameList.lock) != 0) {
485         DFILE_LOGE(TAG, "pthread mutex unlock error");
486         fileManager->errCode = FILE_MANAGER_EMUTEX;
487         goto L_ERR_FILE_MANAGER;
488     }
489     return NSTACKX_EOK;
490 L_ERR_FILE_MANAGER:
491     NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
492     return NSTACKX_EFAILED;
493 }
494 
ClearSendFileList(FileManager * fileManager,FileListTask * fileList)495 void ClearSendFileList(FileManager *fileManager, FileListTask *fileList)
496 {
497     SendRetranRequestNode *retranNode = NULL;
498     for (uint32_t i = 0; i < fileList->fileNum; i++) {
499         CloseFile(&fileList->fileInfo[i]);
500         free(fileList->fileInfo[i].fileName);
501         fileList->fileInfo[i].fileName = NULL;
502     }
503     if (fileList->tarFlag) {
504         CloseFile(&fileList->tarFileInfo);
505     }
506     free(fileList->tarFileInfo.fileName);
507     fileList->tarFileInfo.fileName = NULL;
508     if (fileList->tarFileInfo.tarData != NULL) {
509         free(fileList->tarFileInfo.tarData);
510         fileList->tarFileInfo.tarData = NULL;
511         NSTACKX_ATOM_FETCH_SUB(&fileManager->totalPackInMemory, fileList->tarFileInfo.fileSize);
512     }
513     SemDestroy(&fileList->semStop);
514     if (PthreadMutexLock(&fileList->sendRetranList.lock) != 0) {
515         DFILE_LOGE(TAG, "pthread mutex lock error");
516     }
517     while (fileList->sendRetranList.size > 0) {
518         retranNode = (SendRetranRequestNode *)ListPopFront(&fileList->sendRetranList.head);
519         fileList->sendRetranList.size--;
520         free(retranNode);
521         retranNode = NULL;
522     }
523     if (PthreadMutexUnlock(&fileList->sendRetranList.lock) != 0) {
524         DFILE_LOGE(TAG, "pthread mutex unlock error");
525     }
526     MutexListDestory(&fileList->sendRetranList);
527 #ifndef MBEDTLS_INCLUDED
528     ClearCryptCtx(fileList->cryptPara.ctx);
529 #endif
530     PthreadMutexDestroy(&fileList->newReadOutSet.lock);
531     (void)memset_s(fileList, sizeof(FileListTask), 0, sizeof(FileListTask));
532     free(fileList);
533 }
534 
PushRetranBlockFrame(FileManager * fileManager,const FileListTask * fileList,const FileDataFrame * fileDataFrame)535 uint8_t PushRetranBlockFrame(FileManager *fileManager, const FileListTask *fileList, const FileDataFrame *fileDataFrame)
536 {
537     uint8_t ret = NSTACKX_FALSE;
538     SendBlockFrameListPara *para = &fileManager->sendBlockFrameListPara[fileList->bindedSendBlockListIdx];
539     if (fileDataFrame == NULL) {
540         DFILE_LOGE(TAG, "frame is NULL");
541         return ret;
542     }
543     CheckSendListFullAndWait(fileManager, &para->semBlockListNotFull);
544     if (CheckManager(fileManager) != NSTACKX_EOK) {
545         return ret;
546     }
547     if (PushFileBlockFrame(fileManager, fileList, fileDataFrame, NSTACKX_TRUE, &ret) != NSTACKX_EOK) {
548         DFILE_LOGE(TAG, "push retran block error");
549     }
550     return ret;
551 }
552 
PushSendBlockFrame(FileManager * fileManager,const FileListTask * fileList,const FileDataFrame * fileDataFrame)553 uint8_t PushSendBlockFrame(FileManager *fileManager, const FileListTask *fileList, const FileDataFrame *fileDataFrame)
554 {
555     uint8_t isAdded = NSTACKX_FALSE;
556 
557     SendBlockFrameListPara *para = &fileManager->sendBlockFrameListPara[fileList->bindedSendBlockListIdx];
558     if (fileDataFrame == NULL) {
559         return NSTACKX_FALSE;
560     }
561 
562     CheckSendListFullAndWait(fileManager, &para->semBlockListNotFull);
563     if (CheckManager(fileManager) != NSTACKX_EOK) {
564         return NSTACKX_FALSE;
565     }
566     if (PushFileBlockFrame(fileManager, fileList, fileDataFrame, NSTACKX_FALSE, &isAdded) != NSTACKX_EOK) {
567         return NSTACKX_FALSE;
568     }
569 
570     return isAdded;
571 }
572 
CreateSendBlockTarFrames(FileManager * fileManager,FileListTask * fileList)573 static uint8_t CreateSendBlockTarFrames(FileManager *fileManager, FileListTask *fileList)
574 {
575     (void)fileManager;
576     (void)fileList;
577     return NSTACKX_FALSE;
578 }
579 
SendTaskProcess(FileManager * fileManager,FileListTask * fileList)580 void SendTaskProcess(FileManager *fileManager, FileListTask *fileList)
581 {
582     FileDataFrame *fileDataFrame = NULL;
583     uint8_t isAdded;
584     uint8_t isEmpty;
585     SendBlockFrameListPara *para = &fileManager->sendBlockFrameListPara[fileList->bindedSendBlockListIdx];
586     while (NSTACKX_TRUE) {
587         if (CheckFilelist(fileList) != NSTACKX_EOK || CheckManager(fileManager) != NSTACKX_EOK) {
588             break;
589         }
590         isEmpty = NSTACKX_FALSE;
591         if (fileList->sendRetranList.size == 0) {
592             isEmpty = NSTACKX_TRUE;
593         }
594         if (isEmpty != NSTACKX_TRUE) {
595             fileDataFrame = CreateRetranBlockFrame(fileManager, fileList);
596             isAdded = PushRetranBlockFrame(fileManager, fileList, fileDataFrame);
597         } else if (fileList->sendFileProcessed >= fileList->fileNum && fileList->newReadOutSet.fileId == 0) {
598             SemWait(&fileList->semStop);
599             continue;
600         } else {
601             if ((fileList->tarFlag == NSTACKX_TRUE) && (fileList->tarFinished != NSTACKX_TRUE)) {
602                 isAdded = CreateSendBlockTarFrames(fileManager, fileList);
603             } else {
604                 fileDataFrame = CreateSendBlockFrame(fileManager, fileList);
605                 isAdded = PushSendBlockFrame(fileManager, fileList, fileDataFrame);
606             }
607         }
608         if (fileDataFrame != NULL) {
609             if (isAdded != NSTACKX_TRUE) {
610                 free(fileDataFrame);
611                 SemPost(&para->semBlockListNotFull);
612             }
613             fileList->hasUnInsetFrame = NSTACKX_FALSE;
614         }
615     }
616 
617     if (fileList->errCode != FILE_MANAGER_EOK) {
618         DFILE_LOGE(TAG, "send task process failed %d", fileList->errCode);
619         NotifyFileListMsg(fileList, FILE_MANAGER_SEND_FAIL);
620     }
621 }
622 
PackGetTarBlockLen(const FileListTask * fmFileList)623 uint64_t PackGetTarBlockLen(const FileListTask *fmFileList)
624 {
625     char pathSeparator = '/';
626     uint64_t tarFilesTotalLen = 0;
627     uint64_t blockCnt;
628     uint32_t i;
629     char *path = NULL;
630 
631     for (i = 0; i < fmFileList->fileNum; i++) {
632         tarFilesTotalLen += BLOCK_LEN;
633 
634         path = fmFileList->fileInfo[i].fileName;
635         if (strlen(path) > MAX_NAME_LEN) {
636             // +1 because of the string end '\0'
637             tarFilesTotalLen += BLOCK_LEN +
638                 (((strlen(path) + 1 - (long long)(path[0] == pathSeparator) + BLOCK_LEN - 1) / BLOCK_LEN) * BLOCK_LEN);
639         }
640 
641         // file body length
642         blockCnt = (fmFileList->fileInfo[i].fileSize + BLOCK_LEN - 1) / BLOCK_LEN;
643         tarFilesTotalLen += (blockCnt * BLOCK_LEN);
644     }
645 
646     // file tail paddings length
647     tarFilesTotalLen += BLOCK_LEN;
648 
649     return tarFilesTotalLen;
650 }
651 
AddTarFileInfo(const char * tarFileName,FileListTask * fmFileList,uint16_t standardBlockSize)652 static int32_t AddTarFileInfo(const char *tarFileName, FileListTask *fmFileList, uint16_t standardBlockSize)
653 {
654     uint64_t tarFilesTotalLen;
655     tarFilesTotalLen = PackGetTarBlockLen(fmFileList);
656     fmFileList->blockOffset = 0;
657     fmFileList->tarFrame = NULL;
658     fmFileList->tarFileInfo.fd = NSTACKX_INVALID_FD;
659     fmFileList->tarFileInfo.fileSize = tarFilesTotalLen;
660     fmFileList->tarFileInfo.standardBlockSize = standardBlockSize;
661     fmFileList->tarFileInfo.totalBlockNum = (uint32_t)((tarFilesTotalLen + standardBlockSize - 1) / standardBlockSize);
662     fmFileList->tarFileInfo.fileId = 1;
663     fmFileList->tarFileInfo.maxSequenceSend = -1;
664     fmFileList->tarFileInfo.tarData = NULL;
665     fmFileList->tarFileInfo.writeOffset = 0;
666     DFILE_LOGI(TAG, "tarLen: %llu, blockNum: %u, endLen: %llu", tarFilesTotalLen,
667         fmFileList->tarFileInfo.totalBlockNum, tarFilesTotalLen % standardBlockSize);
668     fmFileList->tarFileInfo.fileName = realpath(tarFileName, NULL);
669     if ((fmFileList->tarFileInfo.fileName == NULL) ||
670         (!IsAccessiblePath(fmFileList->tarFileInfo.fileName, R_OK, S_IFREG))) {
671         return NSTACKX_EFAILED;
672     }
673     fmFileList->tarFd = NULL;
674     fmFileList->totalBytes = fmFileList->tarFileInfo.fileSize;
675     return NSTACKX_EOK;
676 }
677 
AddSendFileInfo(const SendFileListInfo * fileListInfo,FileListTask * fmFileList,uint16_t standardBlockSize)678 static int32_t AddSendFileInfo(const SendFileListInfo *fileListInfo,
679                                FileListTask *fmFileList, uint16_t standardBlockSize)
680 {
681     uint16_t i;
682     FileInfo *fileInfo = NULL;
683     for (i = 0; i < fmFileList->fileNum; i++) {
684         if (fileListInfo->fileList[i] == NULL) {
685             goto L_ERR_FILE_MANAGER;
686         }
687         fileInfo = &fmFileList->fileInfo[i];
688         fileInfo->fileName = realpath(fileListInfo->fileList[i], NULL);
689         if (fileInfo->fileName == NULL || !IsAccessiblePath(fileInfo->fileName, R_OK, S_IFREG)) {
690             DFILE_LOGE(TAG, "can't get canonicalized absolute pathname, error(%d)", errno);
691             goto L_ERR_FILE_MANAGER;
692         }
693         fileInfo->fileSize = fileListInfo->fileSize[i];
694         fileInfo->standardBlockSize = standardBlockSize;
695         fileInfo->totalBlockNum = (uint32_t)(fileInfo->fileSize / standardBlockSize);
696         if (fileInfo->fileSize % standardBlockSize != 0) {
697             fileInfo->totalBlockNum++;
698         }
699         fmFileList->totalBytes += fileInfo->fileSize;
700         fileInfo->fileId = i + 1;
701         fileInfo->startOffset = fileListInfo->startOffset[i];
702         fileInfo->maxSequenceSend = -1;
703         fileInfo->fd = NSTACKX_INVALID_FD;
704         fileInfo->errCode = FILE_MANAGER_EOK;
705         fileInfo->fileOffset = 0;
706         fileInfo->tarData = NULL;
707         fileInfo->writeOffset = 0;
708     }
709 
710     if (fmFileList->tarFlag &&
711         AddTarFileInfo(fileListInfo->fileList[fmFileList->fileNum], fmFileList, standardBlockSize) != NSTACKX_EOK) {
712         goto L_ERR_FILE_MANAGER;
713     }
714 
715     return NSTACKX_EOK;
716 L_ERR_FILE_MANAGER:
717     for (i = 0; i < fmFileList->fileNum; i++) {
718         free(fmFileList->fileInfo[i].fileName);
719         fmFileList->fileInfo[i].fileName = NULL;
720     }
721     return NSTACKX_EFAILED;
722 }
723 
InitSendFilesOutSet(FileListTask * fmFileList)724 static int32_t InitSendFilesOutSet(FileListTask *fmFileList)
725 {
726     if (PthreadMutexInit(&fmFileList->newReadOutSet.lock, NULL) != 0) {
727         DFILE_LOGE(TAG, "PthreadMutexInit error");
728         return NSTACKX_EFAILED;
729     }
730     fmFileList->newReadOutSet.fileId = 0;
731     fmFileList->newReadOutSet.blockSequence = 0;
732     return NSTACKX_EOK;
733 }
734 
CreateSendFileList(const SendFileListInfo * fileListInfo,uint16_t standardBlockSize,const FileListMsgPara * msgPara)735 static FileListTask *CreateSendFileList(const SendFileListInfo *fileListInfo,
736                                         uint16_t standardBlockSize, const FileListMsgPara *msgPara)
737 {
738     FileListTask *fmFileList = NULL;
739     fmFileList = (FileListTask *)calloc(1, sizeof(FileListTask));
740     if (fmFileList == NULL) {
741         DFILE_LOGE(TAG, "file list calloc error");
742         return NULL;
743     }
744     fmFileList->transId = fileListInfo->transId;
745     fmFileList->fileNum = fileListInfo->fileNum;
746     fmFileList->tarFlag = fileListInfo->tarFlag;
747     fmFileList->smallFlag = fileListInfo->smallFlag;
748     if (SemInit(&fmFileList->semStop, 0, 0) != 0) {
749         DFILE_LOGE(TAG, "SemInit error");
750         goto L_ERR_FILE_MANAGER;
751     }
752     fmFileList->runStatus = FILE_LIST_STATUS_IDLE;
753     fmFileList->stopType = FILE_LIST_TRANSFER_FINISH;
754     fmFileList->isOccupied = NSTACKX_FALSE;
755     fmFileList->errCode = FILE_MANAGER_EOK;
756     fmFileList->sendFileProcessed = 0;
757 
758     if (MutexListInit(&fmFileList->sendRetranList, NSTACKX_MAX_RETRAN_BLOCK_NUM) != NSTACKX_EOK) {
759         DFILE_LOGE(TAG, "sendRetranList init error");
760         SemDestroy(&fmFileList->semStop);
761         goto L_ERR_FILE_MANAGER;
762     }
763 
764     if (InitSendFilesOutSet(fmFileList) != NSTACKX_EOK) {
765         SemDestroy(&fmFileList->semStop);
766         MutexListDestory(&fmFileList->sendRetranList);
767         DFILE_LOGE(TAG, "InitRetranFilesInfo error");
768         goto L_ERR_FILE_MANAGER;
769     }
770 
771     if (AddSendFileInfo(fileListInfo, fmFileList, standardBlockSize) != NSTACKX_EOK) {
772         DFILE_LOGE(TAG, "AddSendFileInfo init error");
773         SemDestroy(&fmFileList->semStop);
774         MutexListDestory(&fmFileList->sendRetranList);
775         PthreadMutexDestroy(&fmFileList->newReadOutSet.lock);
776         goto L_ERR_FILE_MANAGER;
777     }
778 
779     if (msgPara != NULL) {
780         fmFileList->msgReceiver = msgPara->msgReceiver;
781         fmFileList->context = msgPara->context;
782     }
783     return fmFileList;
784 L_ERR_FILE_MANAGER:
785     (void)memset_s(fmFileList, sizeof(FileListTask), 0, sizeof(FileListTask));
786     free(fmFileList);
787     return NULL;
788 }
789 
GetTargetSendBlockListIdx(const FileManager * fileManager)790 static uint32_t GetTargetSendBlockListIdx(const FileManager *fileManager)
791 {
792     uint32_t ret = 0;
793     uint32_t bindingNum = NSTACKX_MAX_PROCESSING_TASK_NUM;
794 
795     for (uint32_t i = 0; i < fileManager->sendFrameListNum; i++) {
796         if (fileManager->sendBlockFrameListPara[i].bandingTransNum < bindingNum) {
797             bindingNum = fileManager->sendBlockFrameListPara[i].bandingTransNum;
798             ret = i;
799         }
800     }
801     return ret;
802 }
803 
FileManagerSendFileTask(FileManager * fileManager,const SendFileListInfo * fileListInfo,const FileListMsgPara * msgPara)804 int32_t FileManagerSendFileTask(FileManager *fileManager, const SendFileListInfo *fileListInfo,
805                                 const FileListMsgPara *msgPara)
806 {
807     FileListTask *fmFileList = NULL;
808     uint16_t standardBlockSize;
809     if (CheckSenderManager(fileManager) != NSTACKX_EOK || fileListInfo == NULL ||
810         fileListInfo->fileNum == 0 || fileListInfo->fileNum > NSTACKX_DFILE_MAX_FILE_NUM) {
811         DFILE_LOGE(TAG, "Invalid input");
812         return NSTACKX_EINVAL;
813     }
814     if (fileManager->taskList.size >= fileManager->taskList.maxSize) {
815         DFILE_LOGE(TAG, "task list is full");
816         return NSTACKX_EFAILED;
817     }
818     standardBlockSize = GetStandardBlockSize(fileManager);
819     if (standardBlockSize == 0) {
820         DFILE_LOGE(TAG, "max frame length is too small");
821         return NSTACKX_EFAILED;
822     }
823 
824     fmFileList = CreateSendFileList(fileListInfo, standardBlockSize, msgPara);
825     if (fmFileList == NULL) {
826         DFILE_LOGE(TAG, "Can't creat fmFileList");
827         return NSTACKX_EFAILED;
828     }
829     fmFileList->maxFrameLength = fileManager->maxFrameLength;
830     fmFileList->epollfd = fileManager->epollfd;
831     fmFileList->eventNodeChain = fileManager->eventNodeChain;
832     if (fileManager->keyLen > 0 && SetCryptPara(fmFileList, fileManager->key, fileManager->keyLen) != NSTACKX_EOK) {
833         ClearSendFileList(fileManager, fmFileList);
834         return NSTACKX_EFAILED;
835     }
836     PeerInfo *peerinfo = ClientGetPeerInfoByTransId((DFileSession *)fileManager->context);
837     if (!peerinfo) {
838         ClearSendFileList(fileManager, fmFileList);
839         return NSTACKX_EFAILED;
840     }
841     fmFileList->socketIndex = peerinfo->socketIndex;
842     fmFileList->bindedSendBlockListIdx = GetTargetSendBlockListIdx(fileManager);
843     if (MutexListAddNode(&fileManager->taskList, &fmFileList->list, NSTACKX_FALSE) != NSTACKX_EOK) {
844         DFILE_LOGE(TAG, "Add task to list error");
845         ClearSendFileList(fileManager, fmFileList);
846         fileManager->errCode = FILE_MANAGER_EMUTEX;
847         NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
848         return NSTACKX_EFAILED;
849     }
850     fileManager->totalBytes += fmFileList->totalBytes;
851     fileManager->sendBlockFrameListPara[fmFileList->bindedSendBlockListIdx].bandingTransNum++;
852     SemPost(&fileManager->semTaskListNotEmpty);
853     return NSTACKX_EOK;
854 }
855 
GetRetranFileLostBlocks(const FileListTask * fileList,uint16_t fileId,uint32_t blockSequence)856 static int32_t GetRetranFileLostBlocks(const FileListTask *fileList, uint16_t fileId, uint32_t blockSequence)
857 {
858     uint32_t ret = 0;
859 
860     if (fileList->tarFlag && fileList->tarFinished) {
861         return (int32_t)(fileList->tarFileInfo.totalBlockNum - blockSequence);
862     }
863 
864     for (uint16_t i = fileId; i <= fileList->sendFileProcessed + 1 && i <= fileList->fileNum; i++) {
865         ret += (uint32_t)(fileList->fileInfo[i - 1].maxSequenceSend + 1);
866     }
867 
868     if (ret >= blockSequence) {
869         ret -= blockSequence;
870     } else {
871         ret = 0;
872     }
873 
874     if (ret > INT32_MAX) {
875         ret = INT32_MAX;
876     }
877     return (int32_t)ret;
878 }
879 
IsValidOutSet(const FileListTask * fileList,uint16_t fileId,uint32_t blockSequence)880 static uint8_t IsValidOutSet(const FileListTask *fileList, uint16_t fileId, uint32_t blockSequence)
881 {
882     uint32_t totalBlockNum;
883     uint16_t fileNum;
884     fileNum = (fileList->tarFlag == NSTACKX_TRUE) ? 1 : fileList->fileNum;
885     if (fileId == 0 || fileId > fileNum) {
886         DFILE_LOGE(TAG, "new outset fileId is illegal");
887         return NSTACKX_FALSE;
888     }
889 
890     totalBlockNum = (fileList->tarFlag == NSTACKX_TRUE) ?
891                      fileList->tarFileInfo.totalBlockNum : fileList->fileInfo[fileId - 1].totalBlockNum;
892     if (blockSequence >= totalBlockNum) {
893         DFILE_LOGE(TAG, "new outset blockSequence is illegal");
894         return NSTACKX_FALSE;
895     }
896     return NSTACKX_TRUE;
897 }
898 
FileManagerResetSendOutSet(FileManager * fileManager,uint16_t fileId,uint32_t blockSequence,uint16_t transId)899 int32_t FileManagerResetSendOutSet(FileManager *fileManager, uint16_t fileId, uint32_t blockSequence, uint16_t transId)
900 {
901     FileListTask *fileList = NULL;
902     uint8_t isErrorOccurred;
903     int32_t ret;
904 
905     if (CheckSenderManager(fileManager) != NSTACKX_EOK ||
906         fileManager->maxFrameLength <= offsetof(FileDataFrame, blockPayload)) {
907         DFILE_LOGE(TAG, "Invalid input");
908         return NSTACKX_EINVAL;
909     }
910     fileList = GetFileListById(&fileManager->taskList, transId, &isErrorOccurred);
911     if (isErrorOccurred) {
912         DFILE_LOGE(TAG, "get target file list error");
913         goto L_ERR_FILE_MANAGER;
914     }
915 
916     if (CheckFilelistNotStop(fileList) != NSTACKX_EOK) {
917         DFILE_LOGE(TAG, "target file list is not available");
918         return NSTACKX_EFAILED;
919     }
920 
921     if (!IsValidOutSet(fileList, fileId, blockSequence)) {
922         return NSTACKX_EFAILED;
923     }
924 
925     ret = GetRetranFileLostBlocks(fileList, fileId, blockSequence);
926     if (fileList->tarFlag && fileList->tarFinished != NSTACKX_TRUE) {
927         return ret;
928     }
929     if (PthreadMutexLock(&fileList->newReadOutSet.lock) != 0) {
930         DFILE_LOGE(TAG, "pthread mutex lock error");
931         goto L_ERR_FILE_MANAGER;
932     }
933     fileList->newReadOutSet.blockSequence = blockSequence;
934     fileList->newReadOutSet.fileId = fileId;
935 
936     if (PthreadMutexUnlock(&fileList->newReadOutSet.lock) != 0) {
937         DFILE_LOGE(TAG, "pthread mutex unlock error");
938         goto L_ERR_FILE_MANAGER;
939     }
940     SemPost(&fileList->semStop);
941     return ret;
942 
943 L_ERR_FILE_MANAGER:
944     NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
945     if (fileList != NULL) {
946         NotifyFileListMsg(fileList, FILE_MANAGER_SEND_FAIL);
947     }
948     return NSTACKX_EFAILED;
949 }
950 
GetSendBlockFrameListPara(FileManager * fileManager,uint32_t tid)951 static SendBlockFrameListPara *GetSendBlockFrameListPara(FileManager *fileManager, uint32_t tid)
952 {
953     SendBlockFrameListPara *para = NULL;
954 
955     if (tid < fileManager->sendFrameListNum) {
956         para = &fileManager->sendBlockFrameListPara[tid];
957         if (!ListIsEmpty(&para->sendBlockFrameList.head)) {
958             return para;
959         }
960     }
961 
962     for (uint32_t i = 0; i < fileManager->sendFrameListNum; i++) {
963         para = &fileManager->sendBlockFrameListPara[i];
964         if (!ListIsEmpty(&para->sendBlockFrameList.head)) {
965             return para;
966         }
967     }
968     return NULL;
969 }
970 
GetMultipleBlockFrame(SendBlockFrameListPara * para,BlockFrame ** block,int32_t nr)971 static int32_t GetMultipleBlockFrame(SendBlockFrameListPara *para, BlockFrame **block, int32_t nr)
972 {
973     BlockFrame *frame = NULL;
974     List *cur = NULL;
975     int32_t cnt;
976 
977     for (cnt = 0; cnt < nr; ++cnt) {
978         cur = ListPopFront(&para->sendBlockFrameList.head);
979         if (cur == NULL) {
980             break;
981         }
982         para->sendBlockFrameList.size--;
983         if (para->sendRetranListTail == cur) {
984             para->sendRetranListTail = &para->sendBlockFrameList.head;
985         }
986         if (frame != NULL) {
987             frame->list.next = cur;
988             frame = (BlockFrame *)(void *)cur;
989         } else {
990             frame = (BlockFrame *)(void *)cur;
991             *block = frame;
992         }
993     }
994     return cnt;
995 }
996 
GetDataFrameFromSendList(SendBlockFrameListPara * para,BlockFrame ** block,int32_t nr)997 static int32_t GetDataFrameFromSendList(SendBlockFrameListPara *para, BlockFrame **block, int32_t nr)
998 {
999     int32_t ret;
1000 
1001     if (PthreadMutexLock(&para->sendBlockFrameList.lock) != 0) {
1002         DFILE_LOGE(TAG, "pthread mutex lock error");
1003         return FILE_MANAGER_EMUTEX;
1004     }
1005 
1006     ret = GetMultipleBlockFrame(para, block, nr);
1007 
1008     if (PthreadMutexUnlock(&para->sendBlockFrameList.lock) != 0) {
1009         DFILE_LOGE(TAG, "pthread mutex unlock error");
1010     }
1011     for (int i = 0; i < ret; ++i) {
1012         SemPost(&para->semBlockListNotFull);
1013     }
1014     return ret;
1015 }
1016 
FileManagerFileRead(FileManager * fileManager,uint32_t tid,BlockFrame ** block,int32_t nr)1017 int32_t FileManagerFileRead(FileManager *fileManager, uint32_t tid, BlockFrame **block, int32_t nr)
1018 {
1019     int32_t ret;
1020     SendBlockFrameListPara *para = NULL;
1021     *block = NULL;
1022 
1023     if (CheckSenderManager(fileManager) != NSTACKX_EOK) {
1024         DFILE_LOGE(TAG, "Invalid input");
1025         return NSTACKX_EINVAL;
1026     }
1027 
1028     para = GetSendBlockFrameListPara(fileManager, tid);
1029     if (para == NULL || ListIsEmpty(&para->sendBlockFrameList.head)) {
1030         return 0;
1031     }
1032     ret = GetDataFrameFromSendList(para, block, nr);
1033     if (ret < 0) {
1034         fileManager->errCode = ret;
1035         NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1036         DFILE_LOGE(TAG, "GetDataFrameFromSendList failed");
1037         return ret;
1038     }
1039     if (*block != NULL) {
1040         RefreshBytesTransFerred(fileManager, *block);
1041     }
1042 
1043     return ret;
1044 }
1045 
InitSendBlockLists(FileManager * fileManager)1046 int32_t InitSendBlockLists(FileManager *fileManager)
1047 {
1048     uint32_t i;
1049     SendBlockFrameListPara *para = NULL;
1050     uint32_t sendListSize = fileManager->maxSendBlockListSize;
1051 
1052     for (i = 0; i < fileManager->sendFrameListNum; i++) {
1053         para = &fileManager->sendBlockFrameListPara[i];
1054         if (MutexListInit(&para->sendBlockFrameList, sendListSize) != NSTACKX_EOK) {
1055             DFILE_LOGE(TAG, "sendBlockFrameList InitList error");
1056             goto L_ERR_FILE_MANAGER;
1057         }
1058         para->sendRetranListTail = &para->sendBlockFrameList.head;
1059     }
1060     return NSTACKX_EOK;
1061 
1062 L_ERR_FILE_MANAGER:
1063     while (i > 0) {
1064         para = &fileManager->sendBlockFrameListPara[i - 1];
1065         MutexListDestory(&para->sendBlockFrameList);
1066         para->sendRetranListTail = NULL;
1067         i--;
1068     }
1069     return NSTACKX_EFAILED;
1070 }
1071 
GetMaxSendListSize(uint16_t connType)1072 uint32_t GetMaxSendListSize(uint16_t connType)
1073 {
1074     if (connType == CONNECT_TYPE_WLAN) {
1075         return NSTACKX_WLAN_SEND_BLOCK_QUEUE_MAX_LEN;
1076     } else if (connType == CONNECT_TYPE_P2P) {
1077         return NSTACKX_P2P_SEND_BLOCK_QUEUE_MAX_LEN;
1078     } else {
1079         DFILE_LOGE(TAG, "invalid connect type");
1080         return 0;
1081     }
1082 }
1083 
GetSendListNum(void)1084 uint16_t GetSendListNum(void)
1085 {
1086     return 1;
1087 }
1088 
ClearSendFrameList(FileManager * fileManager)1089 void ClearSendFrameList(FileManager *fileManager)
1090 {
1091     BlockFrame *blockFrame = NULL;
1092     uint32_t i;
1093     SendBlockFrameListPara *para = NULL;
1094     for (i = 0; i < fileManager->sendFrameListNum; i++) {
1095         para = &fileManager->sendBlockFrameListPara[i];
1096         if (PthreadMutexLock(&para->sendBlockFrameList.lock) != 0) {
1097             DFILE_LOGE(TAG, "pthread mutex lock error");
1098         }
1099         while (para->sendBlockFrameList.size > 0) {
1100             blockFrame = (BlockFrame *)ListPopFront(&para->sendBlockFrameList.head);
1101             para->sendBlockFrameList.size--;
1102             if (blockFrame != NULL) {
1103                 free(blockFrame->fileDataFrame);
1104                 free(blockFrame);
1105                 blockFrame = NULL;
1106             }
1107         }
1108         para->sendRetranListTail = &para->sendBlockFrameList.head;
1109         if (PthreadMutexUnlock(&para->sendBlockFrameList.lock) != 0) {
1110             DFILE_LOGE(TAG, "pthread mutex unlock error");
1111         }
1112         MutexListDestory(&para->sendBlockFrameList);
1113     }
1114 }
1115 
FileManagerIsLastBlockRead(FileManager * fileManager,uint16_t transId)1116 uint8_t FileManagerIsLastBlockRead(FileManager *fileManager, uint16_t transId)
1117 {
1118     FileListTask *fileList = NULL;
1119     uint8_t isErrorOccurred;
1120     if (fileManager == NULL) {
1121         return NSTACKX_FALSE;
1122     }
1123     fileList = GetFileListById(&fileManager->taskList, transId, &isErrorOccurred);
1124     if (isErrorOccurred) {
1125         fileManager->errCode = FILE_MANAGER_EMUTEX;
1126         NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1127         return NSTACKX_FALSE;
1128     }
1129     if (fileList == NULL) {
1130         return NSTACKX_FALSE;
1131     }
1132     if (fileList->newReadOutSet.fileId == 0 && fileList->sendFileProcessed == fileList->fileNum &&
1133         fileList->sendRetranList.size == 0 && !fileList->hasUnInsetFrame) {
1134         return NSTACKX_TRUE;
1135     }
1136     return NSTACKX_FALSE;
1137 }
1138 
FileManagerHasPendingDataMp(FileManager * fileManager,uint8_t socketIndex)1139 uint8_t FileManagerHasPendingDataMp(FileManager *fileManager, uint8_t socketIndex)
1140 {
1141     List *list = NULL;
1142     FileListTask *fileList = NULL;
1143     uint8_t hasPendingData = NSTACKX_FALSE;
1144 
1145     if (fileManager == NULL || fileManager->isSender != NSTACKX_TRUE) {
1146         return NSTACKX_FALSE;
1147     }
1148 
1149     if (fileManager->sendBlockFrameListPara[socketIndex].sendBlockFrameList.size > 0) {
1150         return NSTACKX_TRUE;
1151     }
1152 
1153     if (PthreadMutexLock(&fileManager->taskList.lock) != 0) {
1154         DFILE_LOGE(TAG, "pthread mutex lock error");
1155         fileManager->errCode = FILE_MANAGER_EMUTEX;
1156         NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1157         return NSTACKX_FALSE;
1158     }
1159 
1160     LIST_FOR_EACH(list, &fileManager->taskList.head) {
1161         fileList = (FileListTask *)list;
1162         if (fileList->socketIndex != socketIndex || CheckFilelistNotStop(fileList) != NSTACKX_EOK) {
1163             continue;
1164         }
1165 
1166         if (fileList->newReadOutSet.fileId > 0) {
1167             hasPendingData = NSTACKX_TRUE;
1168             break;
1169         }
1170 
1171         if (fileList->sendFileProcessed < fileList->fileNum) {
1172             hasPendingData = NSTACKX_TRUE;
1173             break;
1174         }
1175         if (fileList->sendRetranList.size > 0) {
1176             hasPendingData = NSTACKX_TRUE;
1177             break;
1178         }
1179 
1180         if (fileList->hasUnInsetFrame) {
1181             hasPendingData = NSTACKX_TRUE;
1182             break;
1183         }
1184     }
1185     if (PthreadMutexUnlock(&fileManager->taskList.lock) != 0) {
1186         DFILE_LOGE(TAG, "pthread mutex unlock error");
1187         fileManager->errCode = FILE_MANAGER_EMUTEX;
1188         NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1189     }
1190 
1191     return hasPendingData;
1192 }
1193 
FileManagerHasPendingDataInner(FileManager * fileManager)1194 uint8_t FileManagerHasPendingDataInner(FileManager *fileManager)
1195 {
1196     List *list = NULL;
1197     FileListTask *fileList = NULL;
1198     uint8_t hasPendingData = NSTACKX_FALSE;
1199 
1200     if (fileManager == NULL || fileManager->isSender != NSTACKX_TRUE) {
1201         return NSTACKX_FALSE;
1202     }
1203 
1204     if (PthreadMutexLock(&fileManager->taskList.lock) != 0) {
1205         DFILE_LOGE(TAG, "pthread mutex lock error");
1206         fileManager->errCode = FILE_MANAGER_EMUTEX;
1207         NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1208         return NSTACKX_FALSE;
1209     }
1210 
1211     LIST_FOR_EACH(list, &fileManager->taskList.head) {
1212         fileList = (FileListTask *)list;
1213         if (CheckFilelistNotStop(fileList) != NSTACKX_EOK) {
1214             continue;
1215         }
1216 
1217         if (fileList->newReadOutSet.fileId > 0) {
1218             hasPendingData = NSTACKX_TRUE;
1219             break;
1220         }
1221 
1222         if (fileList->sendFileProcessed < fileList->fileNum) {
1223             hasPendingData = NSTACKX_TRUE;
1224             break;
1225         }
1226         if (fileList->sendRetranList.size > 0) {
1227             hasPendingData = NSTACKX_TRUE;
1228             break;
1229         }
1230 
1231         if (fileList->hasUnInsetFrame) {
1232             hasPendingData = NSTACKX_TRUE;
1233             break;
1234         }
1235     }
1236     if (PthreadMutexUnlock(&fileManager->taskList.lock) != 0) {
1237         DFILE_LOGE(TAG, "pthread mutex unlock error");
1238         fileManager->errCode = FILE_MANAGER_EMUTEX;
1239         NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1240         return NSTACKX_FALSE;
1241     }
1242     for (uint32_t i = 0; i < fileManager->sendFrameListNum; i++) {
1243         if (fileManager->sendBlockFrameListPara[i].sendBlockFrameList.size > 0) {
1244             return NSTACKX_TRUE;
1245         }
1246     }
1247 
1248     return hasPendingData;
1249 }
1250 
FileManagerHasPendingData(FileManager * fileManager)1251 uint8_t FileManagerHasPendingData(FileManager *fileManager)
1252 {
1253     return FileManagerHasPendingDataInner(fileManager);
1254 }
1255 
FileManagerGetLastSequence(FileManager * fileManager,uint16_t transId,uint16_t fileId,uint32_t * sequence)1256 int32_t FileManagerGetLastSequence(FileManager *fileManager, uint16_t transId, uint16_t fileId, uint32_t *sequence)
1257 {
1258     FileListTask *fileList = NULL;
1259     uint8_t isErrorOccurred;
1260     if (fileManager == NULL || transId == 0 || fileId == 0) {
1261         DFILE_LOGE(TAG, "invalid input");
1262         return NSTACKX_EINVAL;
1263     }
1264 
1265     fileList = GetFileListById(&fileManager->taskList, transId, &isErrorOccurred);
1266     if (isErrorOccurred) {
1267         fileManager->errCode = FILE_MANAGER_EMUTEX;
1268         NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1269         DFILE_LOGE(TAG, "failed to get target fileList %hu", transId);
1270         return NSTACKX_EFAILED;
1271     }
1272     if (fileList == NULL || fileId > fileList->fileNum) {
1273         DFILE_LOGE(TAG, "failed to get target fileList %hu", transId);
1274         return NSTACKX_EFAILED;
1275     }
1276 
1277     if (fileList->fileInfo[fileId - 1].totalBlockNum == 0) {
1278         *sequence = 0;
1279     } else {
1280         *sequence = fileList->fileInfo[fileId - 1].totalBlockNum - 1;
1281     }
1282     return NSTACKX_EOK;
1283 }
1284