• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "softbus_mintp_socket.h"
17 
18 #include "conn_log.h"
19 #include "softbus_adapter_errcode.h"
20 #include "softbus_conn_common.h"
21 #include "softbus_error_code.h"
22 #include "softbus_socket.h"
23 #include "softbus_tcp_socket.h"
24 #include "softbus_utils.h"
25 
26 #define IPPROTO_MINTP       200
27 #define SOL_MTP             300
28 #define MTP_ADDR_TYPE_MAC   0
29 #define MTP_ADDR_TYPE_IPV4  1
30 #define MTP_ADDR_TYPE_IPV6  2
31 #define MTP_SOCKET_MSG_SIZE 8000
32 #define MTP_TOS             1
33 #define MTP_KEEPIDLE        2
34 #define MTP_MAX_MSG_SIZE    3
35 #define MTP_TRANS_TYPE      10
36 #define MTP_TIME_SYNC       11
37 #define USER_TIMEOUT_MS     (15 * 1000) // 15s
38 
39 struct MtpMacAddr {
40     unsigned char addr[6];
41     unsigned char pad[6]; // the inet framework need size of addr >= 16
42 };
43 
44 struct MtpIpAddr {
45     unsigned char addr;
46     unsigned char pad[8]; // the inet framework need size of addr >= 16
47 };
48 
49 struct MtpIp6Addr {
50     unsigned int flowinfo;  // IPv6 flow information
51     unsigned char addr[16]; // IPv6 address
52     unsigned int scope;     // IPv6 address scope
53 };
54 
55 struct SockAddrMtp {
56     unsigned short saFamily;
57     unsigned char port;
58     unsigned char type;
59     union {
60         struct MtpMacAddr mac;
61         struct MtpIpAddr ip;
62         struct MtpIp6Addr ip6;
63     };
64 };
65 
SetMintpSocketMsgSize(int32_t fd)66 int32_t SetMintpSocketMsgSize(int32_t fd)
67 {
68     int32_t msgSize = MTP_SOCKET_MSG_SIZE;
69     int32_t rc = SoftBusSocketSetOpt(fd, SOL_MTP, MTP_MAX_MSG_SIZE, &msgSize, sizeof(msgSize));
70     if (rc != SOFTBUS_ADAPTER_OK) {
71         CONN_LOGE(CONN_COMMON, "set MTP_MAX_MSG_SIZE fail. rc=%{public}d, errno=%{public}d", rc, errno);
72         return rc;
73     }
74     return SOFTBUS_OK;
75 }
76 
SetMintpSocketTos(int32_t fd,uint32_t tos)77 int32_t SetMintpSocketTos(int32_t fd, uint32_t tos)
78 {
79     int32_t rc = SoftBusSocketSetOpt(fd, SOL_MTP, MTP_TOS, &tos, sizeof(tos));
80     if (rc != SOFTBUS_ADAPTER_OK) {
81         CONN_LOGE(CONN_COMMON, "set mintp tos fail. fd=%{public}d", fd);
82         return rc;
83     }
84     return SOFTBUS_OK;
85 }
86 
SetMintpSocketTransType(int32_t fd,uint32_t transType)87 int32_t SetMintpSocketTransType(int32_t fd, uint32_t transType)
88 {
89     int32_t rc = SoftBusSocketSetOpt(fd, SOL_MTP, MTP_TRANS_TYPE, &transType, sizeof(transType));
90     if (rc != SOFTBUS_ADAPTER_OK) {
91         CONN_LOGE(CONN_COMMON, "set mintp trans type fail. fd=%{public}d", fd);
92         return rc;
93     }
94     return SOFTBUS_OK;
95 }
96 
SetMintpSocketKeepAlive(int32_t fd,int32_t timeoutMs)97 int32_t SetMintpSocketKeepAlive(int32_t fd, int32_t timeoutMs)
98 {
99     if (timeoutMs <= 0) {
100         CONN_LOGE(CONN_COMMON, "invalid param.");
101         return SOFTBUS_INVALID_PARAM;
102     }
103     int32_t rc = SoftBusSocketSetOpt(fd, SOL_MTP, MTP_KEEPIDLE, &timeoutMs, sizeof(timeoutMs));
104     if (rc != SOFTBUS_ADAPTER_OK) {
105         CONN_LOGE(CONN_COMMON, "set mintp keep idle fail. fd=%{public}d", fd);
106         return rc;
107     }
108     return SOFTBUS_OK;
109 }
110 
SetMintpSocketTimeSync(int32_t fd,MintpTimeSync * timeSync)111 int32_t SetMintpSocketTimeSync(int32_t fd, MintpTimeSync *timeSync)
112 {
113     if (timeSync == NULL) {
114         CONN_LOGE(CONN_COMMON, "invalid param.");
115         return SOFTBUS_INVALID_PARAM;
116     }
117     int32_t rc = SoftBusSocketSetOpt(fd, SOL_MTP, MTP_TIME_SYNC, timeSync, sizeof(MintpTimeSync));
118     if (rc != SOFTBUS_ADAPTER_OK) {
119         CONN_LOGE(CONN_COMMON, "set mintp time sync fail. fd=%{public}d", fd);
120         return rc;
121     }
122     return SOFTBUS_OK;
123 }
124 
SetMintpOption(int32_t fd)125 static void SetMintpOption(int32_t fd)
126 {
127     SetMintpSocketKeepAlive(fd, USER_TIMEOUT_MS);
128     SetMintpSocketMsgSize(fd);
129     SetMintpSocketTransType(fd, 1);
130 }
131 
BindMintp(int32_t domain,int32_t fd,const char * localIp)132 static int32_t BindMintp(int32_t domain, int32_t fd, const char *localIp)
133 {
134     bool isIpv4 = domain == SOFTBUS_AF_INET;
135     struct SockAddrMtp tmpAddr;
136     uint32_t addrLen;
137     (void)memset_s(&tmpAddr, sizeof(tmpAddr), 0, sizeof(tmpAddr));
138     tmpAddr.saFamily = domain;
139     tmpAddr.port = 0;
140     tmpAddr.type = isIpv4 ? MTP_ADDR_TYPE_IPV4 : MTP_ADDR_TYPE_IPV6;
141     if (isIpv4) {
142         int32_t rc = SoftBusInetPtoN(SOFTBUS_AF_INET, localIp, &tmpAddr.ip.addr);
143         if (rc != SOFTBUS_ADAPTER_OK) {
144             CONN_LOGE(CONN_COMMON, "ipv4 SoftBusInetPtoN fail. rc=%{public}d", rc);
145             return SOFTBUS_SOCKET_ADDR_ERR;
146         }
147     } else {
148         int32_t rc = SoftBusInetPtoN(SOFTBUS_AF_INET6, localIp, &tmpAddr.ip6.addr);
149         if (rc != SOFTBUS_ADAPTER_OK) {
150             CONN_LOGE(CONN_COMMON, "ipv6 SoftBusInetPtoN fail. rc=%{public}d", rc);
151             return SOFTBUS_SOCKET_ADDR_ERR;
152         }
153     }
154     addrLen = isIpv4 ? sizeof(SoftBusSockAddrIn) : sizeof(tmpAddr);
155     int32_t ret = bind(fd, (struct sockaddr *)&tmpAddr, addrLen);
156     if (ret != 0) {
157         CONN_LOGE(CONN_COMMON, "bind mintp fail. ret=%{public}d, errno=%{public}d(%{public}s)", ret, errno,
158             strerror(errno));
159         return SOFTBUS_SOCKET_BIND_ERR;
160     }
161     return SOFTBUS_OK;
162 }
163 
OpenMintpServerSocket(const LocalListenerInfo * option)164 static int32_t OpenMintpServerSocket(const LocalListenerInfo *option)
165 {
166     CONN_CHECK_AND_RETURN_RET_LOGE(
167         option != NULL, SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid param, option is null.");
168     CONN_CHECK_AND_RETURN_RET_LOGE(
169         option->type == CONNECT_HML, SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid connect type.");
170     CONN_CHECK_AND_RETURN_RET_LOGE(option->socketOption.port >= 0, SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid port.");
171 
172     char animizedIp[IP_LEN] = { 0 };
173     ConvertAnonymizeIpAddress(animizedIp, IP_LEN, option->socketOption.addr, strlen(option->socketOption.addr));
174     CONN_LOGI(CONN_COMMON, "open mintp server socket, ip=%{public}s, port=%{public}d.", animizedIp,
175         option->socketOption.port);
176 
177     int32_t fd = -1;
178     int32_t domain = GetDomainByAddr(option->socketOption.addr);
179     int32_t ret = SoftBusSocketCreate(domain, SOFTBUS_SOCK_DGRAM | SOFTBUS_SOCK_NONBLOCK, IPPROTO_MINTP, &fd);
180     if (ret != SOFTBUS_ADAPTER_OK) {
181         CONN_LOGE(CONN_COMMON, "create mintp socket fail. ret=%{public}d", ret);
182         return ret;
183     }
184     ret = BindMintp(domain, fd, option->socketOption.addr);
185     if (ret != SOFTBUS_OK) {
186         CONN_LOGE(CONN_COMMON, "bind mintp fail. ret=%{public}d", ret);
187         ConnShutdownSocket(fd);
188         return ret;
189     }
190     SetMintpOption(fd);
191     CONN_LOGI(CONN_COMMON, "open mintp server socket success, fd=%{public}d.", fd);
192     return fd;
193 }
194 
MintpSocketConnect(int32_t fd,int32_t domain,const ConnectOption * option)195 static int32_t MintpSocketConnect(int32_t fd, int32_t domain, const ConnectOption *option)
196 {
197     struct SockAddrMtp tmpAddr;
198     tmpAddr.saFamily = domain;
199     tmpAddr.port = SoftBusHtoNs((uint16_t)(option->socketOption.port));
200     tmpAddr.type = domain == SOFTBUS_AF_INET ? MTP_ADDR_TYPE_IPV4 : MTP_ADDR_TYPE_IPV6;
201     if (domain == SOFTBUS_AF_INET) {
202         int32_t rc = SoftBusInetPtoN(SOFTBUS_AF_INET, option->socketOption.addr, &tmpAddr.ip.addr);
203         if (rc != SOFTBUS_ADAPTER_OK) {
204             CONN_LOGE(CONN_COMMON, "ipv4 SoftBusInetPtoN fail. rc=%{public}d", rc);
205             return rc;
206         }
207     } else {
208         int32_t rc = SoftBusInetPtoN(SOFTBUS_AF_INET6, option->socketOption.addr, &tmpAddr.ip6.addr);
209         if (rc != SOFTBUS_ADAPTER_OK) {
210             CONN_LOGE(CONN_COMMON, "ipv6 SoftBusInetPtoN fail. rc=%{public}d", rc);
211             return rc;
212         }
213     }
214     int32_t addrLen = domain == SOFTBUS_AF_INET ? sizeof(SoftBusSockAddrIn) : sizeof(tmpAddr);
215     return SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketConnect(fd, (SoftBusSockAddr *)&tmpAddr, addrLen));
216 }
217 
OpenMintpClientSocket(const ConnectOption * option,const char * myIp,bool isNonBlock)218 static int32_t OpenMintpClientSocket(const ConnectOption *option, const char *myIp, bool isNonBlock)
219 {
220     CONN_CHECK_AND_RETURN_RET_LOGE(
221         option != NULL, SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid param, option is null.");
222     CONN_CHECK_AND_RETURN_RET_LOGE(myIp != NULL, SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid param, myIp is null.");
223     CONN_CHECK_AND_RETURN_RET_LOGE(option->type == CONNECT_HML, SOFTBUS_INVALID_PARAM, CONN_COMMON,
224         "invalid param, unsupported connect type, type=%{public}d.", option->type);
225     CONN_CHECK_AND_RETURN_RET_LOGE(
226         option->socketOption.port > 0, SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid param, port is invalid.");
227     CONN_CHECK_AND_RETURN_RET_LOGE(
228         option->socketOption.addr[0] != '\0', SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid param, addr is invalid.");
229 
230     char animizedIp[IP_LEN] = { 0 };
231     ConvertAnonymizeIpAddress(animizedIp, IP_LEN, option->socketOption.addr, strlen(option->socketOption.addr));
232     CONN_LOGI(CONN_COMMON, "open mintp client socket, server ip=%{public}s, server port=%{public}d.", animizedIp,
233         option->socketOption.port);
234     int32_t fd = -1;
235     int32_t domain = GetDomainByAddr(option->socketOption.addr);
236     int32_t ret = SoftBusSocketCreate(domain, SOFTBUS_SOCK_DGRAM, IPPROTO_MINTP, &fd);
237     if (ret != SOFTBUS_OK) {
238         CONN_LOGE(CONN_COMMON, "create mintp socket fail. serverIp=%{public}s, serverPort=%{public}d, ret=%{public}d",
239             animizedIp, option->socketOption.port, ret);
240         return ret;
241     }
242     if (isNonBlock && ConnToggleNonBlockMode(fd, true) != SOFTBUS_OK) {
243         CONN_LOGE(CONN_COMMON, "set nonblock mode fail. serverIp=%{public}s, serverPort=%{public}d", animizedIp,
244             option->socketOption.port);
245         ConnShutdownSocket(fd);
246         return SOFTBUS_SOCKET_ERR;
247     }
248     ret = BindMintp(domain, fd, myIp);
249     if (ret != SOFTBUS_OK) {
250         CONN_LOGE(CONN_COMMON, "bind mintp fail. ret=%{public}d", ret);
251         ConnShutdownSocket(fd);
252         return ret;
253     }
254     SetMintpOption(fd);
255     ret = MintpSocketConnect(fd, domain, option);
256     if ((ret != SOFTBUS_ADAPTER_OK) && (ret != SOFTBUS_ADAPTER_SOCKET_EINPROGRESS) &&
257         (ret != SOFTBUS_ADAPTER_SOCKET_EAGAIN)) {
258         CONN_LOGE(CONN_COMMON, "connect mintp fail. serverIp=%{public}s, serverPort=%{public}d, ret=%{public}d",
259             animizedIp, option->socketOption.port, ret);
260         ConnShutdownSocket(fd);
261         return SOFTBUS_SOCKET_ERR;
262     }
263     CONN_LOGI(CONN_COMMON, "mintp connect success, fd=%{public}d, serverIp=%{public}s, serverPort=%{public}d.", fd,
264         animizedIp, option->socketOption.port);
265     return fd;
266 }
267 
GetMintpSockPort(int32_t fd)268 int32_t GetMintpSockPort(int32_t fd)
269 {
270     SoftBusSockAddr addr;
271     int32_t rc = SoftBusSocketGetLocalName(fd, &addr);
272     if (rc != SOFTBUS_ADAPTER_OK) {
273         CONN_LOGE(CONN_COMMON, "get mintp sock port fail. rc=%{public}d, fd=%{public}d", rc, fd);
274         return rc;
275     }
276     if (addr.saFamily == SOFTBUS_AF_INET6) {
277         return SoftBusNtoHs(((SoftBusSockAddrIn6 *)&addr)->sin6Port);
278     }
279     return SoftBusNtoHs(((SoftBusSockAddrIn *)&addr)->sinPort);
280 }
281 
AcceptMintpClient(int32_t fd,ConnectOption * clientAddr,int32_t * cfd)282 static int32_t AcceptMintpClient(int32_t fd, ConnectOption *clientAddr, int32_t *cfd)
283 {
284     CONN_CHECK_AND_RETURN_RET_LOGW(
285         clientAddr != NULL, SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid param, clientAddr is null");
286     CONN_CHECK_AND_RETURN_RET_LOGW(cfd != NULL, SOFTBUS_INVALID_PARAM, CONN_COMMON, "invalid param, cfd is null");
287     struct SockAddrMtp mtpClientAddr;
288     socklen_t addrLen = sizeof(mtpClientAddr);
289     (void)memset_s(&mtpClientAddr, addrLen, 0, addrLen);
290     int32_t ret = SOFTBUS_TEMP_FAILURE_RETRY(SoftBusSocketAccept(fd, (SoftBusSockAddr *)&mtpClientAddr, cfd));
291     if (ret != SOFTBUS_OK) {
292         CONN_LOGE(CONN_COMMON, "accept mintp client fail. ret=%{public}d", ret);
293         return ret;
294     }
295     clientAddr->type = CONNECT_HML;
296     clientAddr->socketOption.port = GetMintpSockPort(*cfd);
297     clientAddr->socketOption.protocol = LNN_PROTOCOL_MINTP;
298     char mtpMac[BT_MAC_LEN] = { 0 };
299     ret = ConvertBtMacToStr(mtpMac, sizeof(mtpMac), mtpClientAddr.mac.addr, sizeof(mtpClientAddr.mac.addr));
300     if (ret != SOFTBUS_OK) {
301         CONN_LOGE(CONN_COMMON, "convert mintp mac to string fail. ret=%{public}d", ret);
302         return ret;
303     }
304     ret = strcpy_s(clientAddr->socketOption.addr, sizeof(clientAddr->socketOption.addr), mtpMac);
305     if (ret != EOK) {
306         CONN_LOGE(CONN_COMMON, "copy mintp mac to clientAddr fail. ret=%{public}d", ret);
307         return SOFTBUS_ERR;
308     }
309     CONN_LOGI(CONN_COMMON, "accept mintp client success, cfd=%{public}d", *cfd);
310     return SOFTBUS_OK;
311 }
312 
GetMintpProtocol(void)313 const SocketInterface *GetMintpProtocol(void)
314 {
315     static SocketInterface mintpSocketIntf = {
316         .name = "MINTP",
317         .type = LNN_PROTOCOL_MINTP,
318         .GetSockPort = GetMintpSockPort,
319         .OpenClientSocket = OpenMintpClientSocket,
320         .OpenServerSocket = OpenMintpServerSocket,
321         .AcceptClient = AcceptMintpClient,
322     };
323     return &mintpSocketIntf;
324 }
325