1 /*
2    Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #include <winsock2.h>
26 #include <ws2tcpip.h>
27 
28 /* Link with winsock library */
29 #pragma comment(lib, "ws2_32")
30 
31 #include <ndb_global.h>
32 
33 #define MY_SOCKET_FORMAT "%p"
34 #define MY_SOCKET_FORMAT_VALUE(x) (x.s)
35 
36 typedef int ndb_socket_len_t;
37 
38 typedef SOCKET ndb_native_socket_t;
39 typedef struct { SOCKET s; } ndb_socket_t;
40 
41 static inline ndb_native_socket_t
ndb_socket_get_native(ndb_socket_t s)42 ndb_socket_get_native(ndb_socket_t s)
43 {
44   return s.s;
45 }
46 
47 static inline
ndb_socket_valid(ndb_socket_t s)48 int ndb_socket_valid(ndb_socket_t s)
49 {
50   return (s.s != INVALID_SOCKET);
51 }
52 
53 static inline
ndb_socket_invalidate(ndb_socket_t * s)54 ndb_socket_t* ndb_socket_invalidate(ndb_socket_t *s)
55 {
56   s->s= INVALID_SOCKET;
57   return s;
58 }
59 
60 static inline ndb_socket_t
ndb_socket_create_invalid()61 ndb_socket_create_invalid()
62 {
63   ndb_socket_t s;
64   ndb_socket_invalidate(&s);
65   return s;
66 }
67 
68 static inline
ndb_socket_close(ndb_socket_t s)69 int ndb_socket_close(ndb_socket_t s)
70 {
71   return closesocket(s.s);
72 }
73 
ndb_socket_errno()74 static inline int ndb_socket_errno()
75 {
76   return WSAGetLastError();
77 }
78 
79 static inline
ndb_socket_create(int domain,int type,int protocol)80 ndb_socket_t ndb_socket_create(int domain, int type,int protocol)
81 {
82   ndb_socket_t s;
83   s.s= socket(domain, type, protocol);
84 
85   return s;
86 }
87 
88 static inline
ndb_recv(ndb_socket_t s,char * buf,size_t len,int flags)89 ssize_t ndb_recv(ndb_socket_t s, char* buf, size_t len, int flags)
90 {
91   int ret= recv(s.s, buf, (int)len, flags);
92   if (ret == SOCKET_ERROR)
93     return -1;
94   return ret;
95 }
96 
97 static inline
ndb_send(ndb_socket_t s,const char * buf,size_t len,int flags)98 ssize_t ndb_send(ndb_socket_t s, const char* buf, size_t len, int flags)
99 {
100   int ret= send(s.s, buf, (int)len, flags);
101   if (ret == SOCKET_ERROR)
102     return -1;
103   return ret;
104 }
105 
106 static inline
ndb_socket_reuseaddr(ndb_socket_t s,int enable)107 int ndb_socket_reuseaddr(ndb_socket_t s, int enable)
108 {
109   const int on = enable;
110   return setsockopt(s.s, SOL_SOCKET, SO_REUSEADDR,
111                     (const char*)&on, sizeof(on));
112 }
113 
114 static inline
ndb_socket_nonblock(ndb_socket_t s,int enable)115 int ndb_socket_nonblock(ndb_socket_t s, int enable)
116 {
117   unsigned long  ul = enable;
118 
119   if(ioctlsocket(s.s, FIONBIO, &ul))
120     return ndb_socket_errno();
121 
122   return 0;
123 }
124 
125 static inline
ndb_bind_inet(ndb_socket_t s,const struct sockaddr_in * addr)126 int ndb_bind_inet(ndb_socket_t s, const struct sockaddr_in *addr)
127 {
128   return bind(s.s, (const struct sockaddr*)addr, sizeof(struct sockaddr_in));
129 }
130 
131 static inline
ndb_socket_get_port(ndb_socket_t s,unsigned short * port)132 int ndb_socket_get_port(ndb_socket_t s, unsigned short *port)
133 {
134   struct sockaddr_in servaddr;
135   ndb_socket_len_t sock_len = sizeof(servaddr);
136   if(getsockname(s.s, (struct sockaddr*)&servaddr, &sock_len) < 0) {
137     return 1;
138   }
139 
140   *port= ntohs(servaddr.sin_port);
141   return 0;
142 }
143 
144 static inline
ndb_listen(ndb_socket_t s,int backlog)145 int ndb_listen(ndb_socket_t s, int backlog)
146 {
147   return listen(s.s, backlog);
148 }
149 
150 static inline
ndb_accept(ndb_socket_t s,struct sockaddr * addr,ndb_socket_len_t * addrlen)151 ndb_socket_t ndb_accept(ndb_socket_t s, struct sockaddr *addr,
152                        ndb_socket_len_t *addrlen)
153 {
154   ndb_socket_t r;
155   r.s= accept(s.s, addr, addrlen);
156   return r;
157 }
158 
159 static inline
ndb_connect_inet(ndb_socket_t s,const struct sockaddr_in * addr)160 int ndb_connect_inet(ndb_socket_t s, const struct sockaddr_in *addr)
161 {
162   return connect(s.s, (const struct sockaddr*) addr,
163                  sizeof(struct sockaddr_in));
164 }
165 
166 static inline
ndb_getsockopt(ndb_socket_t s,int level,int optname,void * optval,ndb_socket_len_t * optlen)167 int ndb_getsockopt(ndb_socket_t s, int level, int optname,
168                    void *optval, ndb_socket_len_t *optlen)
169 {
170   return getsockopt(s.s, level, optname, (char*)optval, optlen);
171 }
172 
173 static inline
ndb_setsockopt(ndb_socket_t s,int level,int optname,void * optval,ndb_socket_len_t optlen)174 int ndb_setsockopt(ndb_socket_t s, int level, int optname,
175                    void *optval, ndb_socket_len_t optlen)
176 {
177   return setsockopt(s.s, level, optname, (char*)optval, optlen);
178 }
179 
180 static inline
ndb_socket_connect_address(ndb_socket_t s,struct in_addr * a)181 int ndb_socket_connect_address(ndb_socket_t s, struct in_addr *a)
182 {
183   struct sockaddr_in addr;
184   ndb_socket_len_t addrlen= sizeof(addr);
185   if(getpeername(s.s, (struct sockaddr*)&addr, &addrlen)==SOCKET_ERROR)
186     return ndb_socket_errno();
187 
188   *a= addr.sin_addr;
189   return 0;
190 }
191 
192 static inline
ndb_getpeername(ndb_socket_t s,struct sockaddr * a,ndb_socket_len_t * addrlen)193 int ndb_getpeername(ndb_socket_t s, struct sockaddr *a,
194                     ndb_socket_len_t *addrlen)
195 {
196   if(getpeername(s.s, a, addrlen))
197     return ndb_socket_errno();
198 
199   return 0;
200 }
201 
202 static inline
ndb_getsockname(ndb_socket_t s,struct sockaddr * a,ndb_socket_len_t * addrlen)203 int ndb_getsockname(ndb_socket_t s, struct sockaddr *a,
204                                  ndb_socket_len_t *addrlen)
205 {
206   if(getsockname(s.s, a, addrlen))
207     return 1;
208 
209   return 0;
210 }
211 
212 /*
213  * NOTE: the order of len and base are *DIFFERENT* on Linux and Win32.
214  * casting our iovec to a WSABUF is fine as it's the same structure,
215  * just with different names for the members.
216  */
217 struct iovec {
218   u_long iov_len;   /* 'u_long len' in WSABUF */
219   void*  iov_base;  /* 'char*  buf' in WSABUF */
220 };
221 
222 static inline
ndb_socket_readv(ndb_socket_t s,const struct iovec * iov,int iovcnt)223 ssize_t ndb_socket_readv(ndb_socket_t s, const struct iovec *iov,
224                          int iovcnt)
225 {
226   DWORD rv=0;
227   if (WSARecv(s.s,(LPWSABUF)iov,iovcnt,&rv,0,0,0) == SOCKET_ERROR)
228     return -1;
229   return rv;
230 }
231 
232 static inline
ndb_socket_writev(ndb_socket_t s,const struct iovec * iov,int iovcnt)233 ssize_t ndb_socket_writev(ndb_socket_t s, const struct iovec *iov,
234                                        int iovcnt)
235 {
236   DWORD rv=0;
237   if (WSASend(s.s,(LPWSABUF)iov,iovcnt,&rv,0,0,0) == SOCKET_ERROR)
238     return -1;
239   return rv;
240 }
241