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 ret;
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 ret;
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 return fd;
87 }
88
CreateServerSocketByIpv6(const char * ip,int port)89 static int CreateServerSocketByIpv6(const char *ip, int port)
90 {
91 SoftBusSockAddrIn6 addr;
92 int32_t ret = Ipv6AddrToAddrIn(&addr, ip, port);
93 if (ret != SOFTBUS_OK) {
94 TRANS_LOGE(TRANS_FILE, "init addr error, ret=%{public}d", ret);
95 return ret;
96 }
97
98 int fd;
99 ret = SoftBusSocketCreate(SOFTBUS_AF_INET6, SOFTBUS_SOCK_STREAM | SOFTBUS_SOCK_NONBLOCK |
100 SOFTBUS_SOCK_CLOEXEC, 0, &fd);
101 if (ret != SOFTBUS_OK) {
102 TRANS_LOGE(TRANS_FILE, "create socket error, ret=%{public}d.", ret);
103 return ret;
104 }
105
106 ret = SetReuseAddr(fd, 1);
107 if (ret != SOFTBUS_OK) {
108 TRANS_LOGE(TRANS_FILE, "reuse addr error, ret=%{public}d.", ret);
109 ConnShutdownSocket(fd);
110 return ret;
111 }
112
113 ret = SetReusePort(fd, 1);
114 if (ret != SOFTBUS_OK) {
115 TRANS_LOGE(TRANS_FILE, "reuse port error, ret=%{public}d.", ret);
116 ConnShutdownSocket(fd);
117 return ret;
118 }
119
120 ret = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketBind(fd, (SoftBusSockAddr *)&addr, sizeof(addr)));
121 TRANS_LOGI(TRANS_FILE, "bind addr port=%{public}#x", addr.sin6Port);
122 if (ret != SOFTBUS_ADAPTER_OK) {
123 TRANS_LOGE(TRANS_FILE, "bind error, ret=%{public}d.", ret);
124 ConnShutdownSocket(fd);
125 return ret;
126 }
127 return fd;
128 }
129
CreateServerSocket(const char * ip,int32_t * fd,int32_t * port)130 static int32_t CreateServerSocket(const char *ip, int32_t *fd, int32_t *port)
131 {
132 if (ip == NULL || fd == NULL || port == NULL) {
133 TRANS_LOGE(TRANS_FILE, "invalid param.");
134 return SOFTBUS_INVALID_PARAM;
135 }
136
137 int32_t socketFd = -1;
138 if (GetDomainByAddr(ip) == SOFTBUS_AF_INET6) {
139 socketFd = CreateServerSocketByIpv6(ip, 0);
140 } else {
141 socketFd = CreateServerSocketByIpv4(ip, 0);
142 }
143
144 if (socketFd < 0) {
145 TRANS_LOGE(TRANS_FILE, "failed to start tcp server for getting port");
146 return SOFTBUS_FILE_ERR;
147 }
148 const SocketInterface *interface = GetSocketInterface(LNN_PROTOCOL_IP);
149 if (interface == NULL) {
150 TRANS_LOGE(TRANS_FILE, "no ip supportted");
151 ConnShutdownSocket(socketFd);
152 return SOFTBUS_NOT_FIND;
153 }
154 int32_t socketPort = interface->GetSockPort(socketFd);
155 if (socketPort < 0) {
156 TRANS_LOGE(TRANS_FILE, "failed to get port from tcp socket");
157 ConnShutdownSocket(socketFd);
158 return SOFTBUS_INVALID_PORT;
159 }
160 *fd = socketFd;
161 *port = socketPort;
162 TRANS_LOGI(TRANS_FILE, "create socket success, fd=%{public}d, port=%{public}d", socketFd, socketPort);
163 return SOFTBUS_OK;
164 }
165
InitSockAddrInByIpPort(const char * ip,int32_t port,struct sockaddr_in * addr)166 static int32_t InitSockAddrInByIpPort(const char *ip, int32_t port, struct sockaddr_in *addr)
167 {
168 if (ip == NULL || port < 0 || addr == NULL) {
169 TRANS_LOGE(TRANS_FILE, "invalid param.");
170 return SOFTBUS_INVALID_PARAM;
171 }
172 addr->sin_family = AF_INET;
173 addr->sin_port = port;
174 addr->sin_addr.s_addr = SoftBusNtoHl(SoftBusInetAddr(ip));
175 return SOFTBUS_OK;
176 }
177
InitSockAddrIn6ByIpPort(const char * ip,int32_t port,struct sockaddr_in6 * addr)178 static int32_t InitSockAddrIn6ByIpPort(const char *ip, int32_t port, struct sockaddr_in6 *addr)
179 {
180 if (ip == NULL || port < 0 || addr == NULL) {
181 TRANS_LOGE(TRANS_FILE, "invalid param.");
182 return SOFTBUS_INVALID_PARAM;
183 }
184
185 SoftBusSockAddrIn6 addrIn6;
186 int32_t ret = Ipv6AddrToAddrIn(&addrIn6, ip, port);
187 addrIn6.sin6Port = port;
188 if (ret != SOFTBUS_OK) {
189 TRANS_LOGE(TRANS_FILE, "init addr error, ret=%{public}d", ret);
190 return ret;
191 }
192 addr->sin6_family = AF_INET6;
193 addr->sin6_port = addrIn6.sin6Port;
194 addr->sin6_scope_id = addrIn6.sin6ScopeId;
195 if (memcpy_s(&addr->sin6_addr, sizeof(addr->sin6_addr), &addrIn6.sin6Addr, sizeof(addrIn6.sin6Addr)) != EOK) {
196 TRANS_LOGE(TRANS_FILE, "failed to get ip, ret=%{public}d", ret);
197 return SOFTBUS_MEM_ERR;
198 }
199 return SOFTBUS_OK;
200 }
201
StartNStackXDFileServer(const char * myIp,const uint8_t * key,uint32_t keyLen,DFileMsgReceiver msgReceiver,int32_t * filePort)202 int32_t StartNStackXDFileServer(
203 const char *myIp, const uint8_t *key, uint32_t keyLen, DFileMsgReceiver msgReceiver, int32_t *filePort)
204 {
205 if (myIp == NULL || filePort == NULL) {
206 TRANS_LOGE(TRANS_FILE, "invalid param.");
207 return SOFTBUS_INVALID_PARAM;
208 }
209 int32_t port = -1;
210 int32_t fd = -1;
211 int32_t ret = CreateServerSocket(myIp, &fd, &port);
212 if (ret != SOFTBUS_OK) {
213 TRANS_LOGE(TRANS_FILE, "failed to start tcp server for getting port");
214 return ret;
215 }
216 int sessionId = -1;
217 if (GetDomainByAddr(myIp) == SOFTBUS_AF_INET6) {
218 struct sockaddr_in6 localAddr = { 0 };
219 ret = InitSockAddrIn6ByIpPort(myIp, port, &localAddr);
220 if (ret != SOFTBUS_OK) {
221 ConnShutdownSocket(fd);
222 TRANS_LOGE(TRANS_FILE, "failed to create sockaddr_in6, ret=%{public}d", ret);
223 return ret;
224 }
225 socklen_t addrLen = sizeof(struct sockaddr_in6);
226 sessionId = NSTACKX_DFileServer((struct sockaddr_in *)&localAddr, addrLen, key, keyLen, msgReceiver);
227 } else {
228 struct sockaddr_in localAddr = { 0 };
229 ret = InitSockAddrInByIpPort(myIp, port, &localAddr);
230 if (ret != SOFTBUS_OK) {
231 ConnShutdownSocket(fd);
232 TRANS_LOGE(TRANS_FILE, "failed to create sockaddr_in, ret=%{public}d", ret);
233 return ret;
234 }
235 socklen_t addrLen = sizeof(struct sockaddr_in);
236 sessionId = NSTACKX_DFileServer(&localAddr, addrLen, key, keyLen, msgReceiver);
237 }
238 *filePort = port;
239 ConnShutdownSocket(fd);
240 if (sessionId < 0) {
241 TRANS_LOGE(TRANS_FILE, "failed to start dfile server.");
242 return SOFTBUS_TRANS_INVALID_SESSION_ID;
243 }
244
245 char animizedIp[IP_LEN] = { 0 };
246 ConvertAnonymizeIpAddress(animizedIp, IP_LEN, myIp, IP_LEN);
247 TRANS_LOGI(TRANS_FILE, "start dfile server, ip=%{public}s, port=%{public}d", animizedIp, port);
248 return sessionId;
249 }
250
StartNStackXDFileClient(const char * peerIp,int32_t peerPort,const uint8_t * key,uint32_t keyLen,DFileMsgReceiver msgReceiver)251 int32_t StartNStackXDFileClient(
252 const char *peerIp, int32_t peerPort, const uint8_t *key, uint32_t keyLen, DFileMsgReceiver msgReceiver)
253 {
254 if (peerIp == NULL) {
255 TRANS_LOGW(TRANS_FILE, "invalid param.");
256 return SOFTBUS_INVALID_PARAM;
257 }
258
259 int32_t sessionId = -1;
260 if (GetDomainByAddr(peerIp) == SOFTBUS_AF_INET6) {
261 struct sockaddr_in6 localAddr = { 0 };
262 int32_t ret = InitSockAddrIn6ByIpPort(peerIp, peerPort, &localAddr);
263 if (ret != SOFTBUS_OK) {
264 TRANS_LOGE(TRANS_FILE, "failed to create sockaddr_in6, ret=%{public}d", ret);
265 return ret;
266 }
267 socklen_t addrLen = sizeof(struct sockaddr_in6);
268 sessionId = NSTACKX_DFileClient((struct sockaddr_in *)&localAddr, addrLen, key, keyLen, msgReceiver);
269 } else {
270 struct sockaddr_in localAddr = { 0 };
271 int32_t ret = InitSockAddrInByIpPort(peerIp, peerPort, &localAddr);
272 if (ret != SOFTBUS_OK) {
273 TRANS_LOGE(TRANS_FILE, "failed to create sockaddr_in, ret=%{public}d", ret);
274 return ret;
275 }
276 socklen_t addrLen = sizeof(struct sockaddr_in);
277 sessionId = NSTACKX_DFileClient(&localAddr, addrLen, key, keyLen, msgReceiver);
278 }
279
280 if (sessionId < 0) {
281 TRANS_LOGE(TRANS_FILE, "failed to start dfile client");
282 return SOFTBUS_TRANS_INVALID_SESSION_ID;
283 }
284
285 char animizedIp[IP_LEN] = { 0 };
286 ConvertAnonymizeIpAddress(animizedIp, IP_LEN, peerIp, IP_LEN);
287 TRANS_LOGI(TRANS_FILE, "start dfile client, peerIp=%{public}s, peerPort=%{public}d", animizedIp, peerPort);
288 return sessionId;
289 }
290