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