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