• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "file_adapter.h"
21 #include "nstackx_dfile.h"
22 #include "softbus_adapter_mem.h"
23 #include "softbus_adapter_thread.h"
24 #include "softbus_def.h"
25 #include "softbus_errcode.h"
26 #include "softbus_log.h"
27 #include "softbus_utils.h"
28 
29 #define DEFAULT_KEY_LENGTH 32
30 
31 static const UdpChannelMgrCb *g_udpChannelMgrCb = NULL;
32 
NotifySendResult(int32_t sessionId,DFileMsgType msgType,const DFileMsg * msgData,FileListener * listener)33 NO_SANITIZE("cfi") static void NotifySendResult(int32_t sessionId, DFileMsgType msgType,
34     const DFileMsg *msgData, FileListener *listener)
35 {
36     if (msgData == NULL || listener == NULL) {
37         return;
38     }
39 
40     switch (msgType) {
41         case DFILE_ON_FILE_SEND_SUCCESS:
42             if (listener->sendListener.OnSendFileFinished != NULL) {
43                 listener->sendListener.OnSendFileFinished(sessionId, msgData->fileList.files[0]);
44             }
45             break;
46         case DFILE_ON_FILE_SEND_FAIL:
47             if (listener->sendListener.OnFileTransError != NULL) {
48                 listener->sendListener.OnFileTransError(sessionId);
49             }
50             break;
51         case DFILE_ON_TRANS_IN_PROGRESS:
52             if (listener->sendListener.OnSendFileProcess != NULL) {
53                 uint64_t bytesUpload = msgData->transferUpdate.bytesTransferred;
54                 uint64_t bytesTotal = msgData->transferUpdate.totalBytes;
55                 listener->sendListener.OnSendFileProcess(sessionId, bytesUpload, bytesTotal);
56             }
57             break;
58         default:
59             break;
60     }
61 }
62 
FileSendListener(int32_t dfileId,DFileMsgType msgType,const DFileMsg * msgData)63 NO_SANITIZE("cfi") static void FileSendListener(int32_t dfileId, DFileMsgType msgType, const DFileMsg *msgData)
64 {
65     SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_ERROR, "send dfileId=%d type=%d", dfileId, msgType);
66     if (msgData == NULL || msgType == DFILE_ON_BIND || msgType == DFILE_ON_SESSION_IN_PROGRESS ||
67         msgType == DFILE_ON_SESSION_TRANSFER_RATE) {
68         return;
69     }
70     UdpChannel udpChannel;
71     (void)memset_s(&udpChannel, sizeof(UdpChannel), 0, sizeof(UdpChannel));
72     if (TransGetUdpChannelByFileId(dfileId, &udpChannel) != SOFTBUS_OK) {
73         return;
74     }
75     if (msgType == DFILE_ON_CONNECT_SUCCESS) {
76         g_udpChannelMgrCb->OnUdpChannelOpened(udpChannel.channelId);
77         return;
78     }
79 
80     FileListener fileListener;
81     (void)memset_s(&fileListener, sizeof(FileListener), 0, sizeof(FileListener));
82     if (TransGetFileListener(udpChannel.info.mySessionName, &fileListener) != SOFTBUS_OK) {
83         return;
84     }
85 
86     int32_t sessionId = -1;
87     if (g_udpChannelMgrCb->OnFileGetSessionId(udpChannel.channelId, &sessionId) != SOFTBUS_OK) {
88         return;
89     }
90 
91     if (msgType == DFILE_ON_CONNECT_FAIL || msgType == DFILE_ON_FATAL_ERROR) {
92         if (fileListener.sendListener.OnFileTransError != NULL) {
93                 fileListener.sendListener.OnFileTransError(sessionId);
94             }
95         TransOnUdpChannelClosed(udpChannel.channelId);
96         return;
97     }
98 
99     NotifySendResult(sessionId, msgType, msgData, &fileListener);
100     return;
101 }
102 
NotifyRecvResult(int32_t sessionId,DFileMsgType msgType,const DFileMsg * msgData,FileListener * listener)103 NO_SANITIZE("cfi") static void NotifyRecvResult(int32_t sessionId, DFileMsgType msgType, const DFileMsg *msgData,
104     FileListener *listener)
105 {
106     if (msgData == NULL || listener == NULL) {
107         return;
108     }
109 
110     const char *firstFile = msgData->fileList.files[0];
111     uint32_t fileNum = msgData->fileList.fileNum;
112     switch (msgType) {
113         case DFILE_ON_FILE_LIST_RECEIVED:
114             if (listener->recvListener.OnReceiveFileStarted != NULL) {
115                 listener->recvListener.OnReceiveFileStarted(sessionId, firstFile, fileNum);
116             }
117             break;
118         case DFILE_ON_FILE_RECEIVE_SUCCESS:
119             if (listener->recvListener.OnReceiveFileFinished != NULL) {
120                 listener->recvListener.OnReceiveFileFinished(sessionId, firstFile, fileNum);
121             }
122             break;
123         case DFILE_ON_FILE_RECEIVE_FAIL:
124             if (listener->recvListener.OnFileTransError != NULL) {
125                 listener->recvListener.OnFileTransError(sessionId);
126             }
127             break;
128         case DFILE_ON_TRANS_IN_PROGRESS:
129             if (listener->recvListener.OnReceiveFileProcess != NULL) {
130                 uint64_t bytesUpload = msgData->transferUpdate.bytesTransferred;
131                 uint64_t bytesTotal = msgData->transferUpdate.totalBytes;
132                 listener->recvListener.OnReceiveFileProcess(sessionId, firstFile, bytesUpload, bytesTotal);
133             }
134             break;
135         default:
136             break;
137     }
138 }
139 
FileReceiveListener(int32_t dfileId,DFileMsgType msgType,const DFileMsg * msgData)140 NO_SANITIZE("cfi") static void FileReceiveListener(int32_t dfileId, DFileMsgType msgType, const DFileMsg *msgData)
141 {
142     SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_ERROR, "recv dfileId=%d type=%d", dfileId, msgType);
143     if (msgData == NULL || msgType == DFILE_ON_BIND || msgType == DFILE_ON_SESSION_IN_PROGRESS ||
144         msgType == DFILE_ON_SESSION_TRANSFER_RATE) {
145         return;
146     }
147     UdpChannel udpChannel;
148     (void)memset_s(&udpChannel, sizeof(UdpChannel), 0, sizeof(UdpChannel));
149     if (TransGetUdpChannelByFileId(dfileId, &udpChannel) != SOFTBUS_OK) {
150         return;
151     }
152 
153     FileListener fileListener;
154     (void)memset_s(&fileListener, sizeof(FileListener), 0, sizeof(FileListener));
155     if (TransGetFileListener(udpChannel.info.mySessionName, &fileListener) != SOFTBUS_OK) {
156         return;
157     }
158     int32_t sessionId = -1;
159     if (g_udpChannelMgrCb->OnFileGetSessionId(udpChannel.channelId, &sessionId) != SOFTBUS_OK) {
160         return;
161     }
162     if (msgType == DFILE_ON_CONNECT_FAIL || msgType == DFILE_ON_FATAL_ERROR) {
163         if (fileListener.recvListener.OnFileTransError != NULL) {
164                 fileListener.recvListener.OnFileTransError(sessionId);
165             }
166         TransOnUdpChannelClosed(udpChannel.channelId);
167         return;
168     }
169 
170     NotifyRecvResult(sessionId, msgType, msgData, &fileListener);
171     return;
172 }
173 
TransOnFileChannelOpened(const char * sessionName,const ChannelInfo * channel,int32_t * filePort)174 int32_t TransOnFileChannelOpened(const char *sessionName, const ChannelInfo *channel, int32_t *filePort)
175 {
176     if (channel == NULL || filePort == NULL) {
177         SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_ERROR, "%s:invalid param.", __func__);
178         return SOFTBUS_INVALID_PARAM;
179     }
180     int32_t fileSession;
181 
182     uint32_t capabilityValue = channel->isUdpFile ? NSTACKX_WLAN_CAT_DIRECT : NSTACKX_WLAN_CAT_TCP;
183     (void)NSTACKX_DFileSetCapabilities(NSTACKX_CAPS_UDP_GSO | NSTACKX_CAPS_WLAN_CATAGORY, capabilityValue);
184     if (channel->isServer) {
185         FileListener fileListener;
186         (void)memset_s(&fileListener, sizeof(FileListener), 0, sizeof(FileListener));
187         if (TransGetFileListener(sessionName, &fileListener) != SOFTBUS_OK) {
188             SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_ERROR, "get file listener failed");
189             return SOFTBUS_ERR;
190         }
191         fileSession = StartNStackXDFileServer(channel->myIp, (uint8_t *)channel->sessionKey,
192             DEFAULT_KEY_LENGTH, FileReceiveListener, filePort);
193         if (fileSession < 0) {
194             SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_ERROR, "start file channel as server failed");
195             return SOFTBUS_ERR;
196         }
197         if (NSTACKX_DFileSetStoragePath(fileSession, fileListener.rootDir) != SOFTBUS_OK) {
198             NSTACKX_DFileClose(fileSession);
199             SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_ERROR, "set storage path[%s] failed", fileListener.rootDir);
200             return SOFTBUS_ERR;
201         }
202         g_udpChannelMgrCb->OnUdpChannelOpened(channel->channelId);
203     } else {
204         fileSession = StartNStackXDFileClient(channel->peerIp, channel->peerPort,
205             (uint8_t *)channel->sessionKey, DEFAULT_KEY_LENGTH, FileSendListener);
206         if (fileSession < 0) {
207             SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_ERROR, "start file channel as client failed");
208             return SOFTBUS_ERR;
209         }
210     }
211     return fileSession;
212 }
213 
TransCloseDFileProcTask(void * args)214 static void *TransCloseDFileProcTask(void *args)
215 {
216     int32_t *dfileId = (int32_t *)args;
217     SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_INFO, "rsync close dfile=%d.", *dfileId);
218     NSTACKX_DFileClose(*dfileId);
219     SoftBusFree(dfileId);
220     return NULL;
221 }
222 
TransCloseFileChannel(int32_t dfileId)223 void TransCloseFileChannel(int32_t dfileId)
224 {
225     SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_INFO, "start close file channel, dfile=%d.", dfileId);
226     SoftBusThreadAttr threadAttr;
227     SoftBusThread tid;
228     int32_t ret = SoftBusThreadAttrInit(&threadAttr);
229     if (ret != SOFTBUS_OK) {
230         SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_ERROR, "thread attr init failed, ret=%d.", ret);
231         return;
232     }
233     int32_t *args = (int32_t *)SoftBusCalloc(sizeof(int32_t));
234     if (args == NULL) {
235         SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_ERROR, "close dfile %d calloc failed.", dfileId);
236         return;
237     }
238     *args = dfileId;
239     threadAttr.detachState = SOFTBUS_THREAD_DETACH;
240     ret = SoftBusThreadCreate(&tid, &threadAttr, TransCloseDFileProcTask, args);
241     if (ret != SOFTBUS_OK) {
242         SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_ERROR, "create closedfile thread failed, ret=%d.", ret);
243         SoftBusFree(args);
244         return;
245     }
246 }
247 
RegisterFileCb(const UdpChannelMgrCb * fileCb)248 void RegisterFileCb(const UdpChannelMgrCb *fileCb)
249 {
250     if (fileCb == NULL) {
251         g_udpChannelMgrCb = NULL;
252         return;
253     }
254     if (g_udpChannelMgrCb != NULL) {
255         return;
256     }
257     g_udpChannelMgrCb = fileCb;
258 }
259 
TransSendFile(int32_t dfileId,const char * sFileList[],const char * dFileList[],uint32_t fileCnt)260 int32_t TransSendFile(int32_t dfileId, const char *sFileList[], const char *dFileList[], uint32_t fileCnt)
261 {
262     if (dFileList == NULL) {
263         return NSTACKX_DFileSendFiles(dfileId, sFileList, fileCnt, NULL);
264     }
265     return NSTACKX_DFileSendFilesWithRemotePath(dfileId, sFileList, dFileList, fileCnt, NULL);
266 }