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