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 "file_adapter.h"
17
18 #include <securec.h>
19 #include <unistd.h>
20
21 #include "client_trans_tcp_direct_listener.h"
22 #include "softbus_adapter_errcode.h"
23 #include "softbus_adapter_socket.h"
24 #include "softbus_conn_common.h"
25 #include "softbus_error_code.h"
26 #include "softbus_socket.h"
27 #include "trans_log.h"
28
SetReuseAddr(int fd,int on)29 static int SetReuseAddr(int fd, int on)
30 {
31 int rc = SoftBusSocketSetOpt(fd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_REUSEADDR, &on, sizeof(on));
32 if (rc != SOFTBUS_OK) {
33 TRANS_LOGE(TRANS_FILE, "set SO_REUSEADDR error. fd=%{public}d", fd);
34 return SOFTBUS_INVALID_FD;
35 }
36 return SOFTBUS_OK;
37 }
38
SetReusePort(int fd,int on)39 static int SetReusePort(int fd, int on)
40 {
41 int rc = SoftBusSocketSetOpt(fd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_REUSEPORT, &on, sizeof(on));
42 if (rc != SOFTBUS_OK) {
43 TRANS_LOGE(TRANS_FILE, "set SO_REUSEPORT error. fd=%{public}d", fd);
44 return SOFTBUS_INVALID_FD;
45 }
46 return SOFTBUS_OK;
47 }
48
CreateServerSocketByIpv4(const char * ip,int port)49 static int CreateServerSocketByIpv4(const char *ip, int port)
50 {
51 SoftBusSockAddrIn addr;
52 int32_t ret = Ipv4AddrToAddrIn(&addr, ip, port);
53 if (ret != SOFTBUS_OK) {
54 TRANS_LOGE(TRANS_FILE, "init addr error, ret=%{public}d", ret);
55 return ret;
56 }
57
58 int fd;
59
60 ret = SoftBusSocketCreate(SOFTBUS_AF_INET, SOFTBUS_SOCK_STREAM | SOFTBUS_SOCK_NONBLOCK |
61 SOFTBUS_SOCK_CLOEXEC, 0, &fd);
62 if (ret != SOFTBUS_OK) {
63 TRANS_LOGE(TRANS_FILE, "create socket error, ret=%{public}d.", ret);
64 return ret;
65 }
66
67 ret = SetReuseAddr(fd, 1);
68 if (ret != SOFTBUS_OK) {
69 TRANS_LOGE(TRANS_FILE, "reuse addr error, ret=%{public}d.", ret);
70 TransTdcReleaseFd(fd);
71 return ret;
72 }
73
74 ret = SetReusePort(fd, 1);
75 if (ret != SOFTBUS_OK) {
76 TRANS_LOGE(TRANS_FILE, "reuse port error, ret=%{public}d.", ret);
77 TransTdcReleaseFd(fd);
78 return ret;
79 }
80
81 ret = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketBind(fd, (SoftBusSockAddr *)&addr, sizeof(addr)));
82 if (ret != SOFTBUS_ADAPTER_OK) {
83 TRANS_LOGE(TRANS_FILE, "bind error, ret=%{public}d.", ret);
84 TransTdcReleaseFd(fd);
85 return ret;
86 }
87
88 return fd;
89 }
90
CreateServerSocketByIpv6(const char * ip,int port)91 static int CreateServerSocketByIpv6(const char *ip, int port)
92 {
93 SoftBusSockAddrIn6 addr;
94 int32_t ret = Ipv6AddrToAddrIn(&addr, ip, port);
95 if (ret != SOFTBUS_OK) {
96 TRANS_LOGE(TRANS_FILE, "init addr error, ret=%{public}d", ret);
97 return ret;
98 }
99
100 int fd;
101 ret = SoftBusSocketCreate(SOFTBUS_AF_INET6, SOFTBUS_SOCK_STREAM | SOFTBUS_SOCK_NONBLOCK |
102 SOFTBUS_SOCK_CLOEXEC, 0, &fd);
103 if (ret != SOFTBUS_OK) {
104 TRANS_LOGE(TRANS_FILE, "create socket error, ret=%{public}d.", ret);
105 return ret;
106 }
107
108 ret = SetReuseAddr(fd, 1);
109 if (ret != SOFTBUS_OK) {
110 TRANS_LOGE(TRANS_FILE, "reuse addr error, ret=%{public}d.", ret);
111 TransTdcReleaseFd(fd);
112 return ret;
113 }
114
115 ret = SetReusePort(fd, 1);
116 if (ret != SOFTBUS_OK) {
117 TRANS_LOGE(TRANS_FILE, "reuse port error, ret=%{public}d.", ret);
118 TransTdcReleaseFd(fd);
119 return ret;
120 }
121
122 ret = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketBind(fd, (SoftBusSockAddr *)&addr, sizeof(addr)));
123 TRANS_LOGI(TRANS_FILE, "bind addr port=%{public}#x", addr.sin6Port);
124 if (ret != SOFTBUS_ADAPTER_OK) {
125 TRANS_LOGE(TRANS_FILE, "bind error, ret=%{public}d.", ret);
126 TransTdcReleaseFd(fd);
127 return ret;
128 }
129 return fd;
130 }
131
CreateServerSocket(const char * ip,int32_t * fd,int32_t * port)132 static int32_t CreateServerSocket(const char *ip, int32_t *fd, int32_t *port)
133 {
134 if (ip == NULL || fd == NULL || port == NULL) {
135 TRANS_LOGE(TRANS_FILE, "invalid param.");
136 return SOFTBUS_INVALID_PARAM;
137 }
138
139 int32_t socketFd = -1;
140 if (GetDomainByAddr(ip) == SOFTBUS_AF_INET6) {
141 socketFd = CreateServerSocketByIpv6(ip, 0);
142 } else {
143 socketFd = CreateServerSocketByIpv4(ip, 0);
144 }
145
146 if (socketFd < 0) {
147 TRANS_LOGE(TRANS_FILE, "failed to start tcp server for getting port");
148 return SOFTBUS_FILE_ERR;
149 }
150 const SocketInterface *interface = GetSocketInterface(LNN_PROTOCOL_IP);
151 if (interface == NULL) {
152 TRANS_LOGE(TRANS_FILE, "no ip supportted");
153 TransTdcReleaseFd(socketFd);
154 return SOFTBUS_NOT_FIND;
155 }
156 int32_t socketPort = interface->GetSockPort(socketFd);
157 if (socketPort < 0) {
158 TRANS_LOGE(TRANS_FILE, "failed to get port from tcp socket");
159 TransTdcReleaseFd(socketFd);
160 return SOFTBUS_INVALID_PORT;
161 }
162 *fd = socketFd;
163 *port = socketPort;
164 TRANS_LOGI(TRANS_FILE, "create socket success, fd=%{public}d, port=%{public}d", socketFd, socketPort);
165 return SOFTBUS_OK;
166 }
167
InitSockAddrInByIpPort(const char * ip,int32_t port,struct sockaddr_in * addr)168 static int32_t InitSockAddrInByIpPort(const char *ip, int32_t port, struct sockaddr_in *addr)
169 {
170 if (ip == NULL || port < 0 || addr == NULL) {
171 TRANS_LOGE(TRANS_FILE, "invalid param.");
172 return SOFTBUS_INVALID_PARAM;
173 }
174
175 (void)memset_s(addr, sizeof(struct sockaddr_in), 0, sizeof(struct sockaddr_in));
176 addr->sin_family = AF_INET;
177 addr->sin_port = port;
178 addr->sin_addr.s_addr = SoftBusNtoHl(SoftBusInetAddr(ip));
179 return SOFTBUS_OK;
180 }
181
InitSockAddrIn6ByIpPort(const char * ip,int32_t port,struct sockaddr_in6 * addr)182 static int32_t InitSockAddrIn6ByIpPort(const char *ip, int32_t port, struct sockaddr_in6 *addr)
183 {
184 if (ip == NULL || port < 0 || addr == NULL) {
185 TRANS_LOGE(TRANS_FILE, "invalid param.");
186 return SOFTBUS_INVALID_PARAM;
187 }
188
189 SoftBusSockAddrIn6 addrIn6;
190 int32_t ret = Ipv6AddrToAddrIn(&addrIn6, ip, port);
191 addrIn6.sin6Port = port;
192 if (ret != SOFTBUS_OK) {
193 TRANS_LOGE(TRANS_FILE, "init addr error, ret=%{public}d", ret);
194 return ret;
195 }
196
197 (void)memset_s(addr, sizeof(struct sockaddr_in6), 0, sizeof(struct sockaddr_in6));
198 addr->sin6_family = AF_INET6;
199 addr->sin6_port = addrIn6.sin6Port;
200 addr->sin6_scope_id = addrIn6.sin6ScopeId;
201 if (memcpy_s(&addr->sin6_addr, sizeof(addr->sin6_addr), &addrIn6.sin6Addr, sizeof(addrIn6.sin6Addr)) != EOK) {
202 TRANS_LOGE(TRANS_FILE, "failed to get ip, ret=%{public}d", ret);
203 return SOFTBUS_MEM_ERR;
204 }
205 return SOFTBUS_OK;
206 }
207
StartNStackXDFileServer(const char * myIp,const uint8_t * key,uint32_t keyLen,DFileMsgReceiver msgReceiver,int32_t * filePort)208 int32_t StartNStackXDFileServer(
209 const char *myIp, const uint8_t *key, uint32_t keyLen, DFileMsgReceiver msgReceiver, int32_t *filePort)
210 {
211 if (myIp == NULL || filePort == NULL) {
212 TRANS_LOGE(TRANS_FILE, "invalid param.");
213 return SOFTBUS_INVALID_PARAM;
214 }
215 int32_t port = -1;
216 int32_t fd = -1;
217 int32_t ret = CreateServerSocket(myIp, &fd, &port);
218 if (ret != SOFTBUS_OK) {
219 TRANS_LOGE(TRANS_FILE, "failed to start tcp server for getting port");
220 return ret;
221 }
222 int sessionId = -1;
223 if (GetDomainByAddr(myIp) == SOFTBUS_AF_INET6) {
224 struct sockaddr_in6 localAddr = { 0 };
225 ret = InitSockAddrIn6ByIpPort(myIp, port, &localAddr);
226 if (ret != SOFTBUS_OK) {
227 TransTdcReleaseFd(fd);
228 TRANS_LOGE(TRANS_FILE, "failed to create sockaddr_in6, ret=%{public}d", ret);
229 return ret;
230 }
231 socklen_t addrLen = sizeof(struct sockaddr_in6);
232 sessionId = NSTACKX_DFileServer((struct sockaddr_in *)&localAddr, addrLen, key, keyLen, msgReceiver);
233 } else {
234 struct sockaddr_in localAddr = { 0 };
235 ret = InitSockAddrInByIpPort(myIp, port, &localAddr);
236 if (ret != SOFTBUS_OK) {
237 TransTdcReleaseFd(fd);
238 TRANS_LOGE(TRANS_FILE, "failed to create sockaddr_in, ret=%{public}d", ret);
239 return ret;
240 }
241 socklen_t addrLen = sizeof(struct sockaddr_in);
242 sessionId = NSTACKX_DFileServer(&localAddr, addrLen, key, keyLen, msgReceiver);
243 }
244 *filePort = port;
245 TransTdcReleaseFd(fd);
246 if (sessionId < 0) {
247 TRANS_LOGE(TRANS_FILE, "failed to start dfile server.");
248 return SOFTBUS_TRANS_INVALID_SESSION_ID;
249 }
250
251 char animizedIp[IP_LEN] = { 0 };
252 ConvertAnonymizeIpAddress(animizedIp, IP_LEN, myIp, IP_LEN);
253 TRANS_LOGI(TRANS_FILE, "start dfile server, ip=%{public}s, port=%{public}d", animizedIp, port);
254 return sessionId;
255 }
256
StartNStackXDFileClient(const char * peerIp,int32_t peerPort,const uint8_t * key,uint32_t keyLen,DFileMsgReceiver msgReceiver)257 int32_t StartNStackXDFileClient(
258 const char *peerIp, int32_t peerPort, const uint8_t *key, uint32_t keyLen, DFileMsgReceiver msgReceiver)
259 {
260 if (peerIp == NULL) {
261 TRANS_LOGW(TRANS_FILE, "invalid param.");
262 return SOFTBUS_INVALID_PARAM;
263 }
264
265 int32_t sessionId = -1;
266 if (GetDomainByAddr(peerIp) == SOFTBUS_AF_INET6) {
267 struct sockaddr_in6 localAddr = { 0 };
268 int32_t ret = InitSockAddrIn6ByIpPort(peerIp, peerPort, &localAddr);
269 if (ret != SOFTBUS_OK) {
270 TRANS_LOGE(TRANS_FILE, "failed to create sockaddr_in6, ret=%{public}d", ret);
271 return ret;
272 }
273 socklen_t addrLen = sizeof(struct sockaddr_in6);
274 sessionId = NSTACKX_DFileClient((struct sockaddr_in *)&localAddr, addrLen, key, keyLen, msgReceiver);
275 } else {
276 struct sockaddr_in localAddr = { 0 };
277 int32_t ret = InitSockAddrInByIpPort(peerIp, peerPort, &localAddr);
278 if (ret != SOFTBUS_OK) {
279 TRANS_LOGE(TRANS_FILE, "failed to create sockaddr_in, ret=%{public}d", ret);
280 return ret;
281 }
282 socklen_t addrLen = sizeof(struct sockaddr_in);
283 sessionId = NSTACKX_DFileClient(&localAddr, addrLen, key, keyLen, msgReceiver);
284 }
285
286 if (sessionId < 0) {
287 TRANS_LOGE(TRANS_FILE, "failed to start dfile client");
288 return SOFTBUS_TRANS_INVALID_SESSION_ID;
289 }
290
291 char animizedIp[IP_LEN] = { 0 };
292 ConvertAnonymizeIpAddress(animizedIp, IP_LEN, peerIp, IP_LEN);
293 TRANS_LOGI(TRANS_FILE, "start dfile client, peerIp=%{public}s, peerPort=%{public}d", animizedIp, peerPort);
294 return sessionId;
295 }
296