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 ClearCryptCtx(fileList->cryptPara.ctx);
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 task 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 isErrorOccurred;
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, &isErrorOccurred);
909 if (isErrorOccurred) {
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 isErrorOccurred;
1118 if (fileManager == NULL) {
1119 return NSTACKX_FALSE;
1120 }
1121 fileList = GetFileListById(&fileManager->taskList, transId, &isErrorOccurred);
1122 if (isErrorOccurred) {
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 isErrorOccurred;
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, &isErrorOccurred);
1264 if (isErrorOccurred) {
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