1 /*
2  * Copyright (c) 2021-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_file.h"
17 
18 #include <securec.h>
19 #include "client_trans_file_listener.h"
20 #include "client_trans_statistics.h"
21 #include "file_adapter.h"
22 #include "nstackx_dfile.h"
23 #include "softbus_adapter_mem.h"
24 #include "softbus_adapter_thread.h"
25 #include "softbus_def.h"
26 #include "softbus_errcode.h"
27 #include "trans_log.h"
28 #include "client_trans_session_manager.h"
29 
30 #define DEFAULT_KEY_LENGTH 32
31 
32 static const UdpChannelMgrCb *g_udpChannelMgrCb = NULL;
33 
NotifySendResult(int32_t sessionId,DFileMsgType msgType,const DFileMsg * msgData,FileListener * listener)34 static void NotifySendResult(int32_t sessionId, DFileMsgType msgType,
35     const DFileMsg *msgData, FileListener *listener)
36 {
37     if (msgData == NULL || listener == NULL) {
38         return;
39     }
40 
41     switch (msgType) {
42         case DFILE_ON_FILE_SEND_SUCCESS:
43             if (listener->sendListener.OnSendFileFinished != NULL) {
44                 listener->sendListener.OnSendFileFinished(sessionId, msgData->fileList.files[0]);
45             }
46             break;
47         case DFILE_ON_FILE_SEND_FAIL:
48             if (listener->sendListener.OnFileTransError != NULL) {
49                 listener->sendListener.OnFileTransError(sessionId);
50             }
51             break;
52         case DFILE_ON_TRANS_IN_PROGRESS:
53             if (listener->sendListener.OnSendFileProcess != NULL) {
54                 uint64_t bytesUpload = msgData->transferUpdate.bytesTransferred;
55                 uint64_t bytesTotal = msgData->transferUpdate.totalBytes;
56                 listener->sendListener.OnSendFileProcess(sessionId, bytesUpload, bytesTotal);
57             }
58             break;
59         default:
60             break;
61     }
62 }
63 
FillFileStatusList(const DFileMsg * msgData,FileEvent * event)64 static void FillFileStatusList(const DFileMsg *msgData, FileEvent *event)
65 {
66     int32_t fileNum = msgData->clearPolicyFileList.fileNum;
67     if (fileNum <= 0) {
68         TRANS_LOGI(TRANS_SDK, "invalid fileNum.");
69         return;
70     }
71 
72     event->statusList.completedList.files = (char **)SoftBusCalloc(fileNum * sizeof(char *));
73     if (event->statusList.completedList.files == NULL) {
74         TRANS_LOGE(TRANS_SDK, "mem malloc failed");
75         return;
76     }
77     event->statusList.notCompletedList.files = (char **)SoftBusCalloc(fileNum * sizeof(char *));
78     if (event->statusList.notCompletedList.files == NULL) {
79         TRANS_LOGE(TRANS_SDK, "mem malloc failed");
80         return;
81     }
82     event->statusList.notStartedList.files = (char **)SoftBusCalloc(fileNum * sizeof(char *));
83     if (event->statusList.notStartedList.files == NULL) {
84         TRANS_LOGE(TRANS_SDK, "mem malloc failed");
85         return;
86     }
87     int32_t completedIndex = 0;
88     int32_t notCompletedIndex = 0;
89     int32_t notStartedIndex = 0;
90     for (int32_t i = 0; i < fileNum; i++) {
91         if (msgData->clearPolicyFileList.fileInfo[i].stat == FILE_STAT_COMPLETE) {
92             event->statusList.completedList.files[completedIndex] = msgData->clearPolicyFileList.fileInfo[i].file;
93             completedIndex++;
94         } else if (msgData->clearPolicyFileList.fileInfo[i].stat == FILE_STAT_NOT_COMPLETE) {
95             event->statusList.notCompletedList.files[notCompletedIndex] = msgData->clearPolicyFileList.fileInfo[i].file;
96             notCompletedIndex++;
97         } else if (msgData->clearPolicyFileList.fileInfo[i].stat == FILE_STAT_NOT_START) {
98             event->statusList.notStartedList.files[notStartedIndex] = msgData->clearPolicyFileList.fileInfo[i].file;
99             notStartedIndex++;
100         }
101     }
102     event->statusList.completedList.fileCnt = (uint32_t)completedIndex;
103     event->statusList.notCompletedList.fileCnt = (uint32_t)notCompletedIndex;
104     event->statusList.notStartedList.fileCnt = (uint32_t)notStartedIndex;
105     TRANS_LOGI(TRANS_SDK,
106         "status list totalFileNum=%{public}d, completedNum=%{public}d, notCompletedNum=%{public}d, "
107         "notStartedNum=%{public}d",
108         fileNum, event->statusList.completedList.fileCnt, event->statusList.notCompletedList.fileCnt,
109         event->statusList.notStartedList.fileCnt);
110 }
111 
FreeFileStatusList(FileEvent * event)112 static void FreeFileStatusList(FileEvent *event)
113 {
114     if (event == NULL) {
115         return;
116     }
117     if (event->statusList.completedList.files != NULL) {
118         SoftBusFree(event->statusList.completedList.files);
119         event->statusList.completedList.files = NULL;
120     }
121     if (event->statusList.notCompletedList.files != NULL) {
122         SoftBusFree(event->statusList.notCompletedList.files);
123         event->statusList.notCompletedList.files = NULL;
124     }
125     if (event->statusList.notStartedList.files != NULL) {
126         SoftBusFree(event->statusList.notStartedList.files);
127         event->statusList.notStartedList.files = NULL;
128     }
129 }
130 
FillFileEventErrorCode(const DFileMsg * msgData,FileEvent * event)131 static void FillFileEventErrorCode(const DFileMsg *msgData, FileEvent *event)
132 {
133     switch (msgData->errorCode) {
134         case NSTACKX_EOK:
135             event->errorCode = SOFTBUS_OK;
136             break;
137         case NSTACKX_EPERM:
138             event->errorCode = SOFTBUS_TRANS_FILE_PERMISSION_DENIED;
139             break;
140         case NSTACKX_EDQUOT:
141             event->errorCode = SOFTBUS_TRANS_FILE_DISK_QUOTA_EXCEEDED;
142             break;
143         case NSTACKX_ENOMEM:
144             event->errorCode = SOFTBUS_TRANS_FILE_NO_MEMORY;
145             break;
146         case NSTACKX_ENETDOWN:
147             event->errorCode = SOFTBUS_TRANS_FILE_NETWORK_ERROR;
148             break;
149         case NSTACKX_ENOENT:
150             event->errorCode = SOFTBUS_TRANS_FILE_NOT_FOUND;
151             break;
152         case NSTACKX_EEXIST:
153             event->errorCode = SOFTBUS_TRANS_FILE_EXISTED;
154             break;
155         default:
156             event->errorCode = msgData->errorCode;
157             break;
158     }
159 }
160 
NotifySocketSendResult(int32_t socket,DFileMsgType msgType,const DFileMsg * msgData,const FileListener * listener)161 static void NotifySocketSendResult(
162     int32_t socket, DFileMsgType msgType, const DFileMsg *msgData, const FileListener *listener)
163 {
164     FileEvent event;
165     (void)memset_s(&event, sizeof(FileEvent), 0, sizeof(FileEvent));
166     switch (msgType) {
167         case DFILE_ON_TRANS_IN_PROGRESS:
168             event.type = FILE_EVENT_SEND_PROCESS;
169             break;
170         case DFILE_ON_FILE_SEND_SUCCESS:
171             event.type = FILE_EVENT_SEND_FINISH;
172             break;
173         case DFILE_ON_FILE_SEND_FAIL:
174             event.type = FILE_EVENT_SEND_ERROR;
175             break;
176         case DFILE_ON_CLEAR_POLICY_FILE_LIST:
177             event.type = FILE_EVENT_TRANS_STATUS;
178             break;
179         default:
180             return;
181     }
182     TRANS_LOGD(TRANS_SDK, "sendNotify socket=%{public}d type=%{public}d", socket, event.type);
183     event.files = msgData->fileList.files;
184     event.fileCnt = msgData->fileList.fileNum;
185     event.bytesProcessed = msgData->transferUpdate.bytesTransferred;
186     event.bytesTotal = msgData->transferUpdate.totalBytes;
187     event.UpdateRecvPath = NULL;
188     if (event.type == FILE_EVENT_TRANS_STATUS || event.type == FILE_EVENT_SEND_ERROR) {
189         FillFileStatusList(msgData, &event);
190     } else if (event.type == FILE_EVENT_SEND_PROCESS) {
191         event.rate = msgData->rate;
192     }
193     FillFileEventErrorCode(msgData, &event);
194     listener->socketSendCallback(socket, &event);
195     UpdateChannelStatistics(socket, (int64_t)msgData->transferUpdate.totalBytes);
196     FreeFileStatusList(&event);
197 }
198 
IsParmasValid(DFileMsgType msgType,const DFileMsg * msgData)199 static bool IsParmasValid(DFileMsgType msgType, const DFileMsg *msgData)
200 {
201     if (msgData == NULL || msgType == DFILE_ON_BIND || msgType == DFILE_ON_SESSION_IN_PROGRESS ||
202         msgType == DFILE_ON_SESSION_TRANSFER_RATE) {
203         TRANS_LOGE(TRANS_SDK, "param invalid");
204         return false;
205     }
206     return true;
207 }
208 
FileSendErrorEvent(UdpChannel * udpChannel,FileListener * fileListener,const DFileMsg * msgData,DFileMsgType msgType,int32_t sessionId)209 static void FileSendErrorEvent(UdpChannel *udpChannel, FileListener *fileListener, const DFileMsg *msgData,
210     DFileMsgType msgType, int32_t sessionId)
211 {
212     if (fileListener->socketSendCallback != NULL) {
213         FileEvent event;
214         (void)memset_s(&event, sizeof(FileEvent), 0, sizeof(FileEvent));
215         event.type = FILE_EVENT_SEND_ERROR;
216         FillFileStatusList(msgData, &event);
217         FillFileEventErrorCode(msgData, &event);
218         fileListener->socketSendCallback(sessionId, &event);
219         FreeFileStatusList(&event);
220     } else if (fileListener->sendListener.OnFileTransError != NULL) {
221         fileListener->sendListener.OnFileTransError(sessionId);
222     }
223     TRANS_LOGI(TRANS_SDK, "OnFile error. msgType=%{public}d", msgType);
224     TransOnUdpChannelClosed(udpChannel->channelId, SHUTDOWN_REASON_SEND_FILE_ERR);
225     return;
226 }
227 
FileSendListener(int32_t dfileId,DFileMsgType msgType,const DFileMsg * msgData)228 static void FileSendListener(int32_t dfileId, DFileMsgType msgType, const DFileMsg *msgData)
229 {
230     if (!IsParmasValid(msgType, msgData)) {
231         TRANS_LOGE(TRANS_SDK, "Invalid parameter, dfileId=%{public}d, type=%{public}d", dfileId, msgType);
232         return;
233     }
234     UdpChannel udpChannel;
235     (void)memset_s(&udpChannel, sizeof(UdpChannel), 0, sizeof(UdpChannel));
236     if (TransGetUdpChannelByFileId(dfileId, &udpChannel) != SOFTBUS_OK) {
237         TRANS_LOGE(TRANS_SDK, "trans get udp channel failed, dfileId=%{public}d, type=%{public}d", dfileId, msgType);
238         return;
239     }
240     if (msgType == DFILE_ON_CONNECT_SUCCESS) {
241         g_udpChannelMgrCb->OnUdpChannelOpened(udpChannel.channelId);
242         TRANS_LOGE(TRANS_SDK, "msgType failed, dfileId=%{public}d, type=%{public}d", dfileId, msgType);
243         return;
244     }
245 
246     FileListener fileListener;
247     (void)memset_s(&fileListener, sizeof(FileListener), 0, sizeof(FileListener));
248     if (TransGetFileListener(udpChannel.info.mySessionName, &fileListener) != SOFTBUS_OK) {
249         TRANS_LOGE(TRANS_SDK, "TransGetFileListener failed, dfileId=%{public}d, type=%{public}d", dfileId, msgType);
250         return;
251     }
252     if (msgType == DFILE_ON_CLEAR_POLICY_FILE_LIST) {
253         if (fileListener.socketSendCallback != NULL) {
254             NotifySocketSendResult(udpChannel.sessionId, msgType, msgData, &fileListener);
255         }
256         TRANS_LOGI(TRANS_SDK, "notify DFILE_ON_CLEAR_POLICY_FILE_LIST success.");
257         return;
258     }
259 
260     int32_t sessionId = -1;
261     if (g_udpChannelMgrCb->OnFileGetSessionId(udpChannel.channelId, &sessionId) != SOFTBUS_OK) {
262         TRANS_LOGE(TRANS_SDK, "get sessionId failed, dfileId=%{public}d, type=%{public}d", dfileId, msgType);
263         return;
264     }
265 
266     if (msgType == DFILE_ON_CONNECT_FAIL || msgType == DFILE_ON_FATAL_ERROR) {
267         TRANS_LOGE(TRANS_SDK, "FileSendErrorEvent, dfileId=%{public}d, type=%{public}d", dfileId, msgType);
268         FileSendErrorEvent(&udpChannel, &fileListener, msgData, msgType, sessionId);
269         return;
270     }
271     (void)g_udpChannelMgrCb->OnIdleTimeoutReset(sessionId);
272     if (fileListener.socketSendCallback != NULL) {
273         NotifySocketSendResult(sessionId, msgType, msgData, &fileListener);
274     } else {
275         NotifySendResult(sessionId, msgType, msgData, &fileListener);
276     }
277 }
278 
NotifyRecvResult(int32_t sessionId,DFileMsgType msgType,const DFileMsg * msgData,FileListener * listener)279 static void NotifyRecvResult(int32_t sessionId, DFileMsgType msgType, const DFileMsg *msgData,
280     FileListener *listener)
281 {
282     if (msgData == NULL || listener == NULL) {
283         TRANS_LOGE(TRANS_SDK, "param invalid");
284         return;
285     }
286 
287     const char *firstFile = msgData->fileList.files[0];
288     uint32_t fileNum = msgData->fileList.fileNum;
289     switch (msgType) {
290         case DFILE_ON_FILE_LIST_RECEIVED:
291             if (listener->recvListener.OnReceiveFileStarted != NULL) {
292                 listener->recvListener.OnReceiveFileStarted(sessionId, firstFile, fileNum);
293             }
294             break;
295         case DFILE_ON_FILE_RECEIVE_SUCCESS:
296             if (listener->recvListener.OnReceiveFileFinished != NULL) {
297                 listener->recvListener.OnReceiveFileFinished(sessionId, firstFile, fileNum);
298             }
299             break;
300         case DFILE_ON_FILE_RECEIVE_FAIL:
301             if (listener->recvListener.OnFileTransError != NULL) {
302                 listener->recvListener.OnFileTransError(sessionId);
303             }
304             break;
305         case DFILE_ON_TRANS_IN_PROGRESS:
306             if (listener->recvListener.OnReceiveFileProcess != NULL) {
307                 uint64_t bytesUpload = msgData->transferUpdate.bytesTransferred;
308                 uint64_t bytesTotal = msgData->transferUpdate.totalBytes;
309                 listener->recvListener.OnReceiveFileProcess(sessionId, firstFile, bytesUpload, bytesTotal);
310             }
311             break;
312         default:
313             break;
314     }
315 }
316 
NotifySocketRecvResult(int32_t socket,DFileMsgType msgType,const DFileMsg * msgData,const FileListener * listener)317 static void NotifySocketRecvResult(
318     int32_t socket, DFileMsgType msgType, const DFileMsg *msgData, const FileListener *listener)
319 {
320     FileEvent event;
321     (void)memset_s(&event, sizeof(FileEvent), 0, sizeof(FileEvent));
322     switch (msgType) {
323         case DFILE_ON_FILE_LIST_RECEIVED:
324             event.type = FILE_EVENT_RECV_START;
325             break;
326         case DFILE_ON_TRANS_IN_PROGRESS:
327             event.type = FILE_EVENT_RECV_PROCESS;
328             break;
329         case DFILE_ON_FILE_RECEIVE_SUCCESS:
330             event.type = FILE_EVENT_RECV_FINISH;
331             break;
332         case DFILE_ON_FILE_RECEIVE_FAIL:
333             event.type = FILE_EVENT_RECV_ERROR;
334             break;
335         case DFILE_ON_CLEAR_POLICY_FILE_LIST:
336             event.type = FILE_EVENT_TRANS_STATUS;
337             break;
338         default:
339             return;
340     }
341     TRANS_LOGD(TRANS_SDK, "recvNotify socket=%{public}d type=%{public}d", socket, event.type);
342     event.files = msgData->fileList.files;
343     event.fileCnt = msgData->fileList.fileNum;
344     event.bytesProcessed = msgData->transferUpdate.bytesTransferred;
345     event.bytesTotal = msgData->transferUpdate.totalBytes;
346     event.UpdateRecvPath = NULL;
347     if (event.type == FILE_EVENT_TRANS_STATUS || event.type == FILE_EVENT_RECV_ERROR) {
348         FillFileStatusList(msgData, &event);
349     } else if (event.type == FILE_EVENT_RECV_PROCESS) {
350         event.rate = msgData->rate;
351     }
352     FillFileEventErrorCode(msgData, &event);
353     listener->socketRecvCallback(socket, &event);
354     FreeFileStatusList(&event);
355 }
356 
FileRecvErrorEvent(UdpChannel * udpChannel,FileListener * fileListener,const DFileMsg * msgData,DFileMsgType msgType,int32_t sessionId)357 static void FileRecvErrorEvent(UdpChannel *udpChannel, FileListener *fileListener, const DFileMsg *msgData,
358     DFileMsgType msgType, int32_t sessionId)
359 {
360     if (fileListener->socketRecvCallback != NULL) {
361         FileEvent event;
362         (void)memset_s(&event, sizeof(FileEvent), 0, sizeof(FileEvent));
363         event.type = FILE_EVENT_RECV_ERROR;
364         FillFileStatusList(msgData, &event);
365         FillFileEventErrorCode(msgData, &event);
366         fileListener->socketRecvCallback(sessionId, &event);
367         FreeFileStatusList(&event);
368     } else if (fileListener->recvListener.OnFileTransError != NULL) {
369         fileListener->recvListener.OnFileTransError(sessionId);
370     }
371     TransOnUdpChannelClosed(udpChannel->channelId, SHUTDOWN_REASON_RECV_FILE_ERR);
372     return;
373 }
374 
FileReceiveListener(int32_t dfileId,DFileMsgType msgType,const DFileMsg * msgData)375 static void FileReceiveListener(int32_t dfileId, DFileMsgType msgType, const DFileMsg *msgData)
376 {
377     TRANS_LOGD(TRANS_FILE, "recv dfileId=%{public}d, type=%{public}d", dfileId, msgType);
378     if (!IsParmasValid(msgType, msgData)) {
379         return;
380     }
381     UdpChannel udpChannel;
382     (void)memset_s(&udpChannel, sizeof(UdpChannel), 0, sizeof(UdpChannel));
383     if (TransGetUdpChannelByFileId(dfileId, &udpChannel) != SOFTBUS_OK) {
384         TRANS_LOGE(TRANS_SDK, "get udp channel failed");
385         return;
386     }
387 
388     FileListener fileListener;
389     (void)memset_s(&fileListener, sizeof(FileListener), 0, sizeof(FileListener));
390     if (TransGetFileListener(udpChannel.info.mySessionName, &fileListener) != SOFTBUS_OK) {
391         TRANS_LOGE(TRANS_SDK, "get listener failed");
392         return;
393     }
394     if (msgType == DFILE_ON_CLEAR_POLICY_FILE_LIST) {
395         if (fileListener.socketRecvCallback != NULL) {
396             NotifySocketRecvResult(udpChannel.sessionId, msgType, msgData, &fileListener);
397         }
398         TRANS_LOGI(TRANS_SDK, "notify DFILE_ON_CLEAR_POLICY_FILE_LIST success.");
399         return;
400     }
401     int32_t sessionId = -1;
402     if (g_udpChannelMgrCb->OnFileGetSessionId(udpChannel.channelId, &sessionId) != SOFTBUS_OK) {
403         TRANS_LOGE(TRANS_SDK, "get sessionId failed");
404         return;
405     }
406     if (msgType == DFILE_ON_CONNECT_FAIL || msgType == DFILE_ON_FATAL_ERROR) {
407         FileRecvErrorEvent(&udpChannel, &fileListener, msgData, msgType, sessionId);
408         return;
409     }
410     (void)g_udpChannelMgrCb->OnIdleTimeoutReset(sessionId);
411     if (fileListener.socketRecvCallback != NULL) {
412         NotifySocketRecvResult(sessionId, msgType, msgData, &fileListener);
413     } else {
414         NotifyRecvResult(sessionId, msgType, msgData, &fileListener);
415     }
416 }
417 
UpdateFileRecvPath(int32_t channelId,FileListener * fileListener,int32_t fileSession)418 static int32_t UpdateFileRecvPath(int32_t channelId, FileListener *fileListener, int32_t fileSession)
419 {
420     int32_t sessionId = -1;
421     int32_t ret = g_udpChannelMgrCb->OnFileGetSessionId(channelId, &sessionId);
422     TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_SDK, "get sessionId by channelId failed");
423 
424     if (fileListener->socketRecvCallback != NULL) {
425         FileEvent event;
426         (void)memset_s(&event, sizeof(FileEvent), 0, sizeof(FileEvent));
427         event.type = FILE_EVENT_RECV_UPDATE_PATH;
428         fileListener->socketRecvCallback(sessionId, &event);
429         if (event.UpdateRecvPath == NULL) {
430             TRANS_LOGE(TRANS_SDK, "UpdateRecvPath is null");
431             return SOFTBUS_FILE_ERR;
432         }
433 
434         const char *rootDir = event.UpdateRecvPath();
435         char *absPath = realpath(rootDir, NULL);
436         if (absPath == NULL) {
437             TRANS_LOGE(TRANS_SDK,
438                 "rootDir not exist, rootDir=%{private}s, errno=%{public}d.",
439                 (rootDir == NULL ? "null" : rootDir), errno);
440             return SOFTBUS_FILE_ERR;
441         }
442 
443         if (strcpy_s(fileListener->rootDir, FILE_RECV_ROOT_DIR_SIZE_MAX, absPath) != EOK) {
444             TRANS_LOGE(TRANS_SDK, "strcpy rootDir failed");
445             SoftBusFree(absPath);
446             return SOFTBUS_STRCPY_ERR;
447         }
448         SoftBusFree(absPath);
449     }
450 
451     if (NSTACKX_DFileSetStoragePath(fileSession, fileListener->rootDir) != SOFTBUS_OK) {
452         NSTACKX_DFileClose(fileSession);
453         TRANS_LOGE(TRANS_SDK, "set storage path failed. rootDir=%{private}s", fileListener->rootDir);
454         return SOFTBUS_FILE_ERR;
455     }
456     return SOFTBUS_OK;
457 }
458 
RenameHook(DFileRenamePara * renamePara)459 static void RenameHook(DFileRenamePara *renamePara)
460 {
461     if (renamePara == NULL) {
462         TRANS_LOGE(TRANS_SDK, "invalid param renamePara.");
463         return;
464     }
465     (void)strcpy_s(renamePara->newFileName, NSTACKX_MAX_REMOTE_PATH_LEN, renamePara->initFileName);
466     TRANS_LOGD(TRANS_FILE, "default rename hook.");
467 }
468 
TransOnFileChannelOpened(const char * sessionName,const ChannelInfo * channel,int32_t * filePort)469 int32_t TransOnFileChannelOpened(const char *sessionName, const ChannelInfo *channel, int32_t *filePort)
470 {
471     if (channel == NULL || filePort == NULL) {
472         TRANS_LOGW(TRANS_FILE, "invalid param.");
473         return SOFTBUS_INVALID_PARAM;
474     }
475     int32_t fileSession;
476 
477     uint32_t capabilityValue = channel->isUdpFile ? NSTACKX_WLAN_CAT_DIRECT : NSTACKX_WLAN_CAT_TCP;
478     (void)NSTACKX_DFileSetCapabilities(NSTACKX_CAPS_UDP_GSO | NSTACKX_CAPS_WLAN_CATAGORY, capabilityValue);
479     if (channel->isServer) {
480         FileListener fileListener;
481         (void)memset_s(&fileListener, sizeof(FileListener), 0, sizeof(FileListener));
482         int32_t ret = TransGetFileListener(sessionName, &fileListener);
483         TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_FILE, "get file listener failed");
484 
485         fileSession = StartNStackXDFileServer(channel->myIp, (uint8_t *)channel->sessionKey,
486             DEFAULT_KEY_LENGTH, FileReceiveListener, filePort);
487         if (fileSession < 0) {
488             TRANS_LOGE(TRANS_FILE, "start file channel as server failed");
489             return SOFTBUS_FILE_ERR;
490         }
491         ret = g_udpChannelMgrCb->OnUdpChannelOpened(channel->channelId);
492         if (ret != SOFTBUS_OK) {
493             TRANS_LOGE(TRANS_FILE, "udp channel open failed.");
494             NSTACKX_DFileClose(fileSession);
495             *filePort = 0;
496             return ret;
497         }
498         if (UpdateFileRecvPath(channel->channelId, &fileListener, fileSession)) {
499             TRANS_LOGE(TRANS_FILE, "update receive file path failed");
500             NSTACKX_DFileClose(fileSession);
501             *filePort = 0;
502             return SOFTBUS_FILE_ERR;
503         }
504         if (NSTACKX_DFileSetRenameHook(fileSession, RenameHook) != NSTACKX_EOK) {
505             TRANS_LOGE(TRANS_FILE, "set rename hook failed, fileSession=%{public}d, channelId=%{public}d", fileSession,
506                 channel->channelId);
507         }
508     } else {
509         fileSession = StartNStackXDFileClient(channel->peerIp, channel->peerPort,
510             (uint8_t *)channel->sessionKey, DEFAULT_KEY_LENGTH, FileSendListener);
511         if (fileSession < 0) {
512             TRANS_LOGE(TRANS_FILE, "start file channel as client failed");
513             return SOFTBUS_FILE_ERR;
514         }
515     }
516     return fileSession;
517 }
518 
TransCloseDFileProcTask(void * args)519 static void *TransCloseDFileProcTask(void *args)
520 {
521     int32_t *dfileId = (int32_t *)args;
522     TRANS_LOGI(TRANS_FILE, "rsync close dfileId=%{public}d.", *dfileId);
523     NSTACKX_DFileClose(*dfileId);
524     SoftBusFree(dfileId);
525     return NULL;
526 }
527 
TransCloseFileChannel(int32_t dfileId)528 void TransCloseFileChannel(int32_t dfileId)
529 {
530     TRANS_LOGI(TRANS_FILE, "start close file channel, dfileId=%{public}d.", dfileId);
531     SoftBusThreadAttr threadAttr;
532     SoftBusThread tid;
533     int32_t ret = SoftBusThreadAttrInit(&threadAttr);
534     if (ret != SOFTBUS_OK) {
535         TRANS_LOGE(TRANS_FILE, "thread attr init failed, ret=%{public}d.", ret);
536         return;
537     }
538     int32_t *args = (int32_t *)SoftBusCalloc(sizeof(int32_t));
539     if (args == NULL) {
540         TRANS_LOGE(TRANS_FILE, "close dfile calloc failed. dfileId=%{public}d", dfileId);
541         return;
542     }
543     *args = dfileId;
544     threadAttr.detachState = SOFTBUS_THREAD_DETACH;
545     ret = SoftBusThreadCreate(&tid, &threadAttr, TransCloseDFileProcTask, args);
546     if (ret != SOFTBUS_OK) {
547         TRANS_LOGE(TRANS_FILE, "create closed file thread failed, ret=%{public}d.", ret);
548         SoftBusFree(args);
549         return;
550     }
551 }
552 
RegisterFileCb(const UdpChannelMgrCb * fileCb)553 void RegisterFileCb(const UdpChannelMgrCb *fileCb)
554 {
555     if (fileCb == NULL) {
556         TRANS_LOGE(TRANS_FILE, "param invalid");
557         g_udpChannelMgrCb = NULL;
558         return;
559     }
560     if (g_udpChannelMgrCb != NULL) {
561         TRANS_LOGE(TRANS_FILE, "g_udpChannelMgrCb is null");
562         return;
563     }
564     g_udpChannelMgrCb = fileCb;
565 }
566 
TransSendFile(int32_t dfileId,const char * sFileList[],const char * dFileList[],uint32_t fileCnt)567 int32_t TransSendFile(int32_t dfileId, const char *sFileList[], const char *dFileList[], uint32_t fileCnt)
568 {
569     if (dFileList == NULL) {
570         return NSTACKX_DFileSendFiles(dfileId, sFileList, fileCnt, NULL);
571     }
572     return NSTACKX_DFileSendFilesWithRemotePath(dfileId, sFileList, dFileList, fileCnt, NULL);
573 }
574 
NotifyTransLimitChanged(int32_t channelId,uint8_t tos)575 int32_t NotifyTransLimitChanged(int32_t channelId, uint8_t tos)
576 {
577     char sessionName[SESSION_NAME_SIZE_MAX + 1] = { 0 };
578     int32_t ret = ClientGetSessionNameByChannelId(channelId, CHANNEL_TYPE_UDP, sessionName, SESSION_NAME_SIZE_MAX);
579     if (ret != SOFTBUS_OK) {
580         TRANS_LOGE(TRANS_FILE, "failed to get sessionName, channelId=%{public}d", channelId);
581         return ret;
582     }
583     FileListener fileListener;
584     (void)memset_s(&fileListener, sizeof(FileListener), 0, sizeof(FileListener));
585     ret = TransGetFileListener(sessionName, &fileListener);
586     if (ret != SOFTBUS_OK) {
587         TRANS_LOGE(TRANS_FILE, "get file listener failed");
588         return ret;
589     }
590     int32_t sessionId = INVALID_SESSION_ID;
591     ret = ClientGetSessionIdByChannelId(channelId, CHANNEL_TYPE_UDP, &sessionId);
592     if (ret != SOFTBUS_OK) {
593         TRANS_LOGE(TRANS_FILE, "get file listener failed");
594         return ret;
595     }
596     if (fileListener.socketSendCallback != NULL) {
597         FileEvent event;
598         (void)memset_s(&event, sizeof(FileEvent), 0, sizeof(FileEvent));
599         event.type = FILE_EVENT_TRANS_LIMIT_CHANGED;
600         if (tos == FILE_PRIORITY_BE) {
601             event.filePriority = FILE_PRIORITY_TYPE_DEFAUT;
602         } else {
603             event.filePriority = FILE_PRIORITY_TYPE_LOW;
604         }
605         fileListener.socketSendCallback(sessionId, &event);
606         TRANS_LOGI(TRANS_FILE, "notify trans limit changed, file priority=%{public}d", event.filePriority);
607     }
608     return ret;
609 }
610