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(¶->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(¶->sendBlockFrameList.head, &blockFrame->list);
479 }
480 *isAdded = NSTACKX_TRUE;
481 para->sendBlockFrameList.size++;
482 if (PthreadMutexUnlock(¶->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, ¶->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, ¶->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(¶->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(¶->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(¶->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(¶->sendBlockFrameList.head);
978 if (cur == NULL) {
979 break;
980 }
981 para->sendBlockFrameList.size--;
982 if (para->sendRetranListTail == cur) {
983 para->sendRetranListTail = ¶->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(¶->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(¶->sendBlockFrameList.lock) != 0) {
1008 LOGE(TAG, "pthread mutex unlock error");
1009 }
1010 for (int i = 0; i < ret; ++i) {
1011 SemPost(¶->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(¶->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(¶->sendBlockFrameList, sendListSize) != NSTACKX_EOK) {
1054 LOGE(TAG, "sendBlockFrameList InitList error");
1055 goto L_ERR_FILE_MANAGER;
1056 }
1057 para->sendRetranListTail = ¶->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(¶->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(¶->sendBlockFrameList.lock) != 0) {
1096 LOGE(TAG, "pthread mutex lock error");
1097 }
1098 while (para->sendBlockFrameList.size > 0) {
1099 blockFrame = (BlockFrame *)ListPopFront(¶->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 = ¶->sendBlockFrameList.head;
1108 if (PthreadMutexUnlock(¶->sendBlockFrameList.lock) != 0) {
1109 LOGE(TAG, "pthread mutex unlock error");
1110 }
1111 MutexListDestory(¶->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