1 /*
2  * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 #include <windows.h>
26 #include <winsock2.h>
27 
28 #include "sysSocket.h"
29 #include "socketTransport.h"
30 
31 typedef jboolean bool_t;
32 
33 /*
34  * Table of Windows Sockets errors, the specific exception we
35  * throw for the error, and the error text.
36  *
37  * Note that this table excludes OS dependent errors.
38  */
39 static struct {
40     int errCode;
41     const char *errString;
42 } const winsock_errors[] = {
43     { WSAEPROVIDERFAILEDINIT,   "Provider initialization failed (check %SystemRoot%)" },
44     { WSAEACCES,                "Permission denied" },
45     { WSAEADDRINUSE,            "Address already in use" },
46     { WSAEADDRNOTAVAIL,         "Cannot assign requested address" },
47     { WSAEAFNOSUPPORT,          "Address family not supported by protocol family" },
48     { WSAEALREADY,              "Operation already in progress" },
49     { WSAECONNABORTED,          "Software caused connection abort" },
50     { WSAECONNREFUSED,          "Connection refused" },
51     { WSAECONNRESET,            "Connection reset by peer" },
52     { WSAEDESTADDRREQ,          "Destination address required" },
53     { WSAEFAULT,                "Bad address" },
54     { WSAEHOSTDOWN,             "Host is down" },
55     { WSAEHOSTUNREACH,          "No route to host" },
56     { WSAEINPROGRESS,           "Operation now in progress" },
57     { WSAEINTR,                 "Interrupted function call" },
58     { WSAEINVAL,                "Invalid argument" },
59     { WSAEISCONN,               "Socket is already connected" },
60     { WSAEMFILE,                "Too many open files" },
61     { WSAEMSGSIZE,              "The message is larger than the maximum supported by the underlying transport" },
62     { WSAENETDOWN,              "Network is down" },
63     { WSAENETRESET,             "Network dropped connection on reset" },
64     { WSAENETUNREACH,           "Network is unreachable" },
65     { WSAENOBUFS,               "No buffer space available (maximum connections reached?)" },
66     { WSAENOPROTOOPT,           "Bad protocol option" },
67     { WSAENOTCONN,              "Socket is not connected" },
68     { WSAENOTSOCK,              "Socket operation on nonsocket" },
69     { WSAEOPNOTSUPP,            "Operation not supported" },
70     { WSAEPFNOSUPPORT,          "Protocol family not supported" },
71     { WSAEPROCLIM,              "Too many processes" },
72     { WSAEPROTONOSUPPORT,       "Protocol not supported" },
73     { WSAEPROTOTYPE,            "Protocol wrong type for socket" },
74     { WSAESHUTDOWN,             "Cannot send after socket shutdown" },
75     { WSAESOCKTNOSUPPORT,       "Socket type not supported" },
76     { WSAETIMEDOUT,             "Connection timed out" },
77     { WSATYPE_NOT_FOUND,        "Class type not found" },
78     { WSAEWOULDBLOCK,           "Resource temporarily unavailable" },
79     { WSAHOST_NOT_FOUND,        "Host not found" },
80     { WSA_NOT_ENOUGH_MEMORY,    "Insufficient memory available" },
81     { WSANOTINITIALISED,        "Successful WSAStartup not yet performed" },
82     { WSANO_DATA,               "Valid name, no data record of requested type" },
83     { WSANO_RECOVERY,           "This is a nonrecoverable error" },
84     { WSASYSNOTREADY,           "Network subsystem is unavailable" },
85     { WSATRY_AGAIN,             "Nonauthoritative host not found" },
86     { WSAVERNOTSUPPORTED,       "Winsock.dll version out of range" },
87     { WSAEDISCON,               "Graceful shutdown in progress" },
88     { WSA_OPERATION_ABORTED,    "Overlapped operation aborted" },
89 };
90 
91 
92 /*
93  * Initialize Windows Sockets API support
94  */
95 BOOL WINAPI
DllMain(HINSTANCE hinst,DWORD reason,LPVOID reserved)96 DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
97 {
98     WSADATA wsadata;
99 
100     switch (reason) {
101         case DLL_PROCESS_ATTACH:
102             if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0) {
103                 return FALSE;
104             }
105             break;
106 
107         case DLL_PROCESS_DETACH:
108             WSACleanup();
109             break;
110 
111         default:
112             break;
113     }
114     return TRUE;
115 }
116 
117 /*
118  * If we get a nonnull function pointer it might still be the case
119  * that some other thread is in the process of initializing the socket
120  * function pointer table, but our pointer should still be good.
121  */
122 int
dbgsysListen(int fd,int backlog)123 dbgsysListen(int fd, int backlog) {
124     return listen(fd, backlog);
125 }
126 
127 int
dbgsysConnect(int fd,struct sockaddr * name,socklen_t namelen)128 dbgsysConnect(int fd, struct sockaddr *name, socklen_t namelen) {
129     int rv = connect(fd, name, namelen);
130     if (rv == SOCKET_ERROR) {
131         if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK) {
132             return DBG_EINPROGRESS;
133         }
134     }
135     return rv;
136 }
137 
dbgsysFinishConnect(int fd,int timeout)138 int dbgsysFinishConnect(int fd, int timeout) {
139     int rv;
140     struct timeval t;
141     fd_set wr, ex;
142 
143     t.tv_sec = timeout / 1000;
144     t.tv_usec = (timeout % 1000) * 1000;
145 
146     FD_ZERO(&wr);
147     FD_ZERO(&ex);
148     FD_SET((unsigned int)fd, &wr);
149     FD_SET((unsigned int)fd, &ex);
150 
151     rv = select(fd+1, 0, &wr, &ex, &t);
152     if (rv == 0) {
153         return SYS_ERR;     /* timeout */
154     }
155 
156     /*
157      * Check if there was an error - this is preferable to check if
158      * the socket is writable because some versions of Windows don't
159      * report a connected socket as being writable.
160      */
161     if (!FD_ISSET(fd, &ex)) {
162         return SYS_OK;
163     }
164 
165     /*
166      * Unable to establish connection - to get the reason we must
167      * call getsockopt.
168      */
169     return SYS_ERR;
170 }
171 
172 
173 int
dbgsysAccept(int fd,struct sockaddr * name,socklen_t * namelen)174 dbgsysAccept(int fd, struct sockaddr *name, socklen_t *namelen) {
175     return (int)accept(fd, name, namelen);
176 }
177 
178 int
dbgsysRecvFrom(int fd,char * buf,size_t nBytes,int flags,struct sockaddr * from,socklen_t * fromlen)179 dbgsysRecvFrom(int fd, char *buf, size_t nBytes,
180                   int flags, struct sockaddr *from, socklen_t *fromlen) {
181     return recvfrom(fd, buf, (int)nBytes, flags, from, fromlen);
182 }
183 
184 int
dbgsysSendTo(int fd,char * buf,size_t len,int flags,struct sockaddr * to,socklen_t tolen)185 dbgsysSendTo(int fd, char *buf, size_t len,
186                 int flags, struct sockaddr *to, socklen_t tolen) {
187     return sendto(fd, buf, (int)len, flags, to, tolen);
188 }
189 
190 int
dbgsysRecv(int fd,char * buf,size_t nBytes,int flags)191 dbgsysRecv(int fd, char *buf, size_t nBytes, int flags) {
192     return recv(fd, buf, (int) nBytes, flags);
193 }
194 
195 int
dbgsysSend(int fd,char * buf,size_t nBytes,int flags)196 dbgsysSend(int fd, char *buf, size_t nBytes, int flags) {
197     return send(fd, buf, (int)nBytes, flags);
198 }
199 
200 struct hostent *
dbgsysGetHostByName(char * hostname)201 dbgsysGetHostByName(char *hostname) {
202     return gethostbyname(hostname);
203 }
204 
205 unsigned short
dbgsysHostToNetworkShort(unsigned short hostshort)206 dbgsysHostToNetworkShort(unsigned short hostshort) {
207     return htons(hostshort);
208 }
209 
210 int
dbgsysSocket(int domain,int type,int protocol)211 dbgsysSocket(int domain, int type, int protocol) {
212   int fd = (int)socket(domain, type, protocol);
213   if (fd != SOCKET_ERROR) {
214       SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
215   }
216   return fd;
217 }
218 
219 int
dbgsysSocketClose(int fd)220 dbgsysSocketClose(int fd) {
221     struct linger l;
222     int len = sizeof(l);
223 
224     if (getsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&l, &len) == 0) {
225         if (l.l_onoff == 0) {
226             WSASendDisconnect(fd, NULL);
227         }
228     }
229     return closesocket(fd);
230 }
231 
232 /* Additions to original follow */
233 
234 int
dbgsysBind(int fd,struct sockaddr * name,socklen_t namelen)235 dbgsysBind(int fd, struct sockaddr *name, socklen_t namelen) {
236     return bind(fd, name, namelen);
237 }
238 
239 
240 uint32_t
dbgsysInetAddr(const char * cp)241 dbgsysInetAddr(const char* cp) {
242     return (uint32_t)inet_addr(cp);
243 }
244 
245 uint32_t
dbgsysHostToNetworkLong(uint32_t hostlong)246 dbgsysHostToNetworkLong(uint32_t hostlong) {
247     return (uint32_t)htonl((u_long)hostlong);
248 }
249 
250 unsigned short
dbgsysNetworkToHostShort(unsigned short netshort)251 dbgsysNetworkToHostShort(unsigned short netshort) {
252     return ntohs(netshort);
253 }
254 
255 int
dbgsysGetSocketName(int fd,struct sockaddr * name,socklen_t * namelen)256 dbgsysGetSocketName(int fd, struct sockaddr *name, socklen_t *namelen) {
257     return getsockname(fd, name, namelen);
258 }
259 
260 uint32_t
dbgsysNetworkToHostLong(uint32_t netlong)261 dbgsysNetworkToHostLong(uint32_t netlong) {
262     return (uint32_t)ntohl((u_long)netlong);
263 }
264 
265 /*
266  * Below Adapted from PlainSocketImpl.c, win32 version 1.18. Changed exception
267  * throws to returns of SYS_ERR; we should improve the error codes
268  * eventually. Changed java objects to values the debugger back end can
269  * more easily deal with.
270  */
271 
272 int
dbgsysSetSocketOption(int fd,jint cmd,jboolean on,jvalue value)273 dbgsysSetSocketOption(int fd, jint cmd, jboolean on, jvalue value)
274 {
275     if (cmd == TCP_NODELAY) {
276         struct protoent *proto = getprotobyname("TCP");
277         int tcp_level = (proto == 0 ? IPPROTO_TCP: proto->p_proto);
278         long onl = (long)on;
279 
280         if (setsockopt(fd, tcp_level, TCP_NODELAY,
281                        (char *)&onl, sizeof(long)) < 0) {
282                 return SYS_ERR;
283         }
284     } else if (cmd == SO_LINGER) {
285         struct linger arg;
286         arg.l_onoff = on;
287 
288         if(on) {
289             arg.l_linger = (unsigned short)value.i;
290             if(setsockopt(fd, SOL_SOCKET, SO_LINGER,
291                           (char*)&arg, sizeof(arg)) < 0) {
292                 return SYS_ERR;
293             }
294         } else {
295             if (setsockopt(fd, SOL_SOCKET, SO_LINGER,
296                            (char*)&arg, sizeof(arg)) < 0) {
297                 return SYS_ERR;
298             }
299         }
300     } else if (cmd == SO_SNDBUF) {
301         jint buflen = value.i;
302         if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
303                        (char *)&buflen, sizeof(buflen)) < 0) {
304             return SYS_ERR;
305         }
306     } else if (cmd == SO_REUSEADDR) {
307         /*
308          * On Windows the SO_REUSEADDR socket option doesn't implement
309          * BSD semantics. Specifically, the socket option allows multiple
310          * processes to bind to the same address/port rather than allowing
311          * a process to bind with a previous connection in the TIME_WAIT
312          * state. Hence on Windows we never enable this option for TCP
313          * option.
314          */
315         int sotype, arglen=sizeof(sotype);
316         if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) == SOCKET_ERROR) {
317             return SYS_ERR;
318         }
319         if (sotype != SOCK_STREAM) {
320             int oni = (int)on;
321             if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
322                        (char *)&oni, sizeof(oni)) == SOCKET_ERROR) {
323                 return SYS_ERR;
324             }
325         }
326     } else {
327         return SYS_ERR;
328     }
329     return SYS_OK;
330 }
331 
dbgsysConfigureBlocking(int fd,jboolean blocking)332 int dbgsysConfigureBlocking(int fd, jboolean blocking) {
333     u_long argp;
334     int result = 0;
335 
336     if (blocking == JNI_FALSE) {
337         argp = 1;
338     } else {
339         argp = 0;
340     }
341     result = ioctlsocket(fd, FIONBIO, &argp);
342     if (result == SOCKET_ERROR) {
343         return SYS_ERR;
344     } else {
345         return SYS_OK;
346     }
347 }
348 
349 int
dbgsysPoll(int fd,jboolean rd,jboolean wr,long timeout)350 dbgsysPoll(int fd, jboolean rd, jboolean wr, long timeout) {
351     int rv;
352     struct timeval t;
353     fd_set rd_tbl, wr_tbl;
354 
355     t.tv_sec = timeout / 1000;
356     t.tv_usec = (timeout % 1000) * 1000;
357 
358     FD_ZERO(&rd_tbl);
359     if (rd) {
360         FD_SET((unsigned int)fd, &rd_tbl);
361     }
362 
363     FD_ZERO(&wr_tbl);
364     if (wr) {
365         FD_SET((unsigned int)fd, &wr_tbl);
366     }
367 
368     rv = select(fd+1, &rd_tbl, &wr_tbl, 0, &t);
369     if (rv >= 0) {
370         rv = 0;
371         if (FD_ISSET(fd, &rd_tbl)) {
372             rv |= DBG_POLLIN;
373         }
374         if (FD_ISSET(fd, &wr_tbl)) {
375             rv |= DBG_POLLOUT;
376         }
377     }
378     return rv;
379 }
380 
381 int
dbgsysGetLastIOError(char * buf,jint size)382 dbgsysGetLastIOError(char *buf, jint size) {
383     int table_size = sizeof(winsock_errors) /
384                      sizeof(winsock_errors[0]);
385     int i;
386     int error = WSAGetLastError();
387 
388     /*
389      * Check table for known winsock errors
390      */
391     i=0;
392     while (i < table_size) {
393         if (error == winsock_errors[i].errCode) {
394             break;
395         }
396         i++;
397     }
398 
399     if (i < table_size) {
400         strcpy(buf, winsock_errors[i].errString);
401     } else {
402         sprintf(buf, "winsock error %d", error);
403     }
404     return 0;
405 }
406 
407 
408 int
dbgsysTlsAlloc()409 dbgsysTlsAlloc() {
410     return TlsAlloc();
411 }
412 
413 void
dbgsysTlsFree(int index)414 dbgsysTlsFree(int index) {
415     TlsFree(index);
416 }
417 
418 void
dbgsysTlsPut(int index,void * value)419 dbgsysTlsPut(int index, void *value) {
420     TlsSetValue(index, value);
421 }
422 
423 void *
dbgsysTlsGet(int index)424 dbgsysTlsGet(int index) {
425     return TlsGetValue(index);
426 }
427 
428 #define FT2INT64(ft) \
429         ((INT64)(ft).dwHighDateTime << 32 | (INT64)(ft).dwLowDateTime)
430 
431 long
dbgsysCurrentTimeMillis()432 dbgsysCurrentTimeMillis() {
433     static long fileTime_1_1_70 = 0;    /* midnight 1/1/70 */
434     SYSTEMTIME st0;
435     FILETIME   ft0;
436 
437     /* initialize on first usage */
438     if (fileTime_1_1_70 == 0) {
439         memset(&st0, 0, sizeof(st0));
440         st0.wYear  = 1970;
441         st0.wMonth = 1;
442         st0.wDay   = 1;
443         SystemTimeToFileTime(&st0, &ft0);
444         fileTime_1_1_70 = FT2INT64(ft0);
445     }
446 
447     GetSystemTime(&st0);
448     SystemTimeToFileTime(&st0, &ft0);
449 
450     return (FT2INT64(ft0) - fileTime_1_1_70) / 10000;
451 }
452