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