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