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 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 DFILE_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 DFILE_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 DFILE_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 DFILE_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 DFILE_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 DFILE_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 DFILE_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 DFILE_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 DFILE_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 DFILE_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 DFILE_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 DFILE_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 }
532
PushRetranBlockFrame(FileManager * fileManager,const FileListTask * fileList,const FileDataFrame * fileDataFrame)533 uint8_t PushRetranBlockFrame(FileManager *fileManager, const FileListTask *fileList, const FileDataFrame *fileDataFrame)
534 {
535 uint8_t ret = NSTACKX_FALSE;
536 SendBlockFrameListPara *para = &fileManager->sendBlockFrameListPara[fileList->bindedSendBlockListIdx];
537 if (fileDataFrame == NULL) {
538 DFILE_LOGE(TAG, "frame is NULL");
539 return ret;
540 }
541 CheckSendListFullAndWait(fileManager, ¶->semBlockListNotFull);
542 if (CheckManager(fileManager) != NSTACKX_EOK) {
543 return ret;
544 }
545 if (PushFileBlockFrame(fileManager, fileList, fileDataFrame, NSTACKX_TRUE, &ret) != NSTACKX_EOK) {
546 DFILE_LOGE(TAG, "push retran block error");
547 }
548 return ret;
549 }
550
PushSendBlockFrame(FileManager * fileManager,const FileListTask * fileList,const FileDataFrame * fileDataFrame)551 uint8_t PushSendBlockFrame(FileManager *fileManager, const FileListTask *fileList, const FileDataFrame *fileDataFrame)
552 {
553 uint8_t isAdded = NSTACKX_FALSE;
554
555 SendBlockFrameListPara *para = &fileManager->sendBlockFrameListPara[fileList->bindedSendBlockListIdx];
556 if (fileDataFrame == NULL) {
557 return NSTACKX_FALSE;
558 }
559
560 CheckSendListFullAndWait(fileManager, ¶->semBlockListNotFull);
561 if (CheckManager(fileManager) != NSTACKX_EOK) {
562 return NSTACKX_FALSE;
563 }
564 if (PushFileBlockFrame(fileManager, fileList, fileDataFrame, NSTACKX_FALSE, &isAdded) != NSTACKX_EOK) {
565 return NSTACKX_FALSE;
566 }
567
568 return isAdded;
569 }
570
CreateSendBlockTarFrames(FileManager * fileManager,FileListTask * fileList)571 static uint8_t CreateSendBlockTarFrames(FileManager *fileManager, FileListTask *fileList)
572 {
573 (void)fileManager;
574 (void)fileList;
575 return NSTACKX_FALSE;
576 }
577
SendTaskProcess(FileManager * fileManager,FileListTask * fileList)578 void SendTaskProcess(FileManager *fileManager, FileListTask *fileList)
579 {
580 FileDataFrame *fileDataFrame = NULL;
581 uint8_t isAdded;
582 uint8_t isEmpty;
583 SendBlockFrameListPara *para = &fileManager->sendBlockFrameListPara[fileList->bindedSendBlockListIdx];
584 while (NSTACKX_TRUE) {
585 if (CheckFilelist(fileList) != NSTACKX_EOK || CheckManager(fileManager) != NSTACKX_EOK) {
586 break;
587 }
588 isEmpty = NSTACKX_FALSE;
589 if (fileList->sendRetranList.size == 0) {
590 isEmpty = NSTACKX_TRUE;
591 }
592 if (isEmpty != NSTACKX_TRUE) {
593 fileDataFrame = CreateRetranBlockFrame(fileManager, fileList);
594 isAdded = PushRetranBlockFrame(fileManager, fileList, fileDataFrame);
595 } else if (fileList->sendFileProcessed >= fileList->fileNum && fileList->newReadOutSet.fileId == 0) {
596 SemWait(&fileList->semStop);
597 continue;
598 } else {
599 if ((fileList->tarFlag == NSTACKX_TRUE) && (fileList->tarFinished != NSTACKX_TRUE)) {
600 isAdded = CreateSendBlockTarFrames(fileManager, fileList);
601 } else {
602 fileDataFrame = CreateSendBlockFrame(fileManager, fileList);
603 isAdded = PushSendBlockFrame(fileManager, fileList, fileDataFrame);
604 }
605 }
606 if (fileDataFrame != NULL) {
607 if (isAdded != NSTACKX_TRUE) {
608 free(fileDataFrame);
609 SemPost(¶->semBlockListNotFull);
610 }
611 fileList->hasUnInsetFrame = NSTACKX_FALSE;
612 }
613 }
614
615 if (fileList->errCode != FILE_MANAGER_EOK) {
616 DFILE_LOGE(TAG, "send task process failed %d", fileList->errCode);
617 NotifyFileListMsg(fileList, FILE_MANAGER_SEND_FAIL);
618 }
619 }
620
PackGetTarBlockLen(const FileListTask * fmFileList)621 uint64_t PackGetTarBlockLen(const FileListTask *fmFileList)
622 {
623 char pathSeparator = '/';
624 uint64_t tarFilesTotalLen = 0;
625 uint64_t blockCnt;
626 uint32_t i;
627 char *path = NULL;
628
629 for (i = 0; i < fmFileList->fileNum; i++) {
630 tarFilesTotalLen += BLOCK_LEN;
631
632 path = fmFileList->fileInfo[i].fileName;
633 if (strlen(path) > MAX_NAME_LEN) {
634 // +1 because of the string end '\0'
635 tarFilesTotalLen += BLOCK_LEN +
636 (((strlen(path) + 1 - (long long)(path[0] == pathSeparator) + BLOCK_LEN - 1) / BLOCK_LEN) * BLOCK_LEN);
637 }
638
639 // file body length
640 blockCnt = (fmFileList->fileInfo[i].fileSize + BLOCK_LEN - 1) / BLOCK_LEN;
641 tarFilesTotalLen += (blockCnt * BLOCK_LEN);
642 }
643
644 // file tail paddings length
645 tarFilesTotalLen += BLOCK_LEN;
646
647 return tarFilesTotalLen;
648 }
649
AddTarFileInfo(const char * tarFileName,FileListTask * fmFileList,uint16_t standardBlockSize)650 static int32_t AddTarFileInfo(const char *tarFileName, FileListTask *fmFileList, uint16_t standardBlockSize)
651 {
652 uint64_t tarFilesTotalLen;
653 tarFilesTotalLen = PackGetTarBlockLen(fmFileList);
654 fmFileList->blockOffset = 0;
655 fmFileList->tarFrame = NULL;
656 fmFileList->tarFileInfo.fd = NSTACKX_INVALID_FD;
657 fmFileList->tarFileInfo.fileSize = tarFilesTotalLen;
658 fmFileList->tarFileInfo.standardBlockSize = standardBlockSize;
659 fmFileList->tarFileInfo.totalBlockNum = (uint32_t)((tarFilesTotalLen + standardBlockSize - 1) / standardBlockSize);
660 fmFileList->tarFileInfo.fileId = 1;
661 fmFileList->tarFileInfo.maxSequenceSend = -1;
662 fmFileList->tarFileInfo.tarData = NULL;
663 fmFileList->tarFileInfo.writeOffset = 0;
664 DFILE_LOGI(TAG, "tarLen: %llu, blockNum: %u, endLen: %llu", tarFilesTotalLen,
665 fmFileList->tarFileInfo.totalBlockNum, tarFilesTotalLen % standardBlockSize);
666 fmFileList->tarFileInfo.fileName = realpath(tarFileName, NULL);
667 if ((fmFileList->tarFileInfo.fileName == NULL) ||
668 (!IsAccessiblePath(fmFileList->tarFileInfo.fileName, R_OK, S_IFREG))) {
669 return NSTACKX_EFAILED;
670 }
671 fmFileList->tarFd = NULL;
672 fmFileList->totalBytes = fmFileList->tarFileInfo.fileSize;
673 return NSTACKX_EOK;
674 }
675
AddSendFileInfo(const SendFileListInfo * fileListInfo,FileListTask * fmFileList,uint16_t standardBlockSize)676 static int32_t AddSendFileInfo(const SendFileListInfo *fileListInfo,
677 FileListTask *fmFileList, uint16_t standardBlockSize)
678 {
679 uint16_t i;
680 FileInfo *fileInfo = NULL;
681 for (i = 0; i < fmFileList->fileNum; i++) {
682 if (fileListInfo->fileList[i] == NULL) {
683 goto L_ERR_FILE_MANAGER;
684 }
685 fileInfo = &fmFileList->fileInfo[i];
686 fileInfo->fileName = realpath(fileListInfo->fileList[i], NULL);
687 if (fileInfo->fileName == NULL || !IsAccessiblePath(fileInfo->fileName, R_OK, S_IFREG)) {
688 DFILE_LOGE(TAG, "can't get canonicalized absolute pathname, error(%d)", errno);
689 goto L_ERR_FILE_MANAGER;
690 }
691 fileInfo->fileSize = fileListInfo->fileSize[i];
692 fileInfo->standardBlockSize = standardBlockSize;
693 fileInfo->totalBlockNum = (uint32_t)(fileInfo->fileSize / standardBlockSize);
694 if (fileInfo->fileSize % standardBlockSize != 0) {
695 fileInfo->totalBlockNum++;
696 }
697 fmFileList->totalBytes += fileInfo->fileSize;
698 fileInfo->fileId = i + 1;
699 fileInfo->startOffset = fileListInfo->startOffset[i];
700 fileInfo->maxSequenceSend = -1;
701 fileInfo->fd = NSTACKX_INVALID_FD;
702 fileInfo->errCode = FILE_MANAGER_EOK;
703 fileInfo->fileOffset = 0;
704 fileInfo->tarData = NULL;
705 fileInfo->writeOffset = 0;
706 }
707
708 if (fmFileList->tarFlag &&
709 AddTarFileInfo(fileListInfo->fileList[fmFileList->fileNum], fmFileList, standardBlockSize) != NSTACKX_EOK) {
710 goto L_ERR_FILE_MANAGER;
711 }
712
713 return NSTACKX_EOK;
714 L_ERR_FILE_MANAGER:
715 for (i = 0; i < fmFileList->fileNum; i++) {
716 free(fmFileList->fileInfo[i].fileName);
717 fmFileList->fileInfo[i].fileName = NULL;
718 }
719 return NSTACKX_EFAILED;
720 }
721
InitSendFilesOutSet(FileListTask * fmFileList)722 static int32_t InitSendFilesOutSet(FileListTask *fmFileList)
723 {
724 if (PthreadMutexInit(&fmFileList->newReadOutSet.lock, NULL) != 0) {
725 DFILE_LOGE(TAG, "PthreadMutexInit error");
726 return NSTACKX_EFAILED;
727 }
728 fmFileList->newReadOutSet.fileId = 0;
729 fmFileList->newReadOutSet.blockSequence = 0;
730 return NSTACKX_EOK;
731 }
732
CreateSendFileList(const SendFileListInfo * fileListInfo,uint16_t standardBlockSize,const FileListMsgPara * msgPara)733 static FileListTask *CreateSendFileList(const SendFileListInfo *fileListInfo,
734 uint16_t standardBlockSize, const FileListMsgPara *msgPara)
735 {
736 FileListTask *fmFileList = NULL;
737 fmFileList = (FileListTask *)calloc(1, sizeof(FileListTask));
738 if (fmFileList == NULL) {
739 DFILE_LOGE(TAG, "file list calloc error");
740 return NULL;
741 }
742 fmFileList->transId = fileListInfo->transId;
743 fmFileList->fileNum = fileListInfo->fileNum;
744 fmFileList->tarFlag = fileListInfo->tarFlag;
745 fmFileList->smallFlag = fileListInfo->smallFlag;
746 if (SemInit(&fmFileList->semStop, 0, 0) != 0) {
747 DFILE_LOGE(TAG, "SemInit error");
748 goto L_ERR_FILE_MANAGER;
749 }
750 fmFileList->runStatus = FILE_LIST_STATUS_IDLE;
751 fmFileList->stopType = FILE_LIST_TRANSFER_FINISH;
752 fmFileList->isOccupied = NSTACKX_FALSE;
753 fmFileList->errCode = FILE_MANAGER_EOK;
754 fmFileList->sendFileProcessed = 0;
755
756 if (MutexListInit(&fmFileList->sendRetranList, NSTACKX_MAX_RETRAN_BLOCK_NUM) != NSTACKX_EOK) {
757 DFILE_LOGE(TAG, "sendRetranList init error");
758 SemDestroy(&fmFileList->semStop);
759 goto L_ERR_FILE_MANAGER;
760 }
761
762 if (InitSendFilesOutSet(fmFileList) != NSTACKX_EOK) {
763 SemDestroy(&fmFileList->semStop);
764 MutexListDestory(&fmFileList->sendRetranList);
765 DFILE_LOGE(TAG, "InitRetranFilesInfo error");
766 goto L_ERR_FILE_MANAGER;
767 }
768
769 if (AddSendFileInfo(fileListInfo, fmFileList, standardBlockSize) != NSTACKX_EOK) {
770 DFILE_LOGE(TAG, "AddSendFileInfo init error");
771 SemDestroy(&fmFileList->semStop);
772 MutexListDestory(&fmFileList->sendRetranList);
773 PthreadMutexDestroy(&fmFileList->newReadOutSet.lock);
774 goto L_ERR_FILE_MANAGER;
775 }
776
777 if (msgPara != NULL) {
778 fmFileList->msgReceiver = msgPara->msgReceiver;
779 fmFileList->context = msgPara->context;
780 }
781 return fmFileList;
782 L_ERR_FILE_MANAGER:
783 (void)memset_s(fmFileList, sizeof(FileListTask), 0, sizeof(FileListTask));
784 free(fmFileList);
785 return NULL;
786 }
787
GetTargetSendBlockListIdx(const FileManager * fileManager)788 static uint32_t GetTargetSendBlockListIdx(const FileManager *fileManager)
789 {
790 uint32_t ret = 0;
791 uint32_t bindingNum = NSTACKX_MAX_PROCESSING_TASK_NUM;
792
793 for (uint32_t i = 0; i < fileManager->sendFrameListNum; i++) {
794 if (fileManager->sendBlockFrameListPara[i].bandingTransNum < bindingNum) {
795 bindingNum = fileManager->sendBlockFrameListPara[i].bandingTransNum;
796 ret = i;
797 }
798 }
799 return ret;
800 }
801
FileManagerSendFileTask(FileManager * fileManager,const SendFileListInfo * fileListInfo,const FileListMsgPara * msgPara)802 int32_t FileManagerSendFileTask(FileManager *fileManager, const SendFileListInfo *fileListInfo,
803 const FileListMsgPara *msgPara)
804 {
805 FileListTask *fmFileList = NULL;
806 uint16_t standardBlockSize;
807 if (CheckSenderManager(fileManager) != NSTACKX_EOK || fileListInfo == NULL ||
808 fileListInfo->fileNum == 0 || fileListInfo->fileNum > NSTACKX_DFILE_MAX_FILE_NUM) {
809 DFILE_LOGE(TAG, "Invalid input");
810 return NSTACKX_EINVAL;
811 }
812 if (fileManager->taskList.size >= fileManager->taskList.maxSize) {
813 DFILE_LOGE(TAG, "task list is full");
814 return NSTACKX_EFAILED;
815 }
816 standardBlockSize = GetStandardBlockSize(fileManager);
817 if (standardBlockSize == 0) {
818 DFILE_LOGE(TAG, "max frame length is too small");
819 return NSTACKX_EFAILED;
820 }
821
822 fmFileList = CreateSendFileList(fileListInfo, standardBlockSize, msgPara);
823 if (fmFileList == NULL) {
824 DFILE_LOGE(TAG, "Can't creat fmFileList");
825 return NSTACKX_EFAILED;
826 }
827 fmFileList->maxFrameLength = fileManager->maxFrameLength;
828 fmFileList->epollfd = fileManager->epollfd;
829 fmFileList->eventNodeChain = fileManager->eventNodeChain;
830 if (fileManager->keyLen > 0 && SetCryptPara(fmFileList, fileManager->key, fileManager->keyLen) != NSTACKX_EOK) {
831 ClearSendFileList(fileManager, fmFileList);
832 return NSTACKX_EFAILED;
833 }
834 PeerInfo *peerinfo = ClientGetPeerInfoByTransId((DFileSession *)fileManager->context);
835 if (!peerinfo) {
836 ClearSendFileList(fileManager, fmFileList);
837 return NSTACKX_EFAILED;
838 }
839 fmFileList->socketIndex = peerinfo->socketIndex;
840 fmFileList->bindedSendBlockListIdx = GetTargetSendBlockListIdx(fileManager);
841 if (MutexListAddNode(&fileManager->taskList, &fmFileList->list, NSTACKX_FALSE) != NSTACKX_EOK) {
842 DFILE_LOGE(TAG, "Add tast to list error");
843 ClearSendFileList(fileManager, fmFileList);
844 fileManager->errCode = FILE_MANAGER_EMUTEX;
845 NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
846 return NSTACKX_EFAILED;
847 }
848 fileManager->totalBytes += fmFileList->totalBytes;
849 fileManager->sendBlockFrameListPara[fmFileList->bindedSendBlockListIdx].bandingTransNum++;
850 SemPost(&fileManager->semTaskListNotEmpty);
851 return NSTACKX_EOK;
852 }
853
GetRetranFileLostBlocks(const FileListTask * fileList,uint16_t fileId,uint32_t blockSequence)854 static int32_t GetRetranFileLostBlocks(const FileListTask *fileList, uint16_t fileId, uint32_t blockSequence)
855 {
856 uint32_t ret = 0;
857
858 if (fileList->tarFlag && fileList->tarFinished) {
859 return (int32_t)(fileList->tarFileInfo.totalBlockNum - blockSequence);
860 }
861
862 for (uint16_t i = fileId; i <= fileList->sendFileProcessed + 1 && i <= fileList->fileNum; i++) {
863 ret += (uint32_t)(fileList->fileInfo[i - 1].maxSequenceSend + 1);
864 }
865
866 if (ret >= blockSequence) {
867 ret -= blockSequence;
868 } else {
869 ret = 0;
870 }
871
872 if (ret > INT32_MAX) {
873 ret = INT32_MAX;
874 }
875 return (int32_t)ret;
876 }
877
IsValidOutSet(const FileListTask * fileList,uint16_t fileId,uint32_t blockSequence)878 static uint8_t IsValidOutSet(const FileListTask *fileList, uint16_t fileId, uint32_t blockSequence)
879 {
880 uint32_t totalBlockNum;
881 uint16_t fileNum;
882 fileNum = (fileList->tarFlag == NSTACKX_TRUE) ? 1 : fileList->fileNum;
883 if (fileId == 0 || fileId > fileNum) {
884 DFILE_LOGE(TAG, "new outset fileId is illegal");
885 return NSTACKX_FALSE;
886 }
887
888 totalBlockNum = (fileList->tarFlag == NSTACKX_TRUE) ?
889 fileList->tarFileInfo.totalBlockNum : fileList->fileInfo[fileId - 1].totalBlockNum;
890 if (blockSequence >= totalBlockNum) {
891 DFILE_LOGE(TAG, "new outset blockSequence is illegal");
892 return NSTACKX_FALSE;
893 }
894 return NSTACKX_TRUE;
895 }
896
FileManagerResetSendOutSet(FileManager * fileManager,uint16_t fileId,uint32_t blockSequence,uint16_t transId)897 int32_t FileManagerResetSendOutSet(FileManager *fileManager, uint16_t fileId, uint32_t blockSequence, uint16_t transId)
898 {
899 FileListTask *fileList = NULL;
900 uint8_t isErrorOccured;
901 int32_t ret;
902
903 if (CheckSenderManager(fileManager) != NSTACKX_EOK ||
904 fileManager->maxFrameLength <= offsetof(FileDataFrame, blockPayload)) {
905 DFILE_LOGE(TAG, "Invalid input");
906 return NSTACKX_EINVAL;
907 }
908 fileList = GetFileListById(&fileManager->taskList, transId, &isErrorOccured);
909 if (isErrorOccured) {
910 DFILE_LOGE(TAG, "get target file list error");
911 goto L_ERR_FILE_MANAGER;
912 }
913
914 if (CheckFilelistNotStop(fileList) != NSTACKX_EOK) {
915 DFILE_LOGE(TAG, "target file list is not available");
916 return NSTACKX_EFAILED;
917 }
918
919 if (!IsValidOutSet(fileList, fileId, blockSequence)) {
920 return NSTACKX_EFAILED;
921 }
922
923 ret = GetRetranFileLostBlocks(fileList, fileId, blockSequence);
924 if (fileList->tarFlag && fileList->tarFinished != NSTACKX_TRUE) {
925 return ret;
926 }
927 if (PthreadMutexLock(&fileList->newReadOutSet.lock) != 0) {
928 DFILE_LOGE(TAG, "pthread mutex lock error");
929 goto L_ERR_FILE_MANAGER;
930 }
931 fileList->newReadOutSet.blockSequence = blockSequence;
932 fileList->newReadOutSet.fileId = fileId;
933
934 if (PthreadMutexUnlock(&fileList->newReadOutSet.lock) != 0) {
935 DFILE_LOGE(TAG, "pthread mutex unlock error");
936 goto L_ERR_FILE_MANAGER;
937 }
938 SemPost(&fileList->semStop);
939 return ret;
940
941 L_ERR_FILE_MANAGER:
942 NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
943 if (fileList != NULL) {
944 NotifyFileListMsg(fileList, FILE_MANAGER_SEND_FAIL);
945 }
946 return NSTACKX_EFAILED;
947 }
948
GetSendBlockFrameListPara(FileManager * fileManager,uint32_t tid)949 static SendBlockFrameListPara *GetSendBlockFrameListPara(FileManager *fileManager, uint32_t tid)
950 {
951 SendBlockFrameListPara *para = NULL;
952
953 if (tid < fileManager->sendFrameListNum) {
954 para = &fileManager->sendBlockFrameListPara[tid];
955 if (!ListIsEmpty(¶->sendBlockFrameList.head)) {
956 return para;
957 }
958 }
959
960 for (uint32_t i = 0; i < fileManager->sendFrameListNum; i++) {
961 para = &fileManager->sendBlockFrameListPara[i];
962 if (!ListIsEmpty(¶->sendBlockFrameList.head)) {
963 return para;
964 }
965 }
966 return NULL;
967 }
968
GetMultipleBlockFrame(SendBlockFrameListPara * para,BlockFrame ** block,int32_t nr)969 static int32_t GetMultipleBlockFrame(SendBlockFrameListPara *para, BlockFrame **block, int32_t nr)
970 {
971 BlockFrame *frame = NULL;
972 List *cur = NULL;
973 int32_t cnt;
974
975 for (cnt = 0; cnt < nr; ++cnt) {
976 cur = ListPopFront(¶->sendBlockFrameList.head);
977 if (cur == NULL) {
978 break;
979 }
980 para->sendBlockFrameList.size--;
981 if (para->sendRetranListTail == cur) {
982 para->sendRetranListTail = ¶->sendBlockFrameList.head;
983 }
984 if (frame != NULL) {
985 frame->list.next = cur;
986 frame = (BlockFrame *)(void *)cur;
987 } else {
988 frame = (BlockFrame *)(void *)cur;
989 *block = frame;
990 }
991 }
992 return cnt;
993 }
994
GetDataFrameFromSendList(SendBlockFrameListPara * para,BlockFrame ** block,int32_t nr)995 static int32_t GetDataFrameFromSendList(SendBlockFrameListPara *para, BlockFrame **block, int32_t nr)
996 {
997 int32_t ret;
998
999 if (PthreadMutexLock(¶->sendBlockFrameList.lock) != 0) {
1000 DFILE_LOGE(TAG, "pthread mutex lock error");
1001 return FILE_MANAGER_EMUTEX;
1002 }
1003
1004 ret = GetMultipleBlockFrame(para, block, nr);
1005
1006 if (PthreadMutexUnlock(¶->sendBlockFrameList.lock) != 0) {
1007 DFILE_LOGE(TAG, "pthread mutex unlock error");
1008 }
1009 for (int i = 0; i < ret; ++i) {
1010 SemPost(¶->semBlockListNotFull);
1011 }
1012 return ret;
1013 }
1014
FileManagerFileRead(FileManager * fileManager,uint32_t tid,BlockFrame ** block,int32_t nr)1015 int32_t FileManagerFileRead(FileManager *fileManager, uint32_t tid, BlockFrame **block, int32_t nr)
1016 {
1017 int32_t ret;
1018 SendBlockFrameListPara *para = NULL;
1019 *block = NULL;
1020
1021 if (CheckSenderManager(fileManager) != NSTACKX_EOK) {
1022 DFILE_LOGE(TAG, "Invalid input");
1023 return NSTACKX_EINVAL;
1024 }
1025
1026 para = GetSendBlockFrameListPara(fileManager, tid);
1027 if (para == NULL || ListIsEmpty(¶->sendBlockFrameList.head)) {
1028 return 0;
1029 }
1030 ret = GetDataFrameFromSendList(para, block, nr);
1031 if (ret < 0) {
1032 fileManager->errCode = ret;
1033 NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1034 DFILE_LOGE(TAG, "GetDataFrameFromSendList failed");
1035 return ret;
1036 }
1037 if (*block != NULL) {
1038 RefreshBytesTransFerred(fileManager, *block);
1039 }
1040
1041 return ret;
1042 }
1043
InitSendBlockLists(FileManager * fileManager)1044 int32_t InitSendBlockLists(FileManager *fileManager)
1045 {
1046 uint32_t i;
1047 SendBlockFrameListPara *para = NULL;
1048 uint32_t sendListSize = fileManager->maxSendBlockListSize;
1049
1050 for (i = 0; i < fileManager->sendFrameListNum; i++) {
1051 para = &fileManager->sendBlockFrameListPara[i];
1052 if (MutexListInit(¶->sendBlockFrameList, sendListSize) != NSTACKX_EOK) {
1053 DFILE_LOGE(TAG, "sendBlockFrameList InitList error");
1054 goto L_ERR_FILE_MANAGER;
1055 }
1056 para->sendRetranListTail = ¶->sendBlockFrameList.head;
1057 }
1058 return NSTACKX_EOK;
1059
1060 L_ERR_FILE_MANAGER:
1061 while (i > 0) {
1062 para = &fileManager->sendBlockFrameListPara[i - 1];
1063 MutexListDestory(¶->sendBlockFrameList);
1064 para->sendRetranListTail = NULL;
1065 i--;
1066 }
1067 return NSTACKX_EFAILED;
1068 }
1069
GetMaxSendListSize(uint16_t connType)1070 uint32_t GetMaxSendListSize(uint16_t connType)
1071 {
1072 if (connType == CONNECT_TYPE_WLAN) {
1073 return NSTACKX_WLAN_SEND_BLOCK_QUEUE_MAX_LEN;
1074 } else if (connType == CONNECT_TYPE_P2P) {
1075 return NSTACKX_P2P_SEND_BLOCK_QUEUE_MAX_LEN;
1076 } else {
1077 DFILE_LOGE(TAG, "invalid connect type");
1078 return 0;
1079 }
1080 }
1081
GetSendListNum(void)1082 uint16_t GetSendListNum(void)
1083 {
1084 return 1;
1085 }
1086
ClearSendFrameList(FileManager * fileManager)1087 void ClearSendFrameList(FileManager *fileManager)
1088 {
1089 BlockFrame *blockFrame = NULL;
1090 uint32_t i;
1091 SendBlockFrameListPara *para = NULL;
1092 for (i = 0; i < fileManager->sendFrameListNum; i++) {
1093 para = &fileManager->sendBlockFrameListPara[i];
1094 if (PthreadMutexLock(¶->sendBlockFrameList.lock) != 0) {
1095 DFILE_LOGE(TAG, "pthread mutex lock error");
1096 }
1097 while (para->sendBlockFrameList.size > 0) {
1098 blockFrame = (BlockFrame *)ListPopFront(¶->sendBlockFrameList.head);
1099 para->sendBlockFrameList.size--;
1100 if (blockFrame != NULL) {
1101 free(blockFrame->fileDataFrame);
1102 free(blockFrame);
1103 blockFrame = NULL;
1104 }
1105 }
1106 para->sendRetranListTail = ¶->sendBlockFrameList.head;
1107 if (PthreadMutexUnlock(¶->sendBlockFrameList.lock) != 0) {
1108 DFILE_LOGE(TAG, "pthread mutex unlock error");
1109 }
1110 MutexListDestory(¶->sendBlockFrameList);
1111 }
1112 }
1113
FileManagerIsLastBlockRead(FileManager * fileManager,uint16_t transId)1114 uint8_t FileManagerIsLastBlockRead(FileManager *fileManager, uint16_t transId)
1115 {
1116 FileListTask *fileList = NULL;
1117 uint8_t isErrorOccured;
1118 if (fileManager == NULL) {
1119 return NSTACKX_FALSE;
1120 }
1121 fileList = GetFileListById(&fileManager->taskList, transId, &isErrorOccured);
1122 if (isErrorOccured) {
1123 fileManager->errCode = FILE_MANAGER_EMUTEX;
1124 NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1125 return NSTACKX_FALSE;
1126 }
1127 if (fileList == NULL) {
1128 return NSTACKX_FALSE;
1129 }
1130 if (fileList->newReadOutSet.fileId == 0 && fileList->sendFileProcessed == fileList->fileNum &&
1131 fileList->sendRetranList.size == 0 && !fileList->hasUnInsetFrame) {
1132 return NSTACKX_TRUE;
1133 }
1134 return NSTACKX_FALSE;
1135 }
1136
FileManagerHasPendingDataMp(FileManager * fileManager,uint8_t socketIndex)1137 uint8_t FileManagerHasPendingDataMp(FileManager *fileManager, uint8_t socketIndex)
1138 {
1139 List *list = NULL;
1140 FileListTask *fileList = NULL;
1141 uint8_t hasPendingData = NSTACKX_FALSE;
1142
1143 if (fileManager == NULL || fileManager->isSender != NSTACKX_TRUE) {
1144 return NSTACKX_FALSE;
1145 }
1146
1147 if (fileManager->sendBlockFrameListPara[socketIndex].sendBlockFrameList.size > 0) {
1148 return NSTACKX_TRUE;
1149 }
1150
1151 if (PthreadMutexLock(&fileManager->taskList.lock) != 0) {
1152 DFILE_LOGE(TAG, "pthread mutex lock error");
1153 fileManager->errCode = FILE_MANAGER_EMUTEX;
1154 NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1155 return NSTACKX_FALSE;
1156 }
1157
1158 LIST_FOR_EACH(list, &fileManager->taskList.head) {
1159 fileList = (FileListTask *)list;
1160 if (fileList->socketIndex != socketIndex || CheckFilelistNotStop(fileList) != NSTACKX_EOK) {
1161 continue;
1162 }
1163
1164 if (fileList->newReadOutSet.fileId > 0) {
1165 hasPendingData = NSTACKX_TRUE;
1166 break;
1167 }
1168
1169 if (fileList->sendFileProcessed < fileList->fileNum) {
1170 hasPendingData = NSTACKX_TRUE;
1171 break;
1172 }
1173 if (fileList->sendRetranList.size > 0) {
1174 hasPendingData = NSTACKX_TRUE;
1175 break;
1176 }
1177
1178 if (fileList->hasUnInsetFrame) {
1179 hasPendingData = NSTACKX_TRUE;
1180 break;
1181 }
1182 }
1183 if (PthreadMutexUnlock(&fileManager->taskList.lock) != 0) {
1184 DFILE_LOGE(TAG, "pthread mutex unlock error");
1185 fileManager->errCode = FILE_MANAGER_EMUTEX;
1186 NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1187 }
1188
1189 return hasPendingData;
1190 }
1191
FileManagerHasPendingDataInner(FileManager * fileManager)1192 uint8_t FileManagerHasPendingDataInner(FileManager *fileManager)
1193 {
1194 List *list = NULL;
1195 FileListTask *fileList = NULL;
1196 uint8_t hasPendingData = NSTACKX_FALSE;
1197
1198 if (fileManager == NULL || fileManager->isSender != NSTACKX_TRUE) {
1199 return NSTACKX_FALSE;
1200 }
1201
1202 if (PthreadMutexLock(&fileManager->taskList.lock) != 0) {
1203 DFILE_LOGE(TAG, "pthread mutex lock error");
1204 fileManager->errCode = FILE_MANAGER_EMUTEX;
1205 NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1206 return NSTACKX_FALSE;
1207 }
1208
1209 LIST_FOR_EACH(list, &fileManager->taskList.head) {
1210 fileList = (FileListTask *)list;
1211 if (CheckFilelistNotStop(fileList) != NSTACKX_EOK) {
1212 continue;
1213 }
1214
1215 if (fileList->newReadOutSet.fileId > 0) {
1216 hasPendingData = NSTACKX_TRUE;
1217 break;
1218 }
1219
1220 if (fileList->sendFileProcessed < fileList->fileNum) {
1221 hasPendingData = NSTACKX_TRUE;
1222 break;
1223 }
1224 if (fileList->sendRetranList.size > 0) {
1225 hasPendingData = NSTACKX_TRUE;
1226 break;
1227 }
1228
1229 if (fileList->hasUnInsetFrame) {
1230 hasPendingData = NSTACKX_TRUE;
1231 break;
1232 }
1233 }
1234 if (PthreadMutexUnlock(&fileManager->taskList.lock) != 0) {
1235 DFILE_LOGE(TAG, "pthread mutex unlock error");
1236 fileManager->errCode = FILE_MANAGER_EMUTEX;
1237 NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1238 return NSTACKX_FALSE;
1239 }
1240 for (uint32_t i = 0; i < fileManager->sendFrameListNum; i++) {
1241 if (fileManager->sendBlockFrameListPara[i].sendBlockFrameList.size > 0) {
1242 return NSTACKX_TRUE;
1243 }
1244 }
1245
1246 return hasPendingData;
1247 }
1248
FileManagerHasPendingData(FileManager * fileManager)1249 uint8_t FileManagerHasPendingData(FileManager *fileManager)
1250 {
1251 return FileManagerHasPendingDataInner(fileManager);
1252 }
1253
FileManagerGetLastSequence(FileManager * fileManager,uint16_t transId,uint16_t fileId,uint32_t * sequence)1254 int32_t FileManagerGetLastSequence(FileManager *fileManager, uint16_t transId, uint16_t fileId, uint32_t *sequence)
1255 {
1256 FileListTask *fileList = NULL;
1257 uint8_t isErrorOccured;
1258 if (fileManager == NULL || transId == 0 || fileId == 0) {
1259 DFILE_LOGE(TAG, "invalid input");
1260 return NSTACKX_EINVAL;
1261 }
1262
1263 fileList = GetFileListById(&fileManager->taskList, transId, &isErrorOccured);
1264 if (isErrorOccured) {
1265 fileManager->errCode = FILE_MANAGER_EMUTEX;
1266 NotifyFileManagerMsg(fileManager, FILE_MANAGER_INNER_ERROR);
1267 DFILE_LOGE(TAG, "failed to get target fileList %hu", transId);
1268 return NSTACKX_EFAILED;
1269 }
1270 if (fileList == NULL || fileId > fileList->fileNum) {
1271 DFILE_LOGE(TAG, "failed to get target fileList %hu", transId);
1272 return NSTACKX_EFAILED;
1273 }
1274
1275 if (fileList->fileInfo[fileId - 1].totalBlockNum == 0) {
1276 *sequence = 0;
1277 } else {
1278 *sequence = fileList->fileInfo[fileId - 1].totalBlockNum - 1;
1279 }
1280 return NSTACKX_EOK;
1281 }
1282