1 /*
2  * Copyright (c) 2022-2024 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 "client_trans_proxy_file_manager.h"
17 
18 #include <inttypes.h>
19 #include <limits.h>
20 #include <securec.h>
21 #include <stdbool.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <stdatomic.h>
25 
26 #include "client_trans_pending.h"
27 #include "client_trans_proxy_file_helper.h"
28 #include "client_trans_proxy_manager.h"
29 #include "client_trans_session_manager.h"
30 #include "client_trans_socket_manager.h"
31 #include "lnn_lane_interface.h"
32 #include "softbus_adapter_errcode.h"
33 #include "softbus_adapter_file.h"
34 #include "softbus_adapter_mem.h"
35 #include "softbus_adapter_socket.h"
36 #include "softbus_app_info.h"
37 #include "softbus_def.h"
38 #include "softbus_errcode.h"
39 #include "softbus_utils.h"
40 #include "trans_log.h"
41 
42 static TransFileInfoLock g_sendFileInfoLock = {
43     .lock = 0,
44     .lockInitFlag = false,
45 };
46 static TransFileInfoLock g_recvFileInfoLock = {
47     .lock = 0,
48     .lockInitFlag = false,
49 };
50 static LIST_HEAD(g_sessionFileLockList);
51 static LIST_HEAD(g_sendListenerInfoList);
52 static LIST_HEAD(g_recvRecipientInfoList);
53 
ClearRecipientResources(FileRecipientInfo * info)54 static void ClearRecipientResources(FileRecipientInfo *info)
55 {
56     if (info->recvFileInfo.fileFd != INVALID_FD) {
57         (void)FileUnLock(info->recvFileInfo.fileFd);
58         SoftBusCloseFile(info->recvFileInfo.fileFd);
59         info->recvFileInfo.fileFd = INVALID_FD;
60     }
61     if (info->recvState == TRANS_FILE_RECV_ERR_STATE) {
62         SoftBusRemoveFile(info->recvFileInfo.filePath);
63         if (info->crc == APP_INFO_FILE_FEATURES_SUPPORT) {
64             (void)SendFileTransResult(info->channelId, info->recvFileInfo.seq, SOFTBUS_FILE_ERR, IS_RECV_RESULT);
65         }
66 
67         if (info->fileListener.socketRecvCallback != NULL) {
68             FileEvent event = { .type = FILE_EVENT_RECV_ERROR };
69             info->fileListener.socketRecvCallback(info->sessionId, &event);
70         } else if (info->fileListener.recvListener.OnFileTransError != NULL) {
71             info->fileListener.recvListener.OnFileTransError(info->sessionId);
72         }
73     }
74 }
SetRecipientRecvState(FileRecipientInfo * recipient,int32_t state)75 static void SetRecipientRecvState(FileRecipientInfo *recipient, int32_t state)
76 {
77     if (SoftBusMutexLock(&g_recvFileInfoLock.lock) != SOFTBUS_OK) {
78         return;
79     }
80     if (recipient->recvState != TRANS_FILE_RECV_ERR_STATE) {
81         recipient->recvState = state;
82         if (state == TRANS_FILE_RECV_IDLE_STATE) {
83             recipient->recvFileInfo.fileStatus = NODE_IDLE;
84         }
85     }
86     (void)SoftBusMutexUnlock(&g_recvFileInfoLock.lock);
87 }
88 
ProxyFileTransTimerProc(void)89 static void ProxyFileTransTimerProc(void)
90 {
91 #define FILE_TRANS_TIMEOUT 10
92     if (SoftBusMutexLock(&g_recvFileInfoLock.lock) != SOFTBUS_OK) {
93         TRANS_LOGE(TRANS_FILE, "lock file timer failed");
94         return;
95     }
96     FileRecipientInfo *info = NULL;
97     FileRecipientInfo *next = NULL;
98     LIST_FOR_EACH_ENTRY_SAFE(info, next, &g_recvRecipientInfoList, FileRecipientInfo, node) {
99         if (info->recvState == TRANS_FILE_RECV_IDLE_STATE) {
100             continue;
101         }
102         if (info->recvFileInfo.timeOut >= FILE_TRANS_TIMEOUT) {
103             TRANS_LOGE(TRANS_FILE, "recv timeout, filePath=%{private}s, recvState=%{public}d",
104                 info->recvFileInfo.filePath, info->recvState);
105             info->recvFileInfo.fileStatus = NODE_ERR;
106             info->recvState = TRANS_FILE_RECV_ERR_STATE;
107             info->recvFileInfo.timeOut = 0;
108             info->objRefCount--;
109             ListDelete(&info->node);
110             if (info->objRefCount == 0) {
111                 ClearRecipientResources(info);
112                 SoftBusFree(info);
113             }
114         } else {
115             info->recvFileInfo.timeOut++;
116         }
117     }
118     (void)SoftBusMutexUnlock(&g_recvFileInfoLock.lock);
119 }
120 
ClinetTransProxyFileManagerInit(void)121 int32_t ClinetTransProxyFileManagerInit(void)
122 {
123     if (!atomic_load_explicit(&(g_sendFileInfoLock.lockInitFlag), memory_order_acquire)) {
124         int32_t ret = SoftBusMutexInit(&g_sendFileInfoLock.lock, NULL);
125         TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_FILE, "sendfile mutex init fail!");
126         atomic_store_explicit(&(g_sendFileInfoLock.lockInitFlag), true, memory_order_release);
127     }
128 
129     if (!atomic_load_explicit(&(g_recvFileInfoLock.lockInitFlag), memory_order_acquire)) {
130         int32_t ret = SoftBusMutexInit(&g_recvFileInfoLock.lock, NULL);
131         TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_FILE, "recvfile mutex init fail!");
132         atomic_store_explicit(&(g_recvFileInfoLock.lockInitFlag), true, memory_order_release);
133     }
134     int32_t ret = InitPendingPacket();
135     TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_FILE, "InitPendingPacket fail!");
136 
137     if (RegisterTimeoutCallback(SOFTBUS_PROXY_SENDFILE_TIMER_FUN, ProxyFileTransTimerProc) != SOFTBUS_OK) {
138         TRANS_LOGE(TRANS_FILE, "register sendfile timer fail");
139     }
140     return SOFTBUS_OK;
141 }
142 
ClinetTransProxyFileManagerDeinit(void)143 void ClinetTransProxyFileManagerDeinit(void)
144 {
145     (void)RegisterTimeoutCallback(SOFTBUS_PROXY_SENDFILE_TIMER_FUN, NULL);
146     if (SoftBusMutexDestroy(&g_sendFileInfoLock.lock) != SOFTBUS_OK) {
147         TRANS_LOGE(TRANS_FILE, "destroy send file lock fail");
148     }
149     atomic_store_explicit(&(g_sendFileInfoLock.lockInitFlag), false, memory_order_release);
150     if (SoftBusMutexDestroy(&g_recvFileInfoLock.lock) != SOFTBUS_OK) {
151         TRANS_LOGE(TRANS_FILE, "destroy recv file lock fail");
152     }
153     atomic_store_explicit(&(g_recvFileInfoLock.lockInitFlag), false, memory_order_release);
154 }
155 
GetSessionFileLock(int32_t channelId)156 static ProxyFileMutexLock *GetSessionFileLock(int32_t channelId)
157 {
158     if (SoftBusMutexLock(&g_sendFileInfoLock.lock) != 0) {
159         TRANS_LOGE(TRANS_FILE, "lock mutex failed");
160         return NULL;
161     }
162     ProxyFileMutexLock *item = NULL;
163     ProxyFileMutexLock *sessionLock = NULL;
164     LIST_FOR_EACH_ENTRY(item, &g_sessionFileLockList, ProxyFileMutexLock, node) {
165         if (item->channelId == channelId) {
166             sessionLock = item;
167             break;
168         }
169     }
170     if (sessionLock != NULL) {
171         sessionLock->count++;
172         (void)SoftBusMutexUnlock(&g_sendFileInfoLock.lock);
173         return sessionLock;
174     }
175     sessionLock = (ProxyFileMutexLock *)SoftBusCalloc(sizeof(ProxyFileMutexLock));
176     if (sessionLock == NULL) {
177         (void)SoftBusMutexUnlock(&g_sendFileInfoLock.lock);
178         return NULL;
179     }
180     if (SoftBusMutexInit(&sessionLock->sendLock, NULL) != SOFTBUS_OK) {
181         (void)SoftBusMutexUnlock(&g_sendFileInfoLock.lock);
182         SoftBusFree(sessionLock);
183         return NULL;
184     }
185     ListInit(&sessionLock->node);
186     sessionLock->count = 1;
187     sessionLock->channelId = channelId;
188     ListAdd(&g_sessionFileLockList, &sessionLock->node);
189     TRANS_LOGI(TRANS_FILE, "add channelId=%{public}d", channelId);
190     (void)SoftBusMutexUnlock(&g_sendFileInfoLock.lock);
191     return sessionLock;
192 }
193 
DelSessionFileLock(ProxyFileMutexLock * sessionLock)194 static void DelSessionFileLock(ProxyFileMutexLock *sessionLock)
195 {
196     if (sessionLock == NULL) {
197         return;
198     }
199 
200     if (SoftBusMutexLock(&g_sendFileInfoLock.lock) != SOFTBUS_OK) {
201         TRANS_LOGE(TRANS_FILE, "lock mutex failed");
202         return;
203     }
204     sessionLock->count--;
205     if (sessionLock->count == 0) {
206         ListDelete(&sessionLock->node);
207         (void)SoftBusMutexDestroy(&sessionLock->sendLock);
208         SoftBusFree(sessionLock);
209     }
210     (void)SoftBusMutexUnlock(&g_sendFileInfoLock.lock);
211 }
212 
AddSendListenerInfo(SendListenerInfo * info)213 static int32_t AddSendListenerInfo(SendListenerInfo *info)
214 {
215     if (info == NULL) {
216         TRANS_LOGW(TRANS_FILE, "add send listener info invalid param.");
217         return SOFTBUS_INVALID_PARAM;
218     }
219     if (SoftBusMutexLock(&g_sendFileInfoLock.lock) != SOFTBUS_OK) {
220         TRANS_LOGE(TRANS_FILE, "proxy add send info lock fail");
221         return SOFTBUS_LOCK_ERR;
222     }
223     SendListenerInfo *item = NULL;
224     LIST_FOR_EACH_ENTRY(item, &g_sendListenerInfoList, SendListenerInfo, node) {
225         if (item->sessionId == info->sessionId) {
226             (void)SoftBusMutexUnlock(&g_sendFileInfoLock.lock);
227             return SOFTBUS_ALREADY_EXISTED;
228         }
229     }
230     ListTailInsert(&g_sendListenerInfoList, &info->node);
231     (void)SoftBusMutexUnlock(&g_sendFileInfoLock.lock);
232     return SOFTBUS_OK;
233 }
234 
DelSendListenerInfo(SendListenerInfo * info)235 static void DelSendListenerInfo(SendListenerInfo *info)
236 {
237     if (info == NULL) {
238         TRANS_LOGW(TRANS_FILE, "invalid param.");
239         return;
240     }
241     if (SoftBusMutexLock(&g_sendFileInfoLock.lock) != SOFTBUS_OK) {
242         TRANS_LOGE(TRANS_FILE, "mutex lock error.");
243         return;
244     }
245     ListDelete(&info->node);
246     TRANS_LOGI(TRANS_FILE, "delete sessionId=%{public}d", info->sessionId);
247     SoftBusFree(info);
248     (void)SoftBusMutexUnlock(&g_sendFileInfoLock.lock);
249 }
250 
PackFileTransStartInfo(FileFrame * fileFrame,const char * destFile,uint64_t fileSize,const SendListenerInfo * info)251 static int32_t PackFileTransStartInfo(
252     FileFrame *fileFrame, const char *destFile, uint64_t fileSize, const SendListenerInfo *info)
253 {
254     if (info == NULL || fileFrame == NULL || destFile == NULL) {
255         TRANS_LOGE(TRANS_FILE, "invalid param.");
256         return SOFTBUS_INVALID_PARAM;
257     }
258     uint32_t len = strlen(destFile);
259     if (info->crc == APP_INFO_FILE_FEATURES_SUPPORT && info->osType == OH_TYPE) {
260         uint64_t dataLen = (uint64_t)len + FRAME_DATA_SEQ_OFFSET + sizeof(uint64_t);
261         fileFrame->frameLength = FRAME_HEAD_LEN + dataLen;
262         if (fileFrame->frameLength > info->packetSize) {
263             TRANS_LOGE(TRANS_FILE, "frameLength overSize");
264             return SOFTBUS_TRANS_INVALID_DATA_LENGTH;
265         }
266         // frameLength = magic(4 bytes) + dataLen(8 bytes) + oneFrameLen(4 bytes) + fileSize(8 bytes) + fileName
267         (*(uint32_t *)(fileFrame->data)) = SoftBusHtoLl(fileFrame->magic);
268         (*(uint64_t *)(fileFrame->data + FRAME_MAGIC_OFFSET)) = SoftBusHtoLll(dataLen);
269         (*(uint32_t *)(fileFrame->fileData)) =
270             SoftBusHtoLl(info->packetSize - FRAME_HEAD_LEN - FRAME_DATA_SEQ_OFFSET - FRAME_CRC_LEN);
271         (*(uint64_t *)(fileFrame->fileData + FRAME_DATA_SEQ_OFFSET)) = SoftBusHtoLll(fileSize);
272         if (memcpy_s(fileFrame->fileData + FRAME_DATA_SEQ_OFFSET + sizeof(uint64_t), len, destFile, len) != EOK) {
273             return SOFTBUS_MEM_ERR;
274         }
275     } else {
276         // frameLength = seq(4 bytes) + fileName
277         fileFrame->frameLength = FRAME_DATA_SEQ_OFFSET + len;
278         if (fileFrame->frameLength > info->packetSize) {
279             return SOFTBUS_TRANS_INVALID_DATA_LENGTH;
280         }
281         (*(int32_t *)(fileFrame->fileData)) = SoftBusHtoLl((uint32_t)info->channelId);
282         if (memcpy_s(fileFrame->fileData + FRAME_DATA_SEQ_OFFSET, len, destFile, len) != EOK) {
283             return SOFTBUS_MEM_ERR;
284         }
285     }
286     return SOFTBUS_OK;
287 }
288 
UnpackFileTransStartInfo(FileFrame * fileFrame,const FileRecipientInfo * info,SingleFileInfo * file,uint32_t packetSize)289 static int32_t UnpackFileTransStartInfo(
290     FileFrame *fileFrame, const FileRecipientInfo *info, SingleFileInfo *file, uint32_t packetSize)
291 {
292     TRANS_CHECK_AND_RETURN_RET_LOGE(
293         (info != NULL && fileFrame != NULL && file != NULL), SOFTBUS_INVALID_PARAM, TRANS_FILE, "invalid param");
294     uint8_t *fileNameData = NULL;
295     uint64_t fileNameLen = 0;
296     if (info->crc == APP_INFO_FILE_FEATURES_SUPPORT && info->osType == OH_TYPE) {
297         if (fileFrame->frameLength < FRAME_HEAD_LEN + FRAME_DATA_SEQ_OFFSET + sizeof(uint64_t)) {
298             TRANS_LOGE(TRANS_FILE, "frameLength invalid");
299             return SOFTBUS_INVALID_PARAM;
300         }
301         // frameLength = magic(4 bytes) + dataLen(8 bytes) + oneFrameLen(4 bytes) + fileSize(8 bytes) + fileName
302         fileFrame->magic = SoftBusLtoHl((*(uint32_t *)(fileFrame->data)));
303         uint64_t dataLen = SoftBusLtoHll((*(uint64_t *)(fileFrame->data + FRAME_MAGIC_OFFSET)));
304         if (dataLen > fileFrame->frameLength - FRAME_HEAD_LEN) {
305             return SOFTBUS_TRANS_INVALID_DATA_LENGTH;
306         }
307         if (fileFrame->magic != FILE_MAGIC_NUMBER || dataLen < (FRAME_DATA_SEQ_OFFSET + sizeof(uint64_t))) {
308             TRANS_LOGE(
309                 TRANS_FILE, "start info fail magic=%{public}X dataLen=%{public}" PRIu64, fileFrame->magic, dataLen);
310             return SOFTBUS_TRANS_INVALID_DATA_LENGTH;
311         }
312         fileFrame->fileData = fileFrame->data + FRAME_HEAD_LEN;
313         file->oneFrameLen = SoftBusLtoHl((*(uint32_t *)(fileFrame->fileData)));
314         if (file->oneFrameLen > packetSize) {
315             TRANS_LOGE(TRANS_FILE, "oneFrameLen invalid, oneFrameLen=%{public}" PRIu64, file->oneFrameLen);
316             return SOFTBUS_TRANS_INVALID_DATA_LENGTH;
317         }
318         file->fileSize = SoftBusLtoHll((*(uint64_t *)(fileFrame->fileData + FRAME_DATA_SEQ_OFFSET)));
319         if (file->fileSize > MAX_FILE_SIZE) {
320             TRANS_LOGE(TRANS_FILE, "fileSize is too large, please check, fileSize=%{public}" PRIu64, file->fileSize);
321             return SOFTBUS_TRANS_INVALID_DATA_LENGTH;
322         }
323         fileNameLen = dataLen - FRAME_DATA_SEQ_OFFSET - sizeof(uint64_t);
324         if (fileNameLen > 0) {
325             fileNameData = fileFrame->fileData + FRAME_DATA_SEQ_OFFSET + sizeof(uint64_t);
326         }
327         file->startSeq = file->preStartSeq = 1;
328         file->seqResult = file->preSeqResult = 0;
329     } else {
330         // frameLength = seq(4byte) + fileName
331         if (fileFrame->frameLength < FRAME_DATA_SEQ_OFFSET) {
332             return SOFTBUS_TRANS_INVALID_DATA_LENGTH;
333         }
334         fileFrame->fileData = fileFrame->data;
335         fileNameLen = fileFrame->frameLength - FRAME_DATA_SEQ_OFFSET;
336         file->seq = SoftBusLtoHl((*(uint32_t *)(fileFrame->fileData)));
337         if (fileNameLen > 0) {
338             fileNameData = fileFrame->fileData + FRAME_DATA_SEQ_OFFSET;
339         }
340     }
341     if (fileNameLen > MAX_FILE_PATH_NAME_LEN) {
342         TRANS_LOGE(TRANS_FILE, "start info fail fileNameLen=%{public}" PRIu64, fileNameLen);
343         return SOFTBUS_INVALID_PARAM;
344     }
345     if (fileNameData != NULL && memcpy_s(file->filePath, MAX_FILE_PATH_NAME_LEN, fileNameData, fileNameLen) != EOK) {
346         return SOFTBUS_MEM_ERR;
347     }
348     return SOFTBUS_OK;
349 }
350 
GetAndCheckFileSize(const char * sourceFile,uint64_t * fileSize,uint64_t * frameNum,int32_t crc,uint32_t packetSize)351 static int32_t GetAndCheckFileSize(
352     const char *sourceFile, uint64_t *fileSize, uint64_t *frameNum, int32_t crc, uint32_t packetSize)
353 {
354     if ((sourceFile == NULL) || (fileSize == NULL) || (frameNum == NULL)) {
355         TRANS_LOGE(TRANS_FILE, "get file size num params invalid");
356         return SOFTBUS_INVALID_PARAM;
357     }
358 
359     if (SoftBusGetFileSize(sourceFile, fileSize) != SOFTBUS_OK) {
360         TRANS_LOGE(TRANS_FILE, "get file size fail");
361         return SOFTBUS_FILE_ERR;
362     }
363 
364     if (*fileSize > MAX_FILE_SIZE) {
365         TRANS_LOGE(TRANS_FILE, "file is too large, fileSize=%{public}" PRIu64, *fileSize);
366         return SOFTBUS_FILE_ERR;
367     }
368 
369     uint64_t oneFrameSize = packetSize - FRAME_DATA_SEQ_OFFSET;
370     if (crc == APP_INFO_FILE_FEATURES_SUPPORT) {
371         oneFrameSize -= (FRAME_HEAD_LEN + FRAME_CRC_LEN);
372     }
373     uint64_t frameNumTemp;
374     if (oneFrameSize != 0) {
375         frameNumTemp = (*fileSize) / oneFrameSize;
376         if (((*fileSize) % oneFrameSize) != 0) {
377             frameNumTemp++;
378         }
379     } else {
380         TRANS_LOGE(TRANS_FILE, "there's division by zero risk");
381         return SOFTBUS_FILE_ERR;
382     }
383 
384     /* add 1 means reserve frame to send destFile string */
385     frameNumTemp++;
386     *frameNum = frameNumTemp;
387     return SOFTBUS_OK;
388 }
389 
SendOneFrameFront(SendListenerInfo * info,int32_t frameType)390 static int32_t SendOneFrameFront(SendListenerInfo *info, int32_t frameType)
391 {
392     if (info == NULL) {
393         TRANS_LOGW(TRANS_FILE, "invalid param.");
394         return SOFTBUS_INVALID_PARAM;
395     }
396     if (info->crc != APP_INFO_FILE_FEATURES_SUPPORT) {
397         return SOFTBUS_OK;
398     }
399     if (frameType == TRANS_SESSION_FILE_FIRST_FRAME) {
400         int32_t ret = CreatePendingPacket(info->sessionId, 0);
401         TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_FILE, "creat pending oacket fail!");
402         info->waitSeq = 0;
403         info->waitTimeoutCount = 0;
404     }
405     return SOFTBUS_OK;
406 }
407 
SendOneFrameMiddle(SendListenerInfo * info,int32_t frameType)408 static int32_t SendOneFrameMiddle(SendListenerInfo *info, int32_t frameType)
409 {
410     if (info == NULL) {
411         TRANS_LOGW(TRANS_FILE, "invalid param.");
412         return SOFTBUS_INVALID_PARAM;
413     }
414     if (info->crc != APP_INFO_FILE_FEATURES_SUPPORT) {
415         return SOFTBUS_OK;
416     }
417     if (frameType == TRANS_SESSION_FILE_ONGOINE_FRAME) {
418         if ((uint32_t)info->seq % FILE_SEND_ACK_INTERVAL != 0) {
419             return SOFTBUS_OK;
420         }
421         int32_t ret = CreatePendingPacket((uint32_t)info->sessionId, (uint64_t)info->seq);
422         TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_FILE, "creat pending oacket fail!");
423         info->waitSeq = (int32_t)(info->seq);
424         info->waitTimeoutCount = 0;
425         ret = SendFileAckReqAndResData(info->channelId, info->seq - FILE_SEND_ACK_INTERVAL + 1, info->seq,
426             TRANS_SESSION_FILE_ACK_REQUEST_SENT);
427         if (ret != SOFTBUS_OK) {
428             DeletePendingPacket((uint32_t)info->sessionId, (uint64_t)info->seq);
429             info->waitSeq = 0;
430             return ret;
431         }
432         TRANS_LOGI(
433             TRANS_FILE, "send ack request. channelId=%{public}d, waitSeq=%{public}d", info->channelId, info->waitSeq);
434     }
435     return SOFTBUS_OK;
436 }
437 
SendOneFrameRear(SendListenerInfo * info,int32_t frameType)438 static int32_t SendOneFrameRear(SendListenerInfo *info, int32_t frameType)
439 {
440     if (info == NULL) {
441         return SOFTBUS_INVALID_PARAM;
442     }
443     if (info->crc != APP_INFO_FILE_FEATURES_SUPPORT || frameType == TRANS_SESSION_FILE_ONLYONE_FRAME) {
444         return SOFTBUS_OK;
445     }
446     int32_t ret;
447     TransPendData pendData = { 0 };
448     if (frameType == TRANS_SESSION_FILE_FIRST_FRAME) {
449         ret = GetPendingPacketData(info->sessionId, 0, WAIT_START_ACK_TIME, true, &pendData);
450         if (ret == SOFTBUS_ALREADY_TRIGGERED || ret == SOFTBUS_OK) {
451             SoftBusFree(pendData.data);
452             return SOFTBUS_OK;
453         }
454         TRANS_LOGE(
455             TRANS_FILE, "recv start frame respone timeout. channelId=%{public}d, ret=%{public}d", info->channelId, ret);
456     } else {
457         if ((uint32_t)info->waitSeq == 0) {
458             return SOFTBUS_OK;
459         }
460         uint32_t time = WAIT_ACK_TIME;
461         if (frameType == TRANS_SESSION_FILE_LAST_FRAME || info->waitTimeoutCount >= WAIT_FRAME_ACK_TIMEOUT_COUNT) {
462             time = WAIT_ACK_LAST_TIME;
463         }
464         ret = GetPendingPacketData(info->sessionId, (uint64_t)info->waitSeq, time, false, &pendData);
465         if (ret == SOFTBUS_ALREADY_TRIGGERED || ret == SOFTBUS_OK) {
466             ret = AckResponseDataHandle(info, pendData.data, pendData.len);
467             info->waitSeq = 0;
468             info->waitTimeoutCount = 0;
469             SoftBusFree(pendData.data);
470             return ret;
471         } else if (ret == SOFTBUS_TIMOUT) {
472             info->waitTimeoutCount++;
473             if (frameType != TRANS_SESSION_FILE_LAST_FRAME && info->waitTimeoutCount <= WAIT_FRAME_ACK_TIMEOUT_COUNT) {
474                 return SOFTBUS_OK;
475             }
476             DeletePendingPacket(info->sessionId, (uint64_t)info->waitSeq);
477         }
478         TRANS_LOGE(TRANS_FILE, "recv ack respone timeout. channelId=%{public}d, waitSeq=%{public}d, ret=%{public}d",
479             info->channelId, info->waitSeq, ret);
480         info->waitSeq = 0;
481         info->waitTimeoutCount = 0;
482     }
483     return SOFTBUS_FILE_ERR;
484 }
485 
SendOneFrame(const SendListenerInfo * sendInfo,const FileFrame * fileFrame)486 static int32_t SendOneFrame(const SendListenerInfo *sendInfo, const FileFrame *fileFrame)
487 {
488     if ((sendInfo == NULL) || (fileFrame == NULL)) {
489         TRANS_LOGW(TRANS_FILE, "invalid param.");
490         return SOFTBUS_INVALID_PARAM;
491     }
492     int ret;
493     if (sendInfo->osType == OH_TYPE) {
494         ret = SendOneFrameFront((SendListenerInfo *)sendInfo, fileFrame->frameType);
495         TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_FILE, "send one frame front fail!");
496     }
497     ret = ProxyChannelSendFileStream(
498         sendInfo->channelId, (char *)fileFrame->data, fileFrame->frameLength, fileFrame->frameType);
499     if (ret != SOFTBUS_OK) {
500         TRANS_LOGE(TRANS_FILE, "conn send buf fail ret=%{public}d", ret);
501         return ret;
502     }
503     if (sendInfo->osType == OH_TYPE) {
504         ret = SendOneFrameMiddle((SendListenerInfo *)sendInfo, fileFrame->frameType);
505         TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_FILE, "send one frame middle fail!");
506         ret = SendOneFrameRear((SendListenerInfo *)sendInfo, fileFrame->frameType);
507         TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_FILE, "send one frame rear fail!");
508         ret = sendInfo->result;
509         if (ret != SOFTBUS_OK) {
510             TRANS_LOGE(TRANS_FILE, "peer receiving data error. channalId=%{public}d, errcode=%{public}d",
511                 sendInfo->channelId, sendInfo->result);
512             return ret;
513         }
514     }
515     return SOFTBUS_OK;
516 }
517 
SendFileCrcCheckSum(const SendListenerInfo * info)518 static int32_t SendFileCrcCheckSum(const SendListenerInfo *info)
519 {
520     if (info == NULL) {
521         TRANS_LOGW(TRANS_FILE, "invalid param.");
522         return SOFTBUS_INVALID_PARAM;
523     }
524     if (info->crc != APP_INFO_FILE_FEATURES_SUPPORT) {
525         return SOFTBUS_OK;
526     }
527     uint32_t len = FRAME_HEAD_LEN + FRAME_DATA_SEQ_OFFSET + sizeof(info->checkSumCRC);
528     char *data = (char *)SoftBusCalloc(len);
529     if (data == NULL) {
530         return SOFTBUS_MALLOC_ERR;
531     }
532     uint32_t seq = info->seq + 1; // magic(4 byte) + dataLen(8 byte) + seq(4 byte) + crc(8 byte)
533     (*(uint32_t *)data) = SoftBusHtoLl(FILE_MAGIC_NUMBER);
534     (*(uint64_t *)(data + FRAME_MAGIC_OFFSET)) = SoftBusHtoLll((FRAME_DATA_SEQ_OFFSET + sizeof(info->checkSumCRC)));
535     (*(uint32_t *)(data + FRAME_HEAD_LEN)) = SoftBusHtoLl(seq);
536     (*(uint64_t *)(data + FRAME_HEAD_LEN + FRAME_DATA_SEQ_OFFSET)) = SoftBusHtoLll(info->checkSumCRC);
537     int32_t ret = CreatePendingPacket((uint32_t)info->sessionId, seq);
538     if (ret != SOFTBUS_OK) {
539         TRANS_LOGE(TRANS_FILE, "Create Pend fail. channelId=%{public}d, seq=%{public}d", info->channelId, seq);
540         SoftBusFree(data);
541         return ret;
542     }
543     TRANS_LOGI(TRANS_FILE, "send check sum. channelId=%{public}d, seq=%{public}d", info->channelId, seq);
544     ret = ProxyChannelSendFileStream(info->channelId, data, len, TRANS_SESSION_FILE_CRC_CHECK_FRAME);
545     if (ret != SOFTBUS_OK) {
546         TRANS_LOGE(TRANS_FILE, "conn send crc buf fail ret=%{public}d", ret);
547         DeletePendingPacket((uint32_t)info->sessionId, seq);
548         SoftBusFree(data);
549         return ret;
550     }
551     SoftBusFree(data);
552     TransPendData pendData = { 0 };
553     ret = GetPendingPacketData(info->sessionId, seq, WAIT_START_ACK_TIME, true, &pendData);
554     if (ret == SOFTBUS_ALREADY_TRIGGERED || ret == SOFTBUS_OK) {
555         SoftBusFree(pendData.data);
556         return SOFTBUS_OK;
557     }
558     TRANS_LOGE(TRANS_FILE, "recv check sum result timeout. channelId=%{public}d, seq=%{public}d, ret=%{public}d",
559         info->channelId, seq, ret);
560     return ret;
561 }
562 
UnpackFileCrcCheckSum(const FileRecipientInfo * info,FileFrame * fileFrame)563 static int32_t UnpackFileCrcCheckSum(const FileRecipientInfo *info, FileFrame *fileFrame)
564 {
565     if ((info == NULL) || (fileFrame == NULL)) {
566         TRANS_LOGW(TRANS_FILE, "invalid param.");
567         return SOFTBUS_INVALID_PARAM;
568     }
569     if (info->crc == APP_INFO_FILE_FEATURES_SUPPORT) {
570         SingleFileInfo *file = (SingleFileInfo *)(&info->recvFileInfo);
571         if (fileFrame->frameLength != FRAME_HEAD_LEN + FRAME_DATA_SEQ_OFFSET + sizeof(file->checkSumCRC)) {
572             return SOFTBUS_TRANS_INVALID_DATA_LENGTH;
573         }
574         fileFrame->magic = SoftBusLtoHl((*(uint32_t *)(fileFrame->data)));
575         uint64_t dataLen = SoftBusLtoHll((*(uint64_t *)(fileFrame->data + FRAME_MAGIC_OFFSET)));
576         if ((fileFrame->magic != FILE_MAGIC_NUMBER) || (dataLen != FRAME_DATA_SEQ_OFFSET + sizeof(file->checkSumCRC))) {
577             TRANS_LOGE(TRANS_FILE, "unpack crc check frame failed. magic=%{public}u, dataLen=%{public}" PRIu64,
578                 fileFrame->magic, dataLen);
579             return SOFTBUS_INVALID_DATA_HEAD;
580         }
581         fileFrame->fileData = fileFrame->data + FRAME_HEAD_LEN;
582         fileFrame->seq = SoftBusLtoHl((*(uint32_t *)(fileFrame->fileData)));
583         uint64_t recvCheckSumCRC = SoftBusLtoHll((*(uint64_t *)(fileFrame->fileData + FRAME_DATA_SEQ_OFFSET)));
584         if (recvCheckSumCRC != file->checkSumCRC) {
585             TRANS_LOGE(TRANS_FILE, "crc check sum fail recvCrc=%{public}" PRIu64 ", crc=%{public}" PRIu64,
586                 recvCheckSumCRC, file->checkSumCRC);
587             return SOFTBUS_FILE_ERR;
588         }
589     }
590     return SOFTBUS_OK;
591 }
592 
HandleSendProgress(SendListenerInfo * sendInfo,uint64_t fileOffset,uint64_t fileSize)593 static void HandleSendProgress(SendListenerInfo *sendInfo, uint64_t fileOffset, uint64_t fileSize)
594 {
595     TRANS_CHECK_AND_RETURN_LOGE(sendInfo != NULL, TRANS_FILE, "sendInfo is empty.");
596 
597     if (sendInfo->fileListener.socketSendCallback != NULL) {
598         FileEvent event = {
599             .type = FILE_EVENT_SEND_PROCESS,
600             .files = sendInfo->totalInfo.files,
601             .fileCnt = sendInfo->totalInfo.fileCnt,
602             .bytesProcessed = sendInfo->totalInfo.bytesProcessed,
603             .bytesTotal = sendInfo->totalInfo.bytesTotal,
604             .UpdateRecvPath = NULL,
605         };
606         sendInfo->fileListener.socketSendCallback(sendInfo->sessionId, &event);
607     } else if (sendInfo->fileListener.sendListener.OnSendFileProcess != NULL) {
608         sendInfo->fileListener.sendListener.OnSendFileProcess(sendInfo->channelId, fileOffset, fileSize);
609     }
610 }
611 
FileToFrame(SendListenerInfo * sendInfo,uint64_t frameNum,const char * destFile,uint64_t fileSize)612 static int32_t FileToFrame(SendListenerInfo *sendInfo, uint64_t frameNum, const char *destFile, uint64_t fileSize)
613 {
614     FileFrame fileFrame = { 0 };
615     fileFrame.data = (uint8_t *)SoftBusCalloc(sendInfo->packetSize);
616     TRANS_CHECK_AND_RETURN_RET_LOGE(fileFrame.data != NULL, SOFTBUS_MALLOC_ERR, TRANS_FILE, "data calloc failed");
617     fileFrame.magic = FILE_MAGIC_NUMBER;
618     fileFrame.fileData = fileFrame.data;
619     uint64_t fileOffset = 0;
620     uint64_t remainedSendSize = fileSize;
621     uint64_t frameDataSize = sendInfo->packetSize - FRAME_DATA_SEQ_OFFSET;
622     if (sendInfo->crc == APP_INFO_FILE_FEATURES_SUPPORT) {
623         fileFrame.fileData = fileFrame.data + FRAME_HEAD_LEN;
624         frameDataSize -= (FRAME_HEAD_LEN + FRAME_CRC_LEN);
625     }
626     for (uint64_t index = 0; index < frameNum; index++) {
627         fileFrame.frameType = FrameIndexToType(index, frameNum);
628         if (index == 0) {
629             if (PackFileTransStartInfo(&fileFrame, destFile, fileSize, sendInfo) != SOFTBUS_OK) {
630                 goto EXIT_ERR;
631             }
632         } else {
633             uint64_t readLength = (remainedSendSize < frameDataSize) ? remainedSendSize : frameDataSize;
634             int64_t len = PackReadFileData(&fileFrame, readLength, fileOffset, sendInfo);
635             if (len <= 0) {
636                 TRANS_LOGE(TRANS_FILE, "read file src file failed");
637                 goto EXIT_ERR;
638             }
639             fileOffset += (uint64_t)len;
640             remainedSendSize -= (uint64_t)len;
641             sendInfo->totalInfo.bytesProcessed += (uint64_t)len;
642         }
643         if (SendOneFrame(sendInfo, &fileFrame) != SOFTBUS_OK) {
644             TRANS_LOGE(TRANS_FILE, "send one frame failed");
645             goto EXIT_ERR;
646         }
647         HandleSendProgress(sendInfo, fileOffset, fileSize);
648         (void)memset_s(fileFrame.data, sendInfo->packetSize, 0, sendInfo->packetSize);
649     }
650     if (sendInfo->osType == OH_TYPE) {
651         TRANS_LOGI(TRANS_FILE, "send crc check sum");
652         if (SendFileCrcCheckSum(sendInfo) != SOFTBUS_OK) {
653             goto EXIT_ERR;
654         }
655     }
656     SoftBusFree(fileFrame.data);
657     return SOFTBUS_OK;
658 EXIT_ERR:
659     SoftBusFree(fileFrame.data);
660     return SOFTBUS_FILE_ERR;
661 }
662 
FileToFrameAndSendFile(SendListenerInfo * sendInfo,const char * sourceFile,const char * destFile)663 static int32_t FileToFrameAndSendFile(SendListenerInfo *sendInfo, const char *sourceFile, const char *destFile)
664 {
665 #define RETRY_READ_LOCK_TIMES 2
666     TRANS_CHECK_AND_RETURN_RET_LOGE(sendInfo != NULL, SOFTBUS_INVALID_PARAM, TRANS_FILE, "invalid param.");
667     if (!CheckDestFilePathValid(destFile)) {
668         TRANS_LOGE(TRANS_FILE, "dest path is wrong. channelId=%{public}d", sendInfo->channelId);
669         return SOFTBUS_FILE_ERR;
670     }
671     char *absSrcPath = (char *)SoftBusCalloc(PATH_MAX + 1);
672     TRANS_CHECK_AND_RETURN_RET_LOGE(absSrcPath != NULL, SOFTBUS_MALLOC_ERR, TRANS_FILE, "calloc absFullDir failed");
673     if (GetAndCheckRealPath(sourceFile, absSrcPath) != SOFTBUS_OK) {
674         TRANS_LOGE(TRANS_FILE, "get src abs file fail. channelId=%{public}d", sendInfo->channelId);
675         SoftBusFree(absSrcPath);
676         return SOFTBUS_FILE_ERR;
677     }
678     uint64_t fileSize = 0;
679     uint64_t frameNum = 0;
680     if (GetAndCheckFileSize(absSrcPath, &fileSize, &frameNum, sendInfo->crc, sendInfo->packetSize) != SOFTBUS_OK) {
681         TRANS_LOGE(TRANS_FILE,
682             "absSrcPath size err. channelId=%{public}d, absSrcPath=%{private}s", sendInfo->channelId, absSrcPath);
683         SoftBusFree(absSrcPath);
684         return SOFTBUS_FILE_ERR;
685     }
686     TRANS_LOGI(TRANS_FILE,
687         "channelId=%{public}d, srcPath=%{private}s, srcAbsPath=%{private}s, destPath=%{private}s, "
688         "fileSize=%{public}" PRIu64 ", frameNum=%{public}" PRIu64,
689         sendInfo->channelId, sourceFile, absSrcPath, destFile, fileSize, frameNum);
690     int32_t fd = SoftBusOpenFile(absSrcPath, SOFTBUS_O_RDONLY);
691     if (fd < 0) {
692         TRANS_LOGE(TRANS_FILE, "open file fail. channelId=%{public}d", sendInfo->channelId);
693         SoftBusFree(absSrcPath);
694         return SOFTBUS_FILE_ERR;
695     }
696     if (TryFileLock(fd, SOFTBUS_F_RDLCK, RETRY_READ_LOCK_TIMES) != SOFTBUS_OK) {
697         TRANS_LOGE(TRANS_FILE, "file is writing");
698         SoftBusCloseFile(fd);
699         SoftBusFree(absSrcPath);
700         return SOFTBUS_FILE_ERR;
701     }
702     sendInfo->fd = fd;
703     sendInfo->fileSize = fileSize;
704     sendInfo->frameNum = frameNum;
705     int32_t ret = FileToFrame(sendInfo, frameNum, destFile, fileSize);
706     SoftBusFree(absSrcPath);
707     TRANS_LOGI(TRANS_FILE, "send file end. channelId=%{public}d, ret=%{public}d", sendInfo->channelId, ret);
708     return ret;
709 }
710 
ClearSendInfo(SendListenerInfo * info)711 static void ClearSendInfo(SendListenerInfo *info)
712 {
713     if (info->fd != INVALID_FD) {
714         (void)FileUnLock(info->fd);
715         SoftBusCloseFile(info->fd);
716         info->fd = INVALID_FD;
717     }
718     info->fileSize = 0;
719     info->frameNum = 0;
720     info->seq = 0;
721     info->waitSeq = 0;
722     info->waitTimeoutCount = 0;
723     info->result = SOFTBUS_OK;
724     info->checkSumCRC = 0;
725 }
726 
SendSingleFile(const SendListenerInfo * sendInfo,const char * sourceFile,const char * destFile)727 static int32_t SendSingleFile(const SendListenerInfo *sendInfo, const char *sourceFile, const char *destFile)
728 {
729     if ((sourceFile == NULL) || (destFile == NULL)) {
730         TRANS_LOGE(TRANS_FILE, "sourfile or dstfile is null");
731         return SOFTBUS_INVALID_PARAM;
732     }
733     TRANS_LOGI(TRANS_FILE, "channelId=%{public}d, srcFile=%{private}s, dstFile=%{private}s", sendInfo->channelId,
734         sourceFile, destFile);
735 
736     int32_t ret = FileToFrameAndSendFile((SendListenerInfo *)sendInfo, sourceFile, destFile);
737     ClearSendInfo((SendListenerInfo *)sendInfo);
738     TRANS_LOGI(
739         TRANS_FILE, "channelId=%{public}d, srcFile=%{private}s, ret=%{public}d", sendInfo->channelId, sourceFile, ret);
740     return ret;
741 }
742 
SendFileList(int32_t channelId,const char ** destFile,uint32_t fileCnt)743 static int32_t SendFileList(int32_t channelId, const char **destFile, uint32_t fileCnt)
744 {
745     TRANS_LOGI(TRANS_FILE, "send file list begin");
746     FileListBuffer bufferInfo = { 0 };
747     int32_t ret = FileListToBuffer(destFile, fileCnt, &bufferInfo);
748     if (ret != SOFTBUS_OK) {
749         TRANS_LOGE(TRANS_FILE, "file list to buffer fail");
750         return ret;
751     }
752 
753     ret = ProxyChannelSendFileStream(
754         channelId, (char *)bufferInfo.buffer, bufferInfo.bufferSize, TRANS_SESSION_FILE_ALLFILE_SENT);
755     SoftBusFree(bufferInfo.buffer);
756     TRANS_LOGI(TRANS_FILE, "send file list ret=%{public}d", ret);
757     return ret;
758 }
759 
IsValidFileString(const char * str[],uint32_t fileNum,uint32_t maxLen)760 static bool IsValidFileString(const char *str[], uint32_t fileNum, uint32_t maxLen)
761 {
762     if (str == NULL || fileNum == 0) {
763         TRANS_LOGE(TRANS_FILE, "param invalid");
764         return false;
765     }
766     for (uint32_t i = 0; i < fileNum; i++) {
767         if (str[i] == NULL) {
768             TRANS_LOGE(TRANS_FILE, "file string invalid");
769             return false;
770         }
771         uint32_t len = strlen(str[i]);
772         if (len == 0 || len >= maxLen) {
773             TRANS_LOGE(TRANS_FILE, "len invalid");
774             return false;
775         }
776     }
777     return true;
778 }
779 
GetFileSize(const char * filePath,uint64_t * fileSize)780 static int32_t GetFileSize(const char *filePath, uint64_t *fileSize)
781 {
782     char *absPath = (char *)SoftBusCalloc(PATH_MAX + 1);
783     if (absPath == NULL) {
784         TRANS_LOGE(TRANS_SDK, "calloc absFullDir fail");
785         return SOFTBUS_FILE_ERR;
786     }
787 
788     if (GetAndCheckRealPath(filePath, absPath) != SOFTBUS_OK) {
789         TRANS_LOGE(TRANS_SDK, "get src abs file fail");
790         SoftBusFree(absPath);
791         return SOFTBUS_FILE_ERR;
792     }
793 
794     if (SoftBusGetFileSize(absPath, fileSize) != SOFTBUS_OK) {
795         TRANS_LOGE(TRANS_SDK, "get file size fail");
796         SoftBusFree(absPath);
797         return SOFTBUS_FILE_ERR;
798     }
799 
800     SoftBusFree(absPath);
801     return SOFTBUS_OK;
802 }
803 
CalcAllFilesInfo(FilesInfo * totalInfo,const char * fileList[],uint32_t fileCnt)804 static int32_t CalcAllFilesInfo(FilesInfo *totalInfo, const char *fileList[], uint32_t fileCnt)
805 {
806     totalInfo->files = fileList;
807     totalInfo->fileCnt = fileCnt;
808     totalInfo->bytesProcessed = 0;
809 
810     uint64_t curFileSize = 0;
811     for (uint32_t i = 0; i < fileCnt; i++) {
812         if (GetFileSize(fileList[i], &curFileSize) != SOFTBUS_OK) {
813             TRANS_LOGE(TRANS_SDK, "get file size failed, path=%{private}s", fileList[i]);
814             return SOFTBUS_FILE_ERR;
815         }
816         totalInfo->bytesTotal += curFileSize;
817     }
818     return SOFTBUS_OK;
819 }
820 
ProxyStartSendFile(const SendListenerInfo * sendInfo,const char * sFileList[],const char * dFileList[],uint32_t fileCnt)821 static int32_t ProxyStartSendFile(
822     const SendListenerInfo *sendInfo, const char *sFileList[], const char *dFileList[], uint32_t fileCnt)
823 {
824     int32_t ret;
825     if (CalcAllFilesInfo((FilesInfo *)&sendInfo->totalInfo, sFileList, fileCnt)) {
826         TRANS_LOGE(TRANS_SDK, "calculate all files information failed");
827         return SOFTBUS_FILE_ERR;
828     }
829 
830     for (uint32_t index = 0; index < fileCnt; index++) {
831         ret = SendSingleFile(sendInfo, sFileList[index], dFileList[index]);
832         if (ret != SOFTBUS_OK) {
833             TRANS_LOGE(
834                 TRANS_FILE, "send file failed. sendFile=%{private}s, ret=%{public}" PRId32, sFileList[index], ret);
835             return SOFTBUS_FILE_ERR;
836         }
837     }
838     ret = SendFileList(sendInfo->channelId, dFileList, fileCnt);
839     if (ret != SOFTBUS_OK) {
840         TRANS_LOGE(TRANS_FILE, "SendFileList failed");
841         return SOFTBUS_FILE_ERR;
842     }
843     if (sendInfo->result != SOFTBUS_OK) {
844         TRANS_LOGE(TRANS_FILE, "send file recv side fail channelId=%{public}d, errCode=%{public}d",
845             sendInfo->channelId, sendInfo->result);
846         return SOFTBUS_FILE_ERR;
847     }
848     if (sendInfo->fileListener.socketSendCallback != NULL) {
849         FileEvent event = {
850             .type = FILE_EVENT_SEND_FINISH,
851             .files = sendInfo->totalInfo.files,
852             .fileCnt = sendInfo->totalInfo.fileCnt,
853             .bytesProcessed = sendInfo->totalInfo.bytesProcessed,
854             .bytesTotal = sendInfo->totalInfo.bytesTotal,
855             .UpdateRecvPath = NULL,
856         };
857         sendInfo->fileListener.socketSendCallback(sendInfo->sessionId, &event);
858     } else if (sendInfo->fileListener.sendListener.OnSendFileFinished != NULL) {
859         sendInfo->fileListener.sendListener.OnSendFileFinished(sendInfo->sessionId, dFileList[0]);
860     }
861     return SOFTBUS_OK;
862 }
863 
GetSendListenerInfoByChannelId(int32_t channelId,SendListenerInfo * info,int32_t osType)864 static int32_t GetSendListenerInfoByChannelId(int32_t channelId, SendListenerInfo *info, int32_t osType)
865 {
866     int32_t sessionId;
867     if (info == NULL) {
868         TRANS_LOGW(TRANS_FILE, "invalid param.");
869         return SOFTBUS_INVALID_PARAM;
870     }
871     int32_t ret = ClientGetSessionIdByChannelId(channelId, CHANNEL_TYPE_PROXY, &sessionId);
872     if (ret != SOFTBUS_OK) {
873         TRANS_LOGE(TRANS_FILE, "get sessionId failed, channelId=%{public}d", channelId);
874         return ret;
875     }
876     char sessionName[SESSION_NAME_SIZE_MAX] = { 0 };
877     ret = ClientGetSessionDataById(sessionId, sessionName, SESSION_NAME_SIZE_MAX, KEY_SESSION_NAME);
878     TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_FILE, "get sessionId name failed");
879 
880     ret = ClientGetFileConfigInfoById(sessionId, &info->fileEncrypt, &info->algorithm, &info->crc);
881     TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_FILE, "get file config failed");
882 
883     ret = TransGetFileListener(sessionName, &(info->fileListener));
884     TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_FILE, "get file listener failed");
885 
886     int32_t linkType;
887     ret = ClientTransProxyGetLinkTypeByChannelId(channelId, &linkType);
888     if (ret != SOFTBUS_OK) {
889         TRANS_LOGE(TRANS_FILE, "client trans proxy get info by ChannelId fail");
890         return ret;
891     }
892     if (linkType == LANE_BR) {
893         info->packetSize = PROXY_BR_MAX_PACKET_SIZE;
894     } else {
895         info->packetSize = PROXY_BLE_MAX_PACKET_SIZE;
896     }
897     info->channelId = channelId;
898     info->sessionId = sessionId;
899     info->osType = osType;
900     ListInit(&info->node);
901     return SOFTBUS_OK;
902 }
903 
CreateSendListenerInfo(SendListenerInfo ** sendListenerInfo,int32_t channelId,int32_t osType)904 static int32_t CreateSendListenerInfo(SendListenerInfo **sendListenerInfo, int32_t channelId, int32_t osType)
905 {
906     SendListenerInfo *sendInfo = (SendListenerInfo *)SoftBusCalloc(sizeof(SendListenerInfo));
907     if (sendInfo == NULL) {
908         return SOFTBUS_MALLOC_ERR;
909     }
910     int32_t ret = SOFTBUS_FILE_ERR;
911     do {
912         ret = GetSendListenerInfoByChannelId(channelId, sendInfo, osType);
913         if (ret != SOFTBUS_OK) {
914             break;
915         }
916 
917         ret = AddSendListenerInfo(sendInfo);
918         if (ret != SOFTBUS_OK) {
919             break;
920         }
921     } while (false);
922 
923     if (ret != SOFTBUS_OK) {
924         SoftBusFree(sendInfo);
925         sendInfo = NULL;
926     }
927 
928     *sendListenerInfo = sendInfo;
929     return ret;
930 }
931 
ReleaseSendListenerInfo(SendListenerInfo * sendInfo)932 static void ReleaseSendListenerInfo(SendListenerInfo *sendInfo)
933 {
934     if (sendInfo == NULL) {
935         return;
936     }
937     DelSendListenerInfo(sendInfo);
938 }
939 
HandleFileSendingProcess(int32_t channelId,const char * sFileList[],const char * dFileList[],uint32_t fileCnt)940 static int32_t HandleFileSendingProcess(
941     int32_t channelId, const char *sFileList[], const char *dFileList[], uint32_t fileCnt)
942 {
943     SendListenerInfo *sendInfo = NULL;
944     int32_t ret = SOFTBUS_FILE_ERR;
945     do {
946         int32_t osType;
947         (void)ClientTransProxyGetOsTypeByChannelId(channelId, &osType);
948         ret = CreateSendListenerInfo(&sendInfo, channelId, osType);
949         if (ret != SOFTBUS_OK || sendInfo == NULL) {
950             TRANS_LOGE(TRANS_FILE, "create send listener info failed! ret=%{public}" PRId32, ret);
951             break;
952         }
953         ret = ProxyStartSendFile(sendInfo, sFileList, dFileList, fileCnt);
954         if (ret != SOFTBUS_OK) {
955             TRANS_LOGE(TRANS_FILE, "proxy send file failed ret=%{public}" PRId32, ret);
956             DeletePendingPacket(sendInfo->sessionId, sendInfo->waitSeq);
957             ret = SOFTBUS_TRANS_PROXY_SENDMSG_ERR;
958             break;
959         }
960         TRANS_LOGI(TRANS_FILE, "proxy send file trans ok");
961     } while (false);
962 
963     if (ret != SOFTBUS_OK) {
964         TRANS_LOGE(TRANS_FILE, "proxy send file trans error");
965         if (sendInfo != NULL && sendInfo->fileListener.socketSendCallback != NULL) {
966             FileEvent event = {
967                 .type = FILE_EVENT_SEND_ERROR,
968                 .files = sendInfo->totalInfo.files,
969                 .fileCnt = sendInfo->totalInfo.fileCnt,
970                 .bytesProcessed = 0,
971                 .bytesTotal = 0,
972             };
973             sendInfo->fileListener.socketSendCallback(sendInfo->sessionId, &event);
974         } else if (sendInfo != NULL && sendInfo->fileListener.sendListener.OnFileTransError != NULL) {
975             sendInfo->fileListener.sendListener.OnFileTransError(sendInfo->sessionId);
976         }
977     }
978 
979     if (sendInfo != NULL) {
980         ReleaseSendListenerInfo(sendInfo);
981         sendInfo = NULL;
982     }
983 
984     return ret;
985 }
986 
ProxyChannelSendFile(int32_t channelId,const char * sFileList[],const char * dFileList[],uint32_t fileCnt)987 int32_t ProxyChannelSendFile(int32_t channelId, const char *sFileList[], const char *dFileList[], uint32_t fileCnt)
988 {
989     TRANS_LOGI(TRANS_FILE, "proxy send file trans start");
990     if (fileCnt == 0 || fileCnt > MAX_SEND_FILE_NUM) {
991         TRANS_LOGE(TRANS_FILE, "sendfile arg filecnt=%{public}u error", fileCnt);
992         return SOFTBUS_INVALID_PARAM;
993     }
994     if (sFileList == NULL || !IsValidFileString(sFileList, fileCnt, MAX_FILE_PATH_NAME_LEN)) {
995         TRANS_LOGE(TRANS_FILE, "sendfile invalid arg sFileList");
996         return SOFTBUS_INVALID_PARAM;
997     }
998     if (dFileList == NULL || !IsValidFileString(dFileList, fileCnt, MAX_FILE_PATH_NAME_LEN)) {
999         TRANS_LOGE(TRANS_FILE, "sendfile invalid arg dFileList");
1000         return SOFTBUS_INVALID_PARAM;
1001     }
1002 
1003     ProxyFileMutexLock *sessionLock = GetSessionFileLock(channelId);
1004     TRANS_CHECK_AND_RETURN_RET_LOGE(sessionLock != NULL, SOFTBUS_LOCK_ERR, TRANS_FILE, "get file lock failed");
1005     if (SoftBusMutexLock(&sessionLock->sendLock) != SOFTBUS_OK) {
1006         TRANS_LOGE(TRANS_FILE, "proxy send file lock file mutex failed");
1007         DelSessionFileLock(sessionLock);
1008         return SOFTBUS_LOCK_ERR;
1009     }
1010 
1011     int32_t ret = HandleFileSendingProcess(channelId, sFileList, dFileList, fileCnt);
1012     if (ret != SOFTBUS_OK) {
1013         TRANS_LOGE(TRANS_FILE, "file senging process failed, ret=%{public}d", ret);
1014     }
1015     (void)SoftBusMutexUnlock(&sessionLock->sendLock);
1016     DelSessionFileLock(sessionLock);
1017     return ret;
1018 }
1019 
CheckRecvFileExist(const char * absFullPath)1020 static bool CheckRecvFileExist(const char *absFullPath)
1021 {
1022     if (absFullPath == NULL) {
1023         TRANS_LOGE(TRANS_FILE, "absFullPath is null");
1024         return false;
1025     }
1026     if (SoftBusMutexLock(&g_recvFileInfoLock.lock) != SOFTBUS_OK) {
1027         TRANS_LOGE(TRANS_FILE, "lock file timer failed");
1028         return false;
1029     }
1030     FileRecipientInfo *info = NULL;
1031     LIST_FOR_EACH_ENTRY(info, &g_recvRecipientInfoList, FileRecipientInfo, node) {
1032         if (info->recvState == TRANS_FILE_RECV_IDLE_STATE || info->recvFileInfo.fileStatus != NODE_BUSY) {
1033             continue;
1034         }
1035         if (strcmp(info->recvFileInfo.filePath, absFullPath) == 0) {
1036             (void)SoftBusMutexUnlock(&g_recvFileInfoLock.lock);
1037             return true;
1038         }
1039     }
1040     (void)SoftBusMutexUnlock(&g_recvFileInfoLock.lock);
1041     return false;
1042 }
PutToRecvFileList(FileRecipientInfo * recipient,const SingleFileInfo * file)1043 static int32_t PutToRecvFileList(FileRecipientInfo *recipient, const SingleFileInfo *file)
1044 {
1045 #define RETRY_WRITE_LOCK_TIMES 2
1046     if (recipient == NULL || file == NULL) {
1047         TRANS_LOGE(TRANS_FILE, "file is null");
1048         return SOFTBUS_INVALID_PARAM;
1049     }
1050     if (recipient->recvFileInfo.fileStatus != NODE_IDLE) {
1051         TRANS_LOGE(TRANS_FILE, "session receiving file");
1052         return SOFTBUS_FILE_ERR;
1053     }
1054     if (CheckRecvFileExist(file->filePath)) {
1055         TRANS_LOGE(TRANS_FILE, "file is already exist and busy");
1056         return SOFTBUS_FILE_ERR;
1057     }
1058     if (memcpy_s(&recipient->recvFileInfo, sizeof(SingleFileInfo), file, sizeof(SingleFileInfo)) != EOK) {
1059         TRANS_LOGE(TRANS_FILE, "memcpy file info fail");
1060         return SOFTBUS_MEM_ERR;
1061     }
1062     int32_t fd = SoftBusOpenFileWithPerms(
1063         file->filePath, SOFTBUS_O_WRONLY | SOFTBUS_O_CREATE, SOFTBUS_S_IRUSR | SOFTBUS_S_IWUSR);
1064     if (fd < 0) {
1065         TRANS_LOGE(TRANS_FILE, "open destFile fail");
1066         return SOFTBUS_FILE_ERR;
1067     }
1068     if (TryFileLock(fd, SOFTBUS_F_WRLCK, RETRY_WRITE_LOCK_TIMES) != SOFTBUS_OK) {
1069         TRANS_LOGE(TRANS_FILE, "file busy");
1070         SoftBusCloseFile(fd);
1071         return SOFTBUS_FILE_ERR;
1072     }
1073     (void)ftruncate(fd, 0);
1074     recipient->recvFileInfo.fileStatus = NODE_BUSY;
1075     recipient->recvFileInfo.fileOffset = 0;
1076     recipient->recvFileInfo.timeOut = 0;
1077     recipient->recvFileInfo.fileFd = fd;
1078     return SOFTBUS_OK;
1079 }
1080 
GetRecipientNoLock(int32_t sessionId)1081 static FileRecipientInfo *GetRecipientNoLock(int32_t sessionId)
1082 {
1083     FileRecipientInfo *info = NULL;
1084     LIST_FOR_EACH_ENTRY(info, &g_recvRecipientInfoList, FileRecipientInfo, node) {
1085         if (info->sessionId == sessionId) {
1086             return info;
1087         }
1088     }
1089     return NULL;
1090 }
1091 
ReleaseRecipientRef(FileRecipientInfo * info)1092 static void ReleaseRecipientRef(FileRecipientInfo *info)
1093 {
1094     if (info == NULL) {
1095         TRANS_LOGE(TRANS_FILE, "param info invalid.");
1096         return;
1097     }
1098     if (SoftBusMutexLock(&g_recvFileInfoLock.lock) != SOFTBUS_OK) {
1099         TRANS_LOGE(TRANS_FILE, "lock failed.");
1100         return;
1101     }
1102     info->objRefCount--;
1103     if (info->objRefCount == 0) {
1104         ListDelete(&info->node);
1105         ClearRecipientResources(info);
1106         SoftBusFree(info);
1107     }
1108     (void)SoftBusMutexUnlock(&g_recvFileInfoLock.lock);
1109 }
1110 
DelRecipient(int32_t sessionId)1111 static void DelRecipient(int32_t sessionId)
1112 {
1113     if (SoftBusMutexLock(&g_recvFileInfoLock.lock) != SOFTBUS_OK) {
1114         return;
1115     }
1116     FileRecipientInfo *info = NULL;
1117     LIST_FOR_EACH_ENTRY(info, &g_recvRecipientInfoList, FileRecipientInfo, node) {
1118         if (info->sessionId == sessionId) {
1119             info->objRefCount--;
1120             if (info->objRefCount == 0) {
1121                 ListDelete(&info->node);
1122                 TRANS_LOGI(TRANS_FILE, "delete sessionId = %{public}d", sessionId);
1123                 ClearRecipientResources(info);
1124                 SoftBusFree(info);
1125             }
1126             break;
1127         }
1128     }
1129     (void)SoftBusMutexUnlock(&g_recvFileInfoLock.lock);
1130 }
1131 
ClientDeleteRecvFileList(int32_t sessionId)1132 void ClientDeleteRecvFileList(int32_t sessionId)
1133 {
1134     if (sessionId <= 0) {
1135         TRANS_LOGE(TRANS_FILE, "session id is invalid");
1136         return;
1137     }
1138     (void)DelRecipient(sessionId);
1139 }
1140 
UpdateFileReceivePath(int32_t sessionId,FileListener * fileListener)1141 static int32_t UpdateFileReceivePath(int32_t sessionId, FileListener *fileListener)
1142 {
1143     if (fileListener->socketRecvCallback == NULL) {
1144         return SOFTBUS_OK;
1145     }
1146     FileEvent event = {
1147         .type = FILE_EVENT_RECV_UPDATE_PATH,
1148         .files = NULL,
1149         .fileCnt = 0,
1150         .bytesProcessed = 0,
1151         .bytesTotal = 0,
1152         .UpdateRecvPath = NULL,
1153     };
1154     fileListener->socketRecvCallback(sessionId, &event);
1155     if (event.UpdateRecvPath == NULL) {
1156         TRANS_LOGE(TRANS_FILE, "failed to obtain the file receive path");
1157         return SOFTBUS_FILE_ERR;
1158     }
1159 
1160     const char *rootDir = event.UpdateRecvPath();
1161     char *absPath = realpath(rootDir, NULL);
1162     if (absPath == NULL) {
1163         TRANS_LOGE(TRANS_SDK, "rootDir not exist, rootDir=%{private}s, errno=%{public}d.",
1164             (rootDir == NULL ? "null" : rootDir), errno);
1165         return SOFTBUS_FILE_ERR;
1166     }
1167 
1168     if (strcpy_s(fileListener->rootDir, FILE_RECV_ROOT_DIR_SIZE_MAX, absPath) != EOK) {
1169         TRANS_LOGE(TRANS_FILE, "failed to strcpy the file receive path");
1170         SoftBusFree(absPath);
1171         return SOFTBUS_STRCPY_ERR;
1172     }
1173     SoftBusFree(absPath);
1174     return SOFTBUS_OK;
1175 }
1176 
CreateNewRecipient(int32_t sessionId,int32_t channelId,int32_t osType)1177 static FileRecipientInfo *CreateNewRecipient(int32_t sessionId, int32_t channelId, int32_t osType)
1178 {
1179     FileRecipientInfo *info = NULL;
1180     LIST_FOR_EACH_ENTRY(info, &g_recvRecipientInfoList, FileRecipientInfo, node) {
1181         if (info->sessionId == sessionId) {
1182             TRANS_LOGE(TRANS_FILE, "session id exists");
1183             return NULL;
1184         }
1185     }
1186     info = (FileRecipientInfo *)SoftBusCalloc(sizeof(FileRecipientInfo));
1187     if (info == NULL) {
1188         TRANS_LOGE(TRANS_FILE, "info calloc failed");
1189         return NULL;
1190     }
1191     char sessionName[SESSION_NAME_SIZE_MAX] = { 0 };
1192     if (ClientGetSessionDataById(sessionId, sessionName, SESSION_NAME_SIZE_MAX, KEY_SESSION_NAME) != SOFTBUS_OK) {
1193         TRANS_LOGE(TRANS_FILE, "get sessionId name failed");
1194         SoftBusFree(info);
1195         return NULL;
1196     }
1197     if (ClientGetFileConfigInfoById(sessionId, &info->fileEncrypt, &info->algorithm, &info->crc) != SOFTBUS_OK) {
1198         TRANS_LOGE(TRANS_FILE, "get file config failed");
1199         SoftBusFree(info);
1200         return NULL;
1201     }
1202     info->channelId = channelId;
1203     info->sessionId = sessionId;
1204     info->osType = osType;
1205     if (TransGetFileListener(sessionName, &(info->fileListener)) != SOFTBUS_OK) {
1206         TRANS_LOGE(TRANS_FILE, "get file listener failed");
1207         SoftBusFree(info);
1208         return NULL;
1209     }
1210 
1211     if (UpdateFileReceivePath(sessionId, &info->fileListener) != SOFTBUS_OK) {
1212         TRANS_LOGE(TRANS_FILE, "failed to get rootDir");
1213         SoftBusFree(info);
1214         return NULL;
1215     }
1216 
1217     ListInit(&info->node);
1218     info->objRefCount = 1;
1219     info->recvFileInfo.fileFd = INVALID_FD;
1220     ListTailInsert(&g_recvRecipientInfoList, &info->node);
1221     return info;
1222 }
1223 
GetFileInfoByStartFrame(const FileFrame * fileFrame,const FileRecipientInfo * info,SingleFileInfo * file,uint32_t packetSize)1224 static int32_t GetFileInfoByStartFrame(
1225     const FileFrame *fileFrame, const FileRecipientInfo *info, SingleFileInfo *file, uint32_t packetSize)
1226 {
1227     if (file == NULL || info == NULL || fileFrame == NULL) {
1228         return SOFTBUS_INVALID_PARAM;
1229     }
1230     const char *rootDir = info->fileListener.rootDir;
1231     if (strstr(rootDir, "..") != NULL) {
1232         TRANS_LOGE(TRANS_FILE, "rootDir is not canonical form. rootDir=%{private}s", rootDir);
1233         return SOFTBUS_FILE_ERR;
1234     }
1235     int32_t ret = UnpackFileTransStartInfo((FileFrame *)fileFrame, info, file, packetSize);
1236     if (ret != SOFTBUS_OK) {
1237         TRANS_LOGE(TRANS_FILE, "unpack start info fail. sessionId=%{public}d", info->sessionId);
1238         return ret;
1239     }
1240     char *filePath = file->filePath;
1241     if (!CheckDestFilePathValid(filePath)) {
1242         TRANS_LOGE(TRANS_FILE, "recv filePath form is wrong. filePath=%{private}s", filePath);
1243         return SOFTBUS_FILE_ERR;
1244     }
1245     TRANS_LOGI(TRANS_FILE, "dst filePath=%{private}s, rootDir=%{private}s", filePath, rootDir);
1246     char *fullRecvPath = GetFullRecvPath(filePath, rootDir);
1247     if (!IsPathValid(fullRecvPath)) {
1248         TRANS_LOGE(TRANS_FILE, "destFilePath is invalid");
1249         SoftBusFree(fullRecvPath);
1250         return SOFTBUS_FILE_ERR;
1251     }
1252     (void)memset_s(filePath, MAX_FILE_PATH_NAME_LEN, 0, MAX_FILE_PATH_NAME_LEN);
1253     ret = CreateDirAndGetAbsPath(fullRecvPath, filePath, MAX_FILE_PATH_NAME_LEN);
1254     if (ret != SOFTBUS_OK) {
1255         TRANS_LOGE(TRANS_FILE, "create dest dir failed");
1256         SoftBusFree(fullRecvPath);
1257         return ret;
1258     }
1259     SoftBusFree(fullRecvPath);
1260     return SOFTBUS_OK;
1261 }
1262 
GetRecipientInCreateFileRef(int32_t sessionId,int32_t channelId,int32_t osType)1263 static FileRecipientInfo *GetRecipientInCreateFileRef(int32_t sessionId, int32_t channelId, int32_t osType)
1264 {
1265     if (SoftBusMutexLock(&g_recvFileInfoLock.lock) != SOFTBUS_OK) {
1266         TRANS_LOGE(TRANS_FILE, "mutex lock fail");
1267         return NULL;
1268     }
1269     FileRecipientInfo *recipient = GetRecipientNoLock(sessionId);
1270     if (recipient == NULL) {
1271         recipient = CreateNewRecipient(sessionId, channelId, osType);
1272         if (recipient == NULL) {
1273             TRANS_LOGE(TRANS_FILE, "create file recipient fail. sessionId=%{public}d", sessionId);
1274             (void)SoftBusMutexUnlock(&g_recvFileInfoLock.lock);
1275             return NULL;
1276         }
1277     }
1278     if (recipient->recvState != TRANS_FILE_RECV_IDLE_STATE) {
1279         TRANS_LOGE(TRANS_FILE, "create file fail. recvState=%{public}d, sessionId=%{public}d", sessionId,
1280             recipient->recvState);
1281         (void)SoftBusMutexUnlock(&g_recvFileInfoLock.lock);
1282         return NULL;
1283     }
1284     recipient->recvState = TRANS_FILE_RECV_START_STATE;
1285     recipient->objRefCount++;
1286     (void)SoftBusMutexUnlock(&g_recvFileInfoLock.lock);
1287     return recipient;
1288 }
1289 
GetRecipientInProcessRef(int32_t sessionId)1290 static FileRecipientInfo *GetRecipientInProcessRef(int32_t sessionId)
1291 {
1292     if (SoftBusMutexLock(&g_recvFileInfoLock.lock) != SOFTBUS_OK) {
1293         TRANS_LOGE(TRANS_FILE, "mutex lock fail");
1294         return NULL;
1295     }
1296     FileRecipientInfo *recipient = GetRecipientNoLock(sessionId);
1297     if (recipient == NULL || recipient->recvState == TRANS_FILE_RECV_IDLE_STATE) {
1298         TRANS_LOGE(TRANS_FILE, "get recipient no lock fail");
1299         (void)SoftBusMutexUnlock(&g_recvFileInfoLock.lock);
1300         return NULL;
1301     }
1302     if (recipient->recvState == TRANS_FILE_RECV_START_STATE) {
1303         recipient->recvState = TRANS_FILE_RECV_PROCESS_STATE;
1304     }
1305     recipient->objRefCount++;
1306     (void)SoftBusMutexUnlock(&g_recvFileInfoLock.lock);
1307     return recipient;
1308 }
1309 
GetRecipientInfo(int32_t sessionId)1310 static FileRecipientInfo *GetRecipientInfo(int32_t sessionId)
1311 {
1312     if (SoftBusMutexLock(&g_recvFileInfoLock.lock) != SOFTBUS_OK) {
1313         TRANS_LOGE(TRANS_FILE, "mutex lock fail");
1314         return NULL;
1315     }
1316     FileRecipientInfo *recipient = GetRecipientNoLock(sessionId);
1317     if (recipient == NULL) {
1318         TRANS_LOGE(TRANS_FILE, "get recipient no lock fail");
1319         (void)SoftBusMutexUnlock(&g_recvFileInfoLock.lock);
1320         return NULL;
1321     }
1322     if (recipient->recvState == TRANS_FILE_RECV_START_STATE) {
1323         recipient->recvState = TRANS_FILE_RECV_PROCESS_STATE;
1324     }
1325     recipient->objRefCount++;
1326     (void)SoftBusMutexUnlock(&g_recvFileInfoLock.lock);
1327     return recipient;
1328 }
1329 
HandleFileTransferCompletion(FileRecipientInfo * recipient,int32_t sessionId,SingleFileInfo * file)1330 static void HandleFileTransferCompletion(FileRecipientInfo *recipient, int32_t sessionId, SingleFileInfo *file)
1331 {
1332     TRANS_CHECK_AND_RETURN_LOGE(recipient != NULL && file != NULL, TRANS_FILE, "recipient or file invalid.");
1333     if (recipient->fileListener.socketRecvCallback != NULL) {
1334         const char *fileList[] = { file->filePath };
1335         FileEvent event = {
1336             .type = FILE_EVENT_RECV_START,
1337             .files = fileList,
1338             .fileCnt = 1,
1339             .bytesProcessed = file->fileSize,
1340             .bytesTotal = file->fileSize,
1341             .UpdateRecvPath = NULL,
1342         };
1343         recipient->fileListener.socketRecvCallback(sessionId, &event);
1344     } else if (recipient->fileListener.recvListener.OnReceiveFileStarted != NULL) {
1345         recipient->fileListener.recvListener.OnReceiveFileStarted(sessionId, file->filePath, 1);
1346     }
1347 }
1348 
CreateFileFromFrame(int32_t sessionId,int32_t channelId,const FileFrame * fileFrame,int32_t osType,uint32_t packetSize)1349 static int32_t CreateFileFromFrame(
1350     int32_t sessionId, int32_t channelId, const FileFrame *fileFrame, int32_t osType, uint32_t packetSize)
1351 {
1352     FileRecipientInfo *recipient = GetRecipientInCreateFileRef(sessionId, channelId, osType);
1353     if (recipient == NULL) {
1354         TRANS_LOGE(TRANS_FILE, "GetRecipientInCreateFileRef fail. sessionId=%{public}d", sessionId);
1355         return SOFTBUS_NO_INIT;
1356     }
1357     int32_t result = SOFTBUS_FILE_ERR;
1358     SingleFileInfo *file = (SingleFileInfo *)SoftBusCalloc(sizeof(SingleFileInfo));
1359     if (file == NULL) {
1360         TRANS_LOGE(TRANS_FILE, "file calloc fail");
1361         goto EXIT_ERR;
1362     }
1363     if (GetFileInfoByStartFrame(fileFrame, recipient, file, packetSize) != SOFTBUS_OK) {
1364         TRANS_LOGE(TRANS_FILE, "get file info by start frame fail");
1365         goto EXIT_ERR;
1366     }
1367     TRANS_LOGI(TRANS_FILE, "null filePath. filePath=%{private}s, seq=%{public}u", file->filePath, file->seq);
1368     if (PutToRecvFileList(recipient, file) != SOFTBUS_OK) {
1369         TRANS_LOGE(TRANS_FILE, "put to recv files failed. sessionId=%{public}u", recipient->sessionId);
1370         goto EXIT_ERR;
1371     }
1372     HandleFileTransferCompletion(recipient, sessionId, file);
1373     SoftBusFree(file);
1374     if (recipient->crc == APP_INFO_FILE_FEATURES_SUPPORT) {
1375         (void)SendFileTransResult(channelId, 0, SOFTBUS_OK, IS_RECV_RESULT);
1376     }
1377     ReleaseRecipientRef(recipient);
1378     return SOFTBUS_OK;
1379 EXIT_ERR:
1380     SoftBusFree(file);
1381     if (recipient->crc == APP_INFO_FILE_FEATURES_SUPPORT) {
1382         (void)SendFileTransResult(channelId, 0, result, IS_RECV_RESULT);
1383     }
1384     if (recipient->fileListener.socketRecvCallback != NULL) {
1385         FileEvent event = { .type = FILE_EVENT_RECV_ERROR };
1386         recipient->fileListener.socketRecvCallback(sessionId, &event);
1387     } else if (recipient->fileListener.recvListener.OnFileTransError != NULL) {
1388         recipient->fileListener.recvListener.OnFileTransError(sessionId);
1389     }
1390     ReleaseRecipientRef(recipient);
1391     DelRecipient(sessionId);
1392     return SOFTBUS_FILE_ERR;
1393 }
1394 
WriteEmptyFrame(SingleFileInfo * fileInfo,int32_t count)1395 static int32_t WriteEmptyFrame(SingleFileInfo *fileInfo, int32_t count)
1396 {
1397     if (fileInfo == NULL) {
1398         TRANS_LOGW(TRANS_FILE, "invalid param.");
1399         return SOFTBUS_INVALID_PARAM;
1400     }
1401 
1402     if (count > 0) {
1403         TRANS_LOGI(TRANS_FILE, "write empty frame. count=%{public}d", count);
1404         char *emptyBuff = (char *)SoftBusCalloc(fileInfo->oneFrameLen);
1405         if (emptyBuff == NULL) {
1406             return SOFTBUS_MALLOC_ERR;
1407         }
1408         for (int32_t i = 0; i < count; ++i) {
1409             int64_t emptyLen =
1410                 SoftBusPwriteFile(fileInfo->fileFd, emptyBuff, fileInfo->oneFrameLen, fileInfo->fileOffset);
1411             if (emptyLen < 0 || (uint64_t)emptyLen != fileInfo->oneFrameLen) {
1412                 TRANS_LOGE(TRANS_FILE, "pwrite empty frame fail");
1413                 SoftBusFree(emptyBuff);
1414                 return SOFTBUS_FILE_ERR;
1415             }
1416             fileInfo->fileOffset += (uint64_t)emptyLen;
1417         }
1418         SoftBusFree(emptyBuff);
1419     }
1420     return SOFTBUS_OK;
1421 }
1422 
ProcessFileFrameSequence(uint64_t * fileOffset,const FileFrame * frame,SingleFileInfo * fileInfo)1423 static int32_t ProcessFileFrameSequence(uint64_t *fileOffset, const FileFrame *frame, SingleFileInfo *fileInfo)
1424 {
1425     uint32_t bit = frame->seq % FILE_SEND_ACK_INTERVAL;
1426     bit = ((bit == 0) ? (FILE_SEND_ACK_INTERVAL - 1) : (bit - 1));
1427     if (frame->seq >= fileInfo->startSeq) {
1428         int64_t seqDiff = (int32_t)((int32_t)frame->seq - (int32_t)fileInfo->seq - 1);
1429         if (seqDiff > INT32_MAX) {
1430             TRANS_LOGE(TRANS_FILE, "seqDiff overflow");
1431             return SOFTBUS_INVALID_NUM;
1432         }
1433 
1434         if (fileInfo->oneFrameLen > INT64_MAX || seqDiff * (int64_t)fileInfo->oneFrameLen > INT64_MAX) {
1435             TRANS_LOGE(TRANS_FILE, "Data overflow");
1436             return SOFTBUS_INVALID_NUM;
1437         }
1438         int64_t bytesToWrite = (int64_t)seqDiff * (int64_t)fileInfo->oneFrameLen;
1439         if (bytesToWrite > MAX_FILE_SIZE) {
1440             TRANS_LOGE(
1441                 TRANS_FILE, "WriteEmptyFrame bytesToWrite is too large, bytesToWrite=%{public}" PRIu64, bytesToWrite);
1442             return SOFTBUS_FILE_ERR;
1443         }
1444         if (fileInfo->fileOffset > (uint64_t)MAX_FILE_SIZE - (uint64_t)bytesToWrite) {
1445             TRANS_LOGE(TRANS_FILE, "file is too large, offset=%{public}" PRIu64, fileInfo->fileOffset + bytesToWrite);
1446             return SOFTBUS_FILE_ERR;
1447         }
1448         int32_t ret = WriteEmptyFrame(fileInfo, (int32_t)seqDiff);
1449         TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_FILE, "write frame failed");
1450 
1451         if ((frame->seq >=
1452             fileInfo->preStartSeq + (uint32_t)FILE_SEND_ACK_INTERVAL + (uint32_t)WAIT_FRAME_ACK_TIMEOUT_COUNT - 1u) ||
1453             (frame->frameType == TRANS_SESSION_FILE_LAST_FRAME && frame->seq > FILE_SEND_ACK_INTERVAL)) {
1454             if ((fileInfo->preSeqResult & FILE_SEND_ACK_RESULT_SUCCESS) != FILE_SEND_ACK_RESULT_SUCCESS) {
1455                 TRANS_LOGE(TRANS_FILE, "recv file fail. frame loss");
1456                 return SOFTBUS_FILE_ERR;
1457             }
1458         }
1459         fileInfo->seq = frame->seq;
1460         *fileOffset = fileInfo->fileOffset;
1461         fileInfo->seqResult |= 0x01 << bit;
1462     } else {
1463         TRANS_LOGI(TRANS_FILE, "recv retrans file frame");
1464         *fileOffset = (frame->seq - 1) * fileInfo->oneFrameLen;
1465         fileInfo->preSeqResult |= 0x01 << bit;
1466     }
1467     return SOFTBUS_OK;
1468 }
1469 
ProcessOneFrameCRC(const FileFrame * frame,uint32_t dataLen,SingleFileInfo * fileInfo)1470 static int32_t ProcessOneFrameCRC(const FileFrame *frame, uint32_t dataLen, SingleFileInfo *fileInfo)
1471 {
1472     TRANS_CHECK_AND_RETURN_RET_LOGE(
1473         (frame != NULL && fileInfo != NULL), SOFTBUS_INVALID_PARAM, TRANS_FILE, "invalid param");
1474 
1475     if (frame->seq < 1 || frame->seq >= fileInfo->startSeq + FILE_SEND_ACK_INTERVAL) {
1476         return SOFTBUS_FILE_ERR;
1477     }
1478     uint64_t fileOffset = 0;
1479     if (ProcessFileFrameSequence(&fileOffset, frame, fileInfo) != SOFTBUS_OK) {
1480         return SOFTBUS_FILE_ERR;
1481     }
1482 
1483     uint32_t frameDataLength = dataLen - FRAME_DATA_SEQ_OFFSET;
1484 
1485     if (MAX_FILE_SIZE < frameDataLength) {
1486         TRANS_LOGE(TRANS_FILE, "frameDataLength is too large, frameDataLen=%{public}" PRIu32, frameDataLength);
1487         return SOFTBUS_FILE_ERR;
1488     }
1489 
1490     if (fileOffset > MAX_FILE_SIZE - frameDataLength) {
1491         TRANS_LOGE(TRANS_FILE, "file is too large, offset=%{public}" PRIu64, fileOffset + frameDataLength);
1492         return SOFTBUS_FILE_ERR;
1493     }
1494 
1495     int64_t writeLength = SoftBusPwriteFile(
1496         fileInfo->fileFd, frame->fileData + FRAME_DATA_SEQ_OFFSET, dataLen - FRAME_DATA_SEQ_OFFSET, fileOffset);
1497     if (writeLength < 0 || (uint64_t)writeLength != dataLen - FRAME_DATA_SEQ_OFFSET) {
1498         TRANS_LOGE(TRANS_FILE, "pwrite file failed");
1499         return SOFTBUS_FILE_ERR;
1500     }
1501     if (frame->seq >= fileInfo->startSeq) {
1502         fileInfo->fileOffset += (uint64_t)writeLength;
1503         if (fileInfo->fileOffset > MAX_FILE_SIZE) {
1504             TRANS_LOGE(TRANS_FILE, "file is too large, offset=%{public}" PRIu64, fileInfo->fileOffset);
1505             return SOFTBUS_FILE_ERR;
1506         }
1507         fileInfo->checkSumCRC += frame->crc;
1508     }
1509     return SOFTBUS_OK;
1510 }
1511 
ProcessOneFrame(const FileFrame * fileFrame,uint32_t dataLen,int32_t crc,SingleFileInfo * fileInfo,int32_t osType)1512 static int32_t ProcessOneFrame(
1513     const FileFrame *fileFrame, uint32_t dataLen, int32_t crc, SingleFileInfo *fileInfo, int32_t osType)
1514 {
1515     if (fileInfo->fileStatus == NODE_ERR) {
1516         TRANS_LOGE(TRANS_FILE, "fileStatus is error");
1517         return SOFTBUS_FILE_ERR;
1518     }
1519     if (crc == APP_INFO_FILE_FEATURES_SUPPORT && osType == OH_TYPE) {
1520         return ProcessOneFrameCRC(fileFrame, dataLen, fileInfo);
1521     } else {
1522         uint32_t frameDataLength = dataLen - FRAME_DATA_SEQ_OFFSET;
1523         fileInfo->seq = fileFrame->seq;
1524 
1525         if (MAX_FILE_SIZE < frameDataLength) {
1526             TRANS_LOGE(TRANS_FILE, "frameDataLength is too large, frameDataLen=%{public}" PRIu32, frameDataLength);
1527             return SOFTBUS_FILE_ERR;
1528         }
1529 
1530         if (fileInfo->fileOffset > MAX_FILE_SIZE - frameDataLength) {
1531             TRANS_LOGE(
1532                 TRANS_FILE, "file is too large, offset=%{public}" PRIu64, fileInfo->fileOffset + frameDataLength);
1533             return SOFTBUS_FILE_ERR;
1534         }
1535         int64_t writeLength = SoftBusPwriteFile(
1536             fileInfo->fileFd, fileFrame->fileData + FRAME_DATA_SEQ_OFFSET, frameDataLength, fileInfo->fileOffset);
1537         if (writeLength != frameDataLength) {
1538             TRANS_LOGE(TRANS_FILE, "pwrite file failed");
1539             return SOFTBUS_FILE_ERR;
1540         }
1541         fileInfo->fileOffset += (uint64_t)writeLength;
1542         if (fileInfo->fileOffset > MAX_FILE_SIZE) {
1543             TRANS_LOGE(TRANS_FILE, "file is too large, offset=%{public}" PRIu64, fileInfo->fileOffset);
1544             return SOFTBUS_FILE_ERR;
1545         }
1546     }
1547     return SOFTBUS_OK;
1548 }
1549 
UpdateFileReceptionStatus(SingleFileInfo * fileInfo,FileRecipientInfo * recipient,const FileFrame * fileFrame,int32_t sessionId)1550 static int32_t UpdateFileReceptionStatus(
1551     SingleFileInfo *fileInfo, FileRecipientInfo *recipient, const FileFrame *fileFrame, int32_t sessionId)
1552 {
1553     fileInfo->timeOut = 0;
1554     if (recipient->fileListener.socketRecvCallback != NULL) {
1555         const char *fileList[] = { fileInfo->filePath };
1556         FileEvent event = {
1557             .type = FILE_EVENT_RECV_PROCESS,
1558             .files = fileList,
1559             .fileCnt = 1,
1560             .bytesProcessed = fileInfo->fileOffset,
1561             .bytesTotal = fileInfo->fileSize,
1562             .UpdateRecvPath = NULL,
1563         };
1564         recipient->fileListener.socketRecvCallback(sessionId, &event);
1565     } else if (recipient->fileListener.recvListener.OnReceiveFileProcess != NULL) {
1566         recipient->fileListener.recvListener.OnReceiveFileProcess(
1567             sessionId, fileInfo->filePath, fileInfo->fileOffset, fileInfo->fileSize);
1568     }
1569     if (recipient->crc != APP_INFO_FILE_FEATURES_SUPPORT) {
1570         if ((fileFrame->frameType == TRANS_SESSION_FILE_LAST_FRAME) ||
1571             (fileFrame->frameType == TRANS_SESSION_FILE_ONLYONE_FRAME)) {
1572             TRANS_LOGI(TRANS_FILE, "process last frame, seq=%{public}u", fileFrame->seq);
1573             SetRecipientRecvState(recipient, TRANS_FILE_RECV_IDLE_STATE);
1574             if (SoftBusMutexLock(&g_recvFileInfoLock.lock) != SOFTBUS_OK) {
1575                 TRANS_LOGE(TRANS_FILE, "mutex lock failed");
1576                 return SOFTBUS_LOCK_ERR;
1577             }
1578             (void)FileUnLock(fileInfo->fileFd);
1579             SoftBusCloseFile(fileInfo->fileFd);
1580             fileInfo->fileFd = INVALID_FD;
1581             (void)SoftBusMutexUnlock(&g_recvFileInfoLock.lock);
1582         }
1583     }
1584 
1585     return SOFTBUS_OK;
1586 }
1587 
WriteFrameToFile(int32_t sessionId,const FileFrame * fileFrame)1588 static int32_t WriteFrameToFile(int32_t sessionId, const FileFrame *fileFrame)
1589 {
1590     FileRecipientInfo *recipient = GetRecipientInProcessRef(sessionId);
1591     if (recipient == NULL) {
1592         TRANS_LOGE(TRANS_FILE, "get recipient in process ref failed");
1593         return SOFTBUS_NOT_FIND;
1594     }
1595     int32_t result = SOFTBUS_FILE_ERR;
1596     SingleFileInfo *fileInfo = &recipient->recvFileInfo;
1597     uint32_t dataLen;
1598     if (UnpackFileDataFrame(recipient, (FileFrame *)fileFrame, &dataLen) != SOFTBUS_OK) {
1599         TRANS_LOGE(TRANS_FILE, "unpack file data frame failed");
1600         goto EXIT_ERR;
1601     }
1602     if (ProcessOneFrame(fileFrame, dataLen, recipient->crc, fileInfo, recipient->osType) != SOFTBUS_OK) {
1603         TRANS_LOGE(TRANS_FILE, "write one frame error");
1604         goto EXIT_ERR;
1605     }
1606     if (UpdateFileReceptionStatus(fileInfo, recipient, fileFrame, sessionId) != SOFTBUS_OK) {
1607         return SOFTBUS_FILE_ERR;
1608     }
1609     ReleaseRecipientRef(recipient);
1610     return SOFTBUS_OK;
1611 EXIT_ERR:
1612     if (recipient->crc == APP_INFO_FILE_FEATURES_SUPPORT) {
1613         (void)SendFileTransResult(recipient->channelId, 0, result, IS_RECV_RESULT);
1614     }
1615     SetRecipientRecvState(recipient, TRANS_FILE_RECV_ERR_STATE);
1616     if (recipient->fileListener.socketRecvCallback != NULL) {
1617         FileEvent event = { .type = FILE_EVENT_RECV_ERROR };
1618         recipient->fileListener.socketRecvCallback(sessionId, &event);
1619     } else if (recipient->fileListener.recvListener.OnFileTransError != NULL) {
1620         recipient->fileListener.recvListener.OnFileTransError(sessionId);
1621     }
1622     ReleaseRecipientRef(recipient);
1623     DelRecipient(sessionId);
1624     return SOFTBUS_FILE_ERR;
1625 }
1626 
NotifyRecipientReceiveStateAndCallback(FileRecipientInfo * recipient,int32_t sessionId,char * absRecvPath,int32_t fileCount)1627 static void NotifyRecipientReceiveStateAndCallback(
1628     FileRecipientInfo *recipient, int32_t sessionId, char *absRecvPath, int32_t fileCount)
1629 {
1630     TRANS_CHECK_AND_RETURN_LOGE(recipient != NULL, TRANS_FILE, "recipient is empty.");
1631 
1632     SetRecipientRecvState(recipient, TRANS_FILE_RECV_IDLE_STATE);
1633     if (recipient->fileListener.socketRecvCallback != NULL) {
1634         const char *fileList[] = { absRecvPath };
1635         FileEvent event = {
1636             .type = FILE_EVENT_RECV_FINISH,
1637             .files = fileList,
1638             .fileCnt = 1,
1639             .bytesProcessed = 0,
1640             .bytesTotal = 0,
1641         };
1642         recipient->fileListener.socketRecvCallback(sessionId, &event);
1643     } else if (recipient->fileListener.recvListener.OnReceiveFileFinished != NULL) {
1644         recipient->fileListener.recvListener.OnReceiveFileFinished(sessionId, absRecvPath, fileCount);
1645     }
1646 }
1647 
ProcessFileListData(int32_t sessionId,const FileFrame * frame)1648 static int32_t ProcessFileListData(int32_t sessionId, const FileFrame *frame)
1649 {
1650     FileRecipientInfo *recipient = GetRecipientInfo(sessionId);
1651     TRANS_CHECK_AND_RETURN_RET_LOGE(recipient != NULL, SOFTBUS_NOT_FIND, TRANS_FILE, "get recipient info failed");
1652 
1653     int32_t ret = SOFTBUS_FILE_ERR;
1654     int32_t fileCount;
1655     char *fullRecvPath = NULL;
1656     char *absRecvPath = NULL;
1657     char *firstFilePath = BufferToFileList(frame->data, frame->frameLength, &fileCount);
1658     if (firstFilePath == NULL) {
1659         TRANS_LOGE(TRANS_FILE, "buffer to file list fail");
1660         goto EXIT_ERR;
1661     }
1662     fullRecvPath = GetFullRecvPath(firstFilePath, recipient->fileListener.rootDir);
1663     SoftBusFree(firstFilePath);
1664     if (!IsPathValid(fullRecvPath)) {
1665         TRANS_LOGE(TRANS_FILE, "file list path is invalid");
1666         SoftBusFree(fullRecvPath);
1667         goto EXIT_ERR;
1668     }
1669     absRecvPath = (char *)SoftBusCalloc(PATH_MAX + 1);
1670     if (absRecvPath == NULL) {
1671         TRANS_LOGE(TRANS_FILE, "calloc absFullDir fail");
1672         SoftBusFree(fullRecvPath);
1673         goto EXIT_ERR;
1674     }
1675     if (GetAndCheckRealPath(fullRecvPath, absRecvPath) != SOFTBUS_OK) {
1676         TRANS_LOGE(TRANS_FILE, "get recv abs file path fail");
1677         SoftBusFree(fullRecvPath);
1678         SoftBusFree(absRecvPath);
1679         goto EXIT_ERR;
1680     }
1681     NotifyRecipientReceiveStateAndCallback(recipient, sessionId, absRecvPath, fileCount);
1682     SoftBusFree(fullRecvPath);
1683     SoftBusFree(absRecvPath);
1684     ret = SOFTBUS_OK;
1685 EXIT_ERR:
1686     if (ret != SOFTBUS_OK) {
1687         if (recipient->fileListener.socketRecvCallback != NULL) {
1688             FileEvent event = { .type = FILE_EVENT_RECV_ERROR };
1689             recipient->fileListener.socketRecvCallback(sessionId, &event);
1690         } else if (recipient->fileListener.recvListener.OnFileTransError != NULL) {
1691             recipient->fileListener.recvListener.OnFileTransError(sessionId);
1692         }
1693         SetRecipientRecvState(recipient, TRANS_FILE_RECV_ERR_STATE);
1694     }
1695     ReleaseRecipientRef(recipient);
1696     DelRecipient(sessionId);
1697     return ret;
1698 }
1699 
ProcessFileRecvResult(int32_t sessionId,uint32_t seq,int32_t result)1700 static int32_t ProcessFileRecvResult(int32_t sessionId, uint32_t seq, int32_t result)
1701 {
1702     if (SoftBusMutexLock(&g_sendFileInfoLock.lock) != SOFTBUS_OK) {
1703         TRANS_LOGE(TRANS_FILE, "process recv result lock fail");
1704         return SOFTBUS_LOCK_ERR;
1705     }
1706     SendListenerInfo *item = NULL;
1707     SendListenerInfo *info = NULL;
1708     LIST_FOR_EACH_ENTRY(item, &g_sendListenerInfoList, SendListenerInfo, node) {
1709         if (item->sessionId == sessionId) {
1710             info = item;
1711             info->result = result;
1712             break;
1713         }
1714     }
1715     (void)SoftBusMutexUnlock(&g_sendFileInfoLock.lock);
1716     if (info != NULL) {
1717         (void)SetPendingPacketData(sessionId, seq, NULL);
1718         return SOFTBUS_OK;
1719     }
1720     return SOFTBUS_NOT_FIND;
1721 }
1722 
ProcessFileSendResult(int32_t sessionId,uint32_t seq,int32_t result)1723 static int32_t ProcessFileSendResult(int32_t sessionId, uint32_t seq, int32_t result)
1724 {
1725     (void)seq;
1726     if (SoftBusMutexLock(&g_recvFileInfoLock.lock) != SOFTBUS_OK) {
1727         TRANS_LOGE(TRANS_FILE, "process send result lock fail");
1728         return SOFTBUS_LOCK_ERR;
1729     }
1730     FileRecipientInfo *item = NULL;
1731     FileRecipientInfo *info = NULL;
1732     LIST_FOR_EACH_ENTRY(item, &g_recvRecipientInfoList, FileRecipientInfo, node) {
1733         if (item->sessionId == sessionId) {
1734             info = item;
1735             info->result = result;
1736             break;
1737         }
1738     }
1739     (void)SoftBusMutexUnlock(&g_recvFileInfoLock.lock);
1740     if (info != NULL) {
1741         return SOFTBUS_OK;
1742     }
1743     return SOFTBUS_NOT_FIND;
1744 }
1745 
ProcessFileTransResult(int32_t sessionId,const FileFrame * frame)1746 static int32_t ProcessFileTransResult(int32_t sessionId, const FileFrame *frame)
1747 {
1748     if (frame == NULL) {
1749         TRANS_LOGE(TRANS_FILE, "invalid param.");
1750         return SOFTBUS_INVALID_PARAM;
1751     }
1752     TRANS_LOGI(TRANS_FILE, "proxy channel send file result. sessionId=%{public}d", sessionId);
1753     uint32_t seq;
1754     int32_t result;
1755     uint32_t side;
1756     int32_t ret = UnpackFileTransResultFrame(frame->data, frame->frameLength, &seq, &result, &side);
1757     TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_FILE, "file trans fail");
1758 
1759     if (side == IS_RECV_RESULT) {
1760         return ProcessFileRecvResult(sessionId, seq, result);
1761     } else if (side == IS_SEND_RESULT) {
1762         return ProcessFileSendResult(sessionId, seq, result);
1763     }
1764     return SOFTBUS_OK;
1765 }
1766 
ProcessCrcCheckSumData(int32_t sessionId,const FileFrame * frame)1767 static int32_t ProcessCrcCheckSumData(int32_t sessionId, const FileFrame *frame)
1768 {
1769     if (frame == NULL) {
1770         TRANS_LOGE(TRANS_FILE, "invalid param.");
1771         return SOFTBUS_INVALID_PARAM;
1772     }
1773     TRANS_LOGI(TRANS_FILE, "proxy channel recv file crc data. sessionId=%{public}d, frameLen=%{public}d",
1774         sessionId, frame->frameLength);
1775     FileRecipientInfo *recipient = GetRecipientInProcessRef(sessionId);
1776     if (recipient == NULL) {
1777         TRANS_LOGE(TRANS_FILE, "recipient invalid");
1778         return SOFTBUS_NOT_FIND;
1779     }
1780     int32_t result = UnpackFileCrcCheckSum(recipient, (FileFrame *)frame);
1781     TRANS_LOGE(TRANS_FILE, "verification crc check sum, ret=%{public}d", result);
1782     int32_t ret = SendFileTransResult(recipient->channelId, frame->seq, result, IS_RECV_RESULT);
1783     if (result != SOFTBUS_OK || ret != SOFTBUS_OK) {
1784         SetRecipientRecvState(recipient, TRANS_FILE_RECV_ERR_STATE);
1785         DelRecipient(sessionId);
1786         return SOFTBUS_FILE_ERR;
1787     }
1788     SetRecipientRecvState(recipient, TRANS_FILE_RECV_IDLE_STATE);
1789     ReleaseRecipientRef(recipient);
1790     return SOFTBUS_OK;
1791 }
1792 
ProcessFileAckRequest(int32_t sessionId,const FileFrame * frame)1793 static int32_t ProcessFileAckRequest(int32_t sessionId, const FileFrame *frame)
1794 {
1795     if (frame == NULL) {
1796         TRANS_LOGE(TRANS_FILE, "invalid param.");
1797         return SOFTBUS_INVALID_PARAM;
1798     }
1799     TRANS_LOGI(TRANS_FILE, "proxy channel recv file ack request. sessionId=%{public}d, len=%{public}u",
1800         sessionId, frame->frameLength);
1801     FileRecipientInfo *recipient = GetRecipientInProcessRef(sessionId);
1802     if (recipient == NULL) {
1803         return SOFTBUS_NOT_FIND;
1804     }
1805     uint32_t startSeq;
1806     uint32_t value;
1807     int32_t ret = UnpackAckReqAndResData((FileFrame *)frame, &startSeq, &value);
1808     if (ret != SOFTBUS_OK) {
1809         ReleaseRecipientRef(recipient);
1810         return ret;
1811     }
1812     SingleFileInfo *file = &recipient->recvFileInfo;
1813     if (startSeq != file->startSeq) {
1814         TRANS_LOGE(TRANS_FILE, "start seq not equal. startSeq=%{public}u, curSeq=%{public}u", startSeq, file->startSeq);
1815         ReleaseRecipientRef(recipient);
1816         return SOFTBUS_FILE_ERR;
1817     }
1818     file->timeOut = 0;
1819     file->preStartSeq = startSeq;
1820     file->startSeq = startSeq + FILE_SEND_ACK_INTERVAL;
1821     value = (uint32_t)(file->seqResult & FILE_SEND_ACK_RESULT_SUCCESS);
1822     file->preSeqResult = value;
1823     file->seqResult = (file->seqResult >> FILE_SEND_ACK_INTERVAL);
1824     ret = SendFileAckReqAndResData(recipient->channelId, startSeq, value, TRANS_SESSION_FILE_ACK_RESPONSE_SENT);
1825     TRANS_LOGI(TRANS_FILE, "send file ack response, ret=%{public}d", ret);
1826     ReleaseRecipientRef(recipient);
1827     return ret;
1828 }
1829 
ProcessFileAckResponse(int32_t sessionId,const FileFrame * frame)1830 static int32_t ProcessFileAckResponse(int32_t sessionId, const FileFrame *frame)
1831 {
1832     if ((frame == NULL) || (frame->data == NULL) || (frame->frameLength == 0)) {
1833         TRANS_LOGE(TRANS_FILE, "invalid param.");
1834         return SOFTBUS_INVALID_PARAM;
1835     }
1836     AckResponseData *data = (AckResponseData *)SoftBusCalloc(sizeof(AckResponseData));
1837     if (data == NULL) {
1838         return SOFTBUS_MALLOC_ERR;
1839     }
1840     TransPendData pendData = {
1841         .data = (char *)data,
1842         .len = sizeof(AckResponseData),
1843     };
1844     int32_t ret = UnpackAckReqAndResData((FileFrame *)frame, &data->startSeq, &data->seqResult);
1845     if (ret != SOFTBUS_OK) {
1846         TRANS_LOGE(TRANS_FILE, "proxy recv unpack ack response fail");
1847         SoftBusFree(data);
1848         return ret;
1849     }
1850     TRANS_LOGI(TRANS_FILE, "recv file ack response. sessionId=%{public}d, startSeq=%{public}u, seqRet=%{public}u",
1851         sessionId, data->startSeq, data->seqResult);
1852     if (SoftBusMutexLock(&g_sendFileInfoLock.lock) != SOFTBUS_OK) {
1853         SoftBusFree(data);
1854         TRANS_LOGE(TRANS_FILE, "proxy recv ack response lock fail");
1855         return SOFTBUS_LOCK_ERR;
1856     }
1857     SendListenerInfo *item = NULL;
1858     LIST_FOR_EACH_ENTRY(item, &g_sendListenerInfoList, SendListenerInfo, node) {
1859         if (item->sessionId == sessionId) {
1860             if (SetPendingPacketData((uint32_t)sessionId, (uint64_t)(item->waitSeq), &pendData) != SOFTBUS_OK) {
1861                 TRANS_LOGE(TRANS_FILE, "proxy recv ack response set pend packet fail");
1862                 (void)SoftBusMutexUnlock(&g_sendFileInfoLock.lock);
1863                 SoftBusFree(data);
1864                 return SOFTBUS_FILE_ERR;
1865             }
1866             (void)SoftBusMutexUnlock(&g_sendFileInfoLock.lock);
1867             return SOFTBUS_OK;
1868         }
1869     }
1870     (void)SoftBusMutexUnlock(&g_sendFileInfoLock.lock);
1871     TRANS_LOGE(
1872         TRANS_FILE, "recv ack response not find. sessionId=%{public}d, startSeq=%{public}u", sessionId, data->startSeq);
1873     SoftBusFree(data);
1874     return SOFTBUS_NOT_FIND;
1875 }
1876 
CheckFrameLength(int32_t channelId,uint32_t frameLength,int32_t osType,uint32_t * packetSize)1877 static int32_t CheckFrameLength(int32_t channelId, uint32_t frameLength, int32_t osType, uint32_t *packetSize)
1878 {
1879     if (osType != OH_TYPE) {
1880         if (frameLength < sizeof(uint32_t)) {
1881             TRANS_LOGE(TRANS_FILE, "invalid frameLength=%{public}u, channelId=%{public}d", frameLength, channelId);
1882             return SOFTBUS_INVALID_PARAM;
1883         }
1884         return SOFTBUS_OK;
1885     }
1886     int32_t linkType;
1887     int32_t ret = ClientTransProxyGetLinkTypeByChannelId(channelId, &linkType);
1888     if (ret != SOFTBUS_OK) {
1889         TRANS_LOGE(TRANS_FILE, "client trans proxy get info by ChannelId fail");
1890         return ret;
1891     }
1892     *packetSize = linkType == LANE_BR ? PROXY_BR_MAX_PACKET_SIZE : PROXY_BLE_MAX_PACKET_SIZE;
1893     return frameLength > *packetSize ? SOFTBUS_INVALID_PARAM : SOFTBUS_OK;
1894 }
1895 
ProcessRecvFileFrameData(int32_t sessionId,int32_t channelId,const FileFrame * oneFrame)1896 int32_t ProcessRecvFileFrameData(int32_t sessionId, int32_t channelId, const FileFrame *oneFrame)
1897 {
1898     if (oneFrame == NULL) {
1899         TRANS_LOGE(TRANS_FILE, "invalid param.");
1900         return SOFTBUS_INVALID_PARAM;
1901     }
1902     int32_t osType;
1903     uint32_t packetSize;
1904     int32_t ret = ClientTransProxyGetOsTypeByChannelId(channelId, &osType);
1905     ret = CheckFrameLength(channelId, oneFrame->frameLength, osType, &packetSize);
1906     if (ret != SOFTBUS_OK) {
1907         TRANS_LOGE(TRANS_FILE, "frameLength is invalid sessionId=%{public}d, osType=%{public}d", sessionId, osType);
1908         return ret;
1909     }
1910     switch (oneFrame->frameType) {
1911         case TRANS_SESSION_FILE_FIRST_FRAME:
1912             ret = CreateFileFromFrame(sessionId, channelId, oneFrame, osType, packetSize);
1913             TRANS_LOGI(TRANS_FILE, "create file from frame ret=%{public}d, sessionId=%{public}d, osType=%{public}d",
1914                 ret, sessionId, osType);
1915             break;
1916         case TRANS_SESSION_FILE_ONGOINE_FRAME:
1917         case TRANS_SESSION_FILE_ONLYONE_FRAME:
1918         case TRANS_SESSION_FILE_LAST_FRAME:
1919             ret = WriteFrameToFile(sessionId, oneFrame);
1920             if (ret != SOFTBUS_OK) {
1921                 TRANS_LOGE(TRANS_FILE, "write frame fail ret=%{public}d, sessionId=%{public}d, osType=%{public}d",
1922                     ret, sessionId, osType);
1923             }
1924             break;
1925         case TRANS_SESSION_FILE_ACK_REQUEST_SENT:
1926             ret = ProcessFileAckRequest(sessionId, oneFrame);
1927             break;
1928         case TRANS_SESSION_FILE_ACK_RESPONSE_SENT:
1929             ret = ProcessFileAckResponse(sessionId, oneFrame);
1930             break;
1931         case TRANS_SESSION_FILE_CRC_CHECK_FRAME:
1932             ret = ProcessCrcCheckSumData(sessionId, oneFrame);
1933             TRANS_LOGI(TRANS_FILE, "process crc check sum. sessionId=%{public}d, ret=%{public}d", sessionId, ret);
1934             break;
1935         case TRANS_SESSION_FILE_RESULT_FRAME:
1936             ret = ProcessFileTransResult(sessionId, oneFrame);
1937             break;
1938         case TRANS_SESSION_FILE_ALLFILE_SENT:
1939             ret = ProcessFileListData(sessionId, oneFrame);
1940             TRANS_LOGI(TRANS_FILE, "process file list data. sessionId=%{public}d, ret=%{public}d", sessionId, ret);
1941             break;
1942         default:
1943             TRANS_LOGE(TRANS_FILE, "frame type is invalid sessionId=%{public}d", sessionId);
1944             return SOFTBUS_FILE_ERR;
1945     }
1946     return ret;
1947 }
1948 
ProcessFileFrameData(int32_t sessionId,int32_t channelId,const char * data,uint32_t len,int32_t type)1949 int32_t ProcessFileFrameData(int32_t sessionId, int32_t channelId, const char *data, uint32_t len, int32_t type)
1950 {
1951     FileFrame oneFrame;
1952     (void)memset_s(&oneFrame, sizeof(FileFrame), 0, sizeof(FileFrame));
1953     oneFrame.frameType = type;
1954     oneFrame.frameLength = len;
1955     oneFrame.data = (uint8_t *)data;
1956     return ProcessRecvFileFrameData(sessionId, channelId, &oneFrame);
1957 }
1958 
GenerateRemoteFiles(const char * sFileList[],uint32_t fileCnt)1959 static const char **GenerateRemoteFiles(const char *sFileList[], uint32_t fileCnt)
1960 {
1961     const char **files = (const char **)SoftBusCalloc(sizeof(const char *) * fileCnt);
1962     if (files == NULL) {
1963         TRANS_LOGE(TRANS_SDK, "malloc *fileCnt oom");
1964         return NULL;
1965     }
1966     for (uint32_t i = 0; i < fileCnt; i++) {
1967         files[i] = TransGetFileName(sFileList[i]);
1968         if (files[i] == NULL) {
1969             TRANS_LOGE(TRANS_SDK, "GetFileName failed at index=%{public}" PRIu32, i);
1970             SoftBusFree(files);
1971             return NULL;
1972         }
1973     }
1974     return files;
1975 }
1976 
TransProxyChannelSendFile(int32_t channelId,const char * sFileList[],const char * dFileList[],uint32_t fileCnt)1977 int32_t TransProxyChannelSendFile(int32_t channelId, const char *sFileList[], const char *dFileList[], uint32_t fileCnt)
1978 {
1979     if (sFileList == NULL || fileCnt == 0 || fileCnt > MAX_SEND_FILE_NUM) {
1980         TRANS_LOGE(TRANS_SDK, "input para failed! fileCnt=%{public}" PRIu32, fileCnt);
1981         return SOFTBUS_INVALID_PARAM;
1982     }
1983     const char **remoteFiles = NULL;
1984     const char **generatedRemoteFiles = NULL;
1985     if (dFileList == NULL) {
1986         generatedRemoteFiles = GenerateRemoteFiles(sFileList, fileCnt);
1987         if (generatedRemoteFiles == NULL) {
1988             return SOFTBUS_FILE_ERR;
1989         }
1990         remoteFiles = generatedRemoteFiles;
1991     } else {
1992         remoteFiles = dFileList;
1993     }
1994     int32_t ret = ProxyChannelSendFile(channelId, sFileList, remoteFiles, fileCnt);
1995     if (generatedRemoteFiles != NULL) {
1996         SoftBusFree(generatedRemoteFiles);
1997         generatedRemoteFiles = NULL;
1998     }
1999     return ret;
2000 }
2001