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