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 }