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