1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2022-05-26     xiangxistu   first version
9  */
10 
11 /* Do NOT include sys/time.h in this file */
12 #include <WinSock2.h>
13 #include <WS2tcpip.h>
14 #include <rtthread.h>
15 #include <stdint.h>
16 
17 #define DBG_TAG    "sal.winsock"
18 #define DBG_LVL    DBG_INFO
19 #include <rtdbg.h>
20 
21 #include "rtt_winsock.h"
22 
23 static struct sal_type_hostent sal_hostent;
24 static sal_type_ip_addr_t hostent_addr = { 0 };
25 static sal_type_ip_addr_t* hostent_addr_p = RT_NULL;
26 
27 /* Important, must reserve */
28 #pragma comment( lib, "ws2_32.lib" )
29 
30 /*
31  * reserve for select / poll
32  *
33  * #define WINDOWS_STACK_SIZE 2048
34  * #define WINDOWS_PRIORITY   2048
35  * #define WINDOWS_TICK       10
36  *
37  * struct poll_thread_list
38  * {
39  *     int socket;
40  *     rt_slist_t slist;
41  * };
42  * static rt_slist_t poll_pending_list = RT_SLIST_OBJECT_INIT(poll_pending_list);
43  *
44  **/
45 
46 #define WINDOWS_PERVIOS_COMAMND                                 \
47     do                                                          \
48     {                                                           \
49         int iResult;                                            \
50         WSADATA wsa_data;                                       \
51                                                                 \
52         iResult = WSAStartup(MAKEWORD(2, 2), &wsa_data);        \
53         if (iResult != 0)                                       \
54         {                                                       \
55             LOG_E("WSAStartup failed: %d\n", iResult);          \
56             return -RT_ERROR;                                   \
57         }                                                       \
58     }while(0)
59 
data_sync_sockaddr(struct sal_type_sockaddr * sal,struct sockaddr ** window)60 static void data_sync_sockaddr(struct sal_type_sockaddr* sal, struct sockaddr** window)
61 {
62     /*
63      *       ws2def.h
64      * typedef struct sockaddr {
65      *
66      * #if (_WIN32_WINNT < 0x0600)
67      *     u_short sa_family;
68      * #else
69      *     ADDRESS_FAMILY sa_family;           // Address family.
70      * #endif //(_WIN32_WINNT < 0x0600)
71      *
72      *     CHAR sa_data[14];                   // Up to 14 bytes of direct address.
73      * } SOCKADDR, *PSOCKADDR, FAR *LPSOCKADDR;
74      *
75      ***********************************
76      *      sal_socket.h
77      * struct sockaddr
78      * {
79      *     uint8_t        sa_len;
80      *     sa_family_t    sa_family;
81      *     char           sa_data[14];
82      * };
83      */
84     ADDRESS_FAMILY family = 0;
85     family = sal->sa_family;
86 
87     *window = sal;
88     (* window)->sa_family = family;
89 }
90 
win_socket(int domain,int type,int protocol)91 int win_socket(int domain, int type, int protocol)
92 {
93     WINDOWS_PERVIOS_COMAMND;
94 
95      return (int)socket(domain, type, protocol);
96 }
97 
win_closesocket(int s)98 int win_closesocket(int s)
99 {
100     return (int)closesocket(s);
101 }
102 
win_bind(int s,const struct sal_type_sockaddr * name,sal_type_socklen_t namelen)103 int win_bind(int s, const struct sal_type_sockaddr *name, sal_type_socklen_t namelen)
104 {
105     return (int)bind(s, name, namelen);
106 }
107 
win_listen(int s,int backlog)108 int win_listen(int s, int backlog)
109 {
110     return (int)listen(s, backlog);
111 }
112 
win_connect(int s,const struct sal_type_sockaddr * name,sal_type_socklen_t namelen)113 int win_connect(int s, const struct sal_type_sockaddr *name, sal_type_socklen_t namelen)
114 {
115     struct sockaddr *windows_addr = RT_NULL;
116     data_sync_sockaddr(name, &windows_addr);
117 
118     return (int)connect(s, windows_addr, namelen);
119 }
120 
win_accept(int s,struct sal_type_sockaddr * addr,sal_type_socklen_t * addrlen)121 int win_accept(int s, struct sal_type_sockaddr *addr, sal_type_socklen_t *addrlen)
122 {
123     WINDOWS_PERVIOS_COMAMND;
124 
125     return (int)accept(s, addr, addrlen);
126 }
127 
win_sendto(int s,const void * data,size_t size,int flags,const struct sal_type_sockaddr * to,sal_type_socklen_t tolen)128 int win_sendto(int s, const void *data, size_t size, int flags, const struct sal_type_sockaddr *to, sal_type_socklen_t tolen)
129 {
130     return (int)sendto(s, data, size, flags, to, tolen);
131 }
132 
win_recvfrom(int s,void * mem,size_t len,int flags,struct sal_type_sockaddr * from,sal_type_socklen_t * fromlen)133 int win_recvfrom(int s, void *mem, size_t len, int flags, struct sal_type_sockaddr *from, sal_type_socklen_t *fromlen)
134 {
135     return (int)recvfrom(s, mem, len, flags, from, fromlen);
136 }
137 
win_getsockopt(int s,int level,int optname,void * optval,sal_type_socklen_t * optlen)138 int win_getsockopt(int s, int level, int optname, void *optval, sal_type_socklen_t *optlen)
139 {
140     return (int)getsockopt(s, level, optname, optval, optlen);
141 }
142 
win_setsockopt(int s,int level,int optname,const void * optval,sal_type_socklen_t optlen)143 int win_setsockopt(int s, int level, int optname, const void *optval, sal_type_socklen_t optlen)
144 {
145     return (int)setsockopt(s, level, optname, optval, optlen);
146 }
147 
win_shutdown(int s,int how)148 int win_shutdown(int s, int how)
149 {
150     return (int)shutdown(s, how);
151 }
152 
win_getpeername(int s,struct sal_type_sockaddr * name,sal_type_socklen_t * namelen)153 int win_getpeername(int s, struct sal_type_sockaddr *name, sal_type_socklen_t *namelen)
154 {
155     return (int)getpeername(s, name, namelen);
156 }
157 
win_getsockname(int s,struct sal_type_sockaddr * name,sal_type_socklen_t * namelen)158 int win_getsockname(int s, struct sal_type_sockaddr *name, sal_type_socklen_t *namelen)
159 {
160     return (int)getsockname(s, name, namelen);
161 }
162 
win_ioctlsocket(int s,long cmd,void * arg)163 int win_ioctlsocket(int s, long cmd, void *arg)
164 {
165     return (int)ioctlsocket(s, cmd, arg);
166 }
167 
168 #ifdef SAL_USING_POSIX
169 /* use windows poll, but not wait */
inet_poll(struct dfs_file * file,struct rt_pollreq * req)170 int inet_poll(struct dfs_file* file, struct rt_pollreq* req)
171 {
172     /*
173     WSAPOLLFD winpoll;
174     struct sal_socket* sal_sock;
175     int mask = 0;
176     int poll_event = 0;
177 
178     sal_sock = sal_get_socket((int)file->data);
179     if (!sal_sock)
180     {
181         return -1;
182     }
183 
184     winpoll.fd = sal_sock->socket;
185     poll_event &= POLLERR | POLLHUP;
186     winpoll.events = req->_key & (~poll_event);
187     poll_event = 0;
188 
189     mask = WSAPoll(&winpoll, 1, 0);
190     if (mask == 0)
191         return 0;
192 
193     return winpoll.revents;
194     */
195 
196    return 0;
197 }
198 #endif /* SAL_USING_POSIX */
199 
win_gethostbyname(const char * name)200 struct sal_type_hostent* win_gethostbyname(const char* name)
201 {
202     struct hostent *windows_hostent;
203     char** h_addr_list;
204 
205     WINDOWS_PERVIOS_COMAMND;
206 
207     windows_hostent = gethostbyname(name);
208 
209     sal_hostent.h_name = windows_hostent->h_name;
210     sal_hostent.h_aliases = windows_hostent->h_aliases;
211     sal_hostent.h_addrtype = windows_hostent->h_addrtype;
212     sal_hostent.h_length = windows_hostent->h_length;
213     sal_hostent.h_addr_list = windows_hostent->h_addr_list;
214     hostent_addr.addr = ((struct in_addr*)windows_hostent->h_addr)->s_addr;
215     hostent_addr_p = &hostent_addr;
216     sal_hostent.h_addr_list = &hostent_addr_p;
217 
218     return &sal_hostent;
219 }
220 
win_getaddrinfo(const char * nodename,const char * servname,const struct sal_type_addrinfo * hints,struct sal_type_addrinfo ** res)221 int win_getaddrinfo(const char* nodename, const char* servname, const struct sal_type_addrinfo* hints, struct sal_type_addrinfo** res)
222 {
223     int port_nr = 0;
224     sal_type_ip_addr_t addr = { 0 };
225     struct sal_type_addrinfo* ai;
226     struct sal_type_sockaddr_storage* sa;
227     size_t total_size = 0;
228     size_t namelen = 0;
229     char* change_point;
230 
231     if (res == RT_NULL)
232         return EAI_FAIL;
233     *res = RT_NULL;
234 
235     if ((nodename == RT_NULL) && (servname == RT_NULL))
236         return EAI_NONAME;
237 
238     if ((hints != RT_NULL)
239         && (hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC))
240         return EAI_FAMILY;
241 
242     if (servname != RT_NULL)
243     {
244         /* service name specified: convert to port number */
245         port_nr = atoi(servname);
246         if ((port_nr <= 0) || (port_nr > 0xffff))
247         {
248             return EAI_SERVICE;
249         }
250     }
251 
252     if (nodename != RT_NULL)
253     {
254         WINDOWS_PERVIOS_COMAMND;
255         struct hostent* hostent = gethostbyname(nodename);
256         if (hostent == RT_NULL)
257             return EAI_FAIL;
258         addr.addr = ((struct in_addr*)hostent->h_addr)->s_addr;
259     }
260 
261     total_size = sizeof(struct sal_type_addrinfo) + sizeof(struct sal_type_sockaddr_storage);
262     if (nodename != RT_NULL)
263     {
264         namelen = strlen(nodename);
265         if (namelen > DNS_MAX_NAME_LENGTH)
266         {
267             /* invalid name length */
268             return EAI_FAIL;
269         }
270         RT_ASSERT(total_size + namelen + 1 > total_size);
271         total_size += namelen + 1;
272     }
273 
274     RT_ASSERT(total_size <= sizeof(struct sal_type_addrinfo) + sizeof(struct sal_type_sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1);
275     ai = (struct sal_type_addrinfo*)rt_malloc(total_size);
276     if (ai == RT_NULL)
277     {
278         return EAI_MEMORY;
279     }
280     rt_memset(ai, 0, total_size);
281 
282     /* cast through void* to get rid of alignment warnings */
283     sa = (struct sal_type_sockaddr_storage*)(void*)((uint8_t*)ai + sizeof(struct sal_type_addrinfo));
284     struct sal_type_sockaddr_in* sa4 = (struct sal_type_sockaddr_in*)sa;
285 
286     sa4->sin_family = AF_INET;
287     sa4->sin_addr.sal_type_s_addr = addr.addr;
288     sa4->sin_port = htons((uint16_t)port_nr);
289 
290     /* set up addrinfo */
291     if (hints != RT_NULL)
292     {
293         /* copy socktype & protocol from hints if specified */
294         ai->ai_socktype = hints->ai_socktype;
295         ai->ai_protocol = hints->ai_protocol;
296     }
297     if (nodename != RT_NULL)
298     {
299         /* copy nodename to canonname if specified */
300         ai->ai_canonname = ((char*)ai + sizeof(struct sal_type_addrinfo) + sizeof(struct sal_type_sockaddr_storage));
301         rt_memcpy(ai->ai_canonname, nodename, namelen);
302         ai->ai_canonname[namelen] = 0;
303     }
304 
305     ai->ai_addrlen = sizeof(struct sal_type_sockaddr_storage);
306     ai->ai_addr = (struct sal_type_sockaddr*)sa;
307     ai->ai_family = sa4->sin_family;
308 
309     *res = ai;
310 
311     return 0;
312 }
313 
win_freeaddrinfo(struct sal_type_addrinfo * ai)314 void win_freeaddrinfo(struct sal_type_addrinfo* ai)
315 {
316     struct sal_type_addrinfo* next;
317 
318     while (ai != NULL)
319     {
320         next = ai->ai_next;
321         rt_free(ai);
322         ai = next;
323     }
324 }
325