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