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 31typedef 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 */ 39static 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 */ 95BOOL WINAPI 96DllMain(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 */ 122int 123dbgsysListen(int fd, int backlog) { 124 return listen(fd, backlog); 125} 126 127int 128dbgsysConnect(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 138int 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 173int 174dbgsysAccept(int fd, struct sockaddr *name, socklen_t *namelen) { 175 return (int)accept(fd, name, namelen); 176} 177 178int 179dbgsysRecvFrom(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 184int 185dbgsysSendTo(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 190int 191dbgsysRecv(int fd, char *buf, size_t nBytes, int flags) { 192 return recv(fd, buf, (int) nBytes, flags); 193} 194 195int 196dbgsysSend(int fd, char *buf, size_t nBytes, int flags) { 197 return send(fd, buf, (int)nBytes, flags); 198} 199 200struct hostent * 201dbgsysGetHostByName(char *hostname) { 202 return gethostbyname(hostname); 203} 204 205unsigned short 206dbgsysHostToNetworkShort(unsigned short hostshort) { 207 return htons(hostshort); 208} 209 210int 211dbgsysSocket(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 219int 220dbgsysSocketClose(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 234int 235dbgsysBind(int fd, struct sockaddr *name, socklen_t namelen) { 236 return bind(fd, name, namelen); 237} 238 239 240uint32_t 241dbgsysInetAddr(const char* cp) { 242 return (uint32_t)inet_addr(cp); 243} 244 245uint32_t 246dbgsysHostToNetworkLong(uint32_t hostlong) { 247 return (uint32_t)htonl((u_long)hostlong); 248} 249 250unsigned short 251dbgsysNetworkToHostShort(unsigned short netshort) { 252 return ntohs(netshort); 253} 254 255int 256dbgsysGetSocketName(int fd, struct sockaddr *name, socklen_t *namelen) { 257 return getsockname(fd, name, namelen); 258} 259 260uint32_t 261dbgsysNetworkToHostLong(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 272int 273dbgsysSetSocketOption(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 332int 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 349int 350dbgsysPoll(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 381int 382dbgsysGetLastIOError(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 408int 409dbgsysTlsAlloc() { 410 return TlsAlloc(); 411} 412 413void 414dbgsysTlsFree(int index) { 415 TlsFree(index); 416} 417 418void 419dbgsysTlsPut(int index, void *value) { 420 TlsSetValue(index, value); 421} 422 423void * 424dbgsysTlsGet(int index) { 425 return TlsGetValue(index); 426} 427 428#define FT2INT64(ft) \ 429 ((INT64)(ft).dwHighDateTime << 32 | (INT64)(ft).dwLowDateTime) 430 431long 432dbgsysCurrentTimeMillis() { 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