Path: blob/master/src/java.base/windows/native/libnet/net_util_md.c
41119 views
/*1* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24#include "net_util.h"2526#include "java_net_InetAddress.h"27#include "java_net_SocketOptions.h"2829// Taken from mstcpip.h in Windows SDK 8.0 or newer.30#define SIO_LOOPBACK_FAST_PATH _WSAIOW(IOC_VENDOR,16)3132#ifndef IPTOS_TOS_MASK33#define IPTOS_TOS_MASK 0x1e34#endif35#ifndef IPTOS_PREC_MASK36#define IPTOS_PREC_MASK 0xe037#endif3839/* true if SO_RCVTIMEO is supported */40jboolean isRcvTimeoutSupported = JNI_TRUE;4142/*43* Table of Windows Sockets errors, the specific exception we44* throw for the error, and the error text.45*46* Note that this table excludes OS dependent errors.47*48* Latest list of Windows Sockets errors can be found at :-49* http://msdn.microsoft.com/library/psdk/winsock/errors_3wc2.htm50*/51static struct {52int errCode;53const char *exc;54const char *errString;55} const winsock_errors[] = {56{ WSAEACCES, 0, "Permission denied" },57{ WSAEADDRINUSE, "BindException", "Address already in use" },58{ WSAEADDRNOTAVAIL, "BindException", "Cannot assign requested address" },59{ WSAEAFNOSUPPORT, 0, "Address family not supported by protocol family" },60{ WSAEALREADY, 0, "Operation already in progress" },61{ WSAECONNABORTED, 0, "Software caused connection abort" },62{ WSAECONNREFUSED, "ConnectException", "Connection refused" },63{ WSAECONNRESET, 0, "Connection reset by peer" },64{ WSAEDESTADDRREQ, 0, "Destination address required" },65{ WSAEFAULT, 0, "Bad address" },66{ WSAEHOSTDOWN, 0, "Host is down" },67{ WSAEHOSTUNREACH, "NoRouteToHostException", "No route to host" },68{ WSAEINPROGRESS, 0, "Operation now in progress" },69{ WSAEINTR, 0, "Interrupted function call" },70{ WSAEINVAL, 0, "Invalid argument" },71{ WSAEISCONN, 0, "Socket is already connected" },72{ WSAEMFILE, 0, "Too many open files" },73{ WSAEMSGSIZE, 0, "The message is larger than the maximum supported by the underlying transport" },74{ WSAENETDOWN, 0, "Network is down" },75{ WSAENETRESET, 0, "Network dropped connection on reset" },76{ WSAENETUNREACH, 0, "Network is unreachable" },77{ WSAENOBUFS, 0, "No buffer space available (maximum connections reached?)" },78{ WSAENOPROTOOPT, 0, "Bad protocol option" },79{ WSAENOTCONN, 0, "Socket is not connected" },80{ WSAENOTSOCK, 0, "Socket operation on nonsocket" },81{ WSAEOPNOTSUPP, 0, "Operation not supported" },82{ WSAEPFNOSUPPORT, 0, "Protocol family not supported" },83{ WSAEPROCLIM, 0, "Too many processes" },84{ WSAEPROTONOSUPPORT, 0, "Protocol not supported" },85{ WSAEPROTOTYPE, 0, "Protocol wrong type for socket" },86{ WSAESHUTDOWN, 0, "Cannot send after socket shutdown" },87{ WSAESOCKTNOSUPPORT, 0, "Socket type not supported" },88{ WSAETIMEDOUT, "ConnectException", "Connection timed out" },89{ WSATYPE_NOT_FOUND, 0, "Class type not found" },90{ WSAEWOULDBLOCK, 0, "Resource temporarily unavailable" },91{ WSAHOST_NOT_FOUND, 0, "Host not found" },92{ WSA_NOT_ENOUGH_MEMORY, 0, "Insufficient memory available" },93{ WSANOTINITIALISED, 0, "Successful WSAStartup not yet performed" },94{ WSANO_DATA, 0, "Valid name, no data record of requested type" },95{ WSANO_RECOVERY, 0, "This is a nonrecoverable error" },96{ WSASYSNOTREADY, 0, "Network subsystem is unavailable" },97{ WSATRY_AGAIN, 0, "Nonauthoritative host not found" },98{ WSAVERNOTSUPPORTED, 0, "Winsock.dll version out of range" },99{ WSAEDISCON, 0, "Graceful shutdown in progress" },100{ WSA_OPERATION_ABORTED, 0, "Overlapped operation aborted" },101};102103/*104* Initialize Windows Sockets API support105*/106BOOL WINAPI107DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)108{109WSADATA wsadata;110111switch (reason) {112case DLL_PROCESS_ATTACH:113if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0) {114return FALSE;115}116break;117118case DLL_PROCESS_DETACH:119WSACleanup();120break;121122default:123break;124}125return TRUE;126}127128void platformInit() {}129130/*131* Since winsock doesn't have the equivalent of strerror(errno)132* use table to lookup error text for the error.133*/134JNIEXPORT void JNICALL135NET_ThrowNew(JNIEnv *env, int errorNum, char *msg)136{137int i;138int table_size = sizeof(winsock_errors) /139sizeof(winsock_errors[0]);140char exc[256];141char fullMsg[256];142char *excP = NULL;143144/*145* If exception already throw then don't overwrite it.146*/147if ((*env)->ExceptionOccurred(env)) {148return;149}150151/*152* Default message text if not provided153*/154if (!msg) {155msg = "no further information";156}157158/*159* Check table for known winsock errors160*/161i=0;162while (i < table_size) {163if (errorNum == winsock_errors[i].errCode) {164break;165}166i++;167}168169/*170* If found get pick the specific exception and error171* message corresponding to this error.172*/173if (i < table_size) {174excP = (char *)winsock_errors[i].exc;175jio_snprintf(fullMsg, sizeof(fullMsg), "%s: %s",176(char *)winsock_errors[i].errString, msg);177} else {178jio_snprintf(fullMsg, sizeof(fullMsg),179"Unrecognized Windows Sockets error: %d: %s",180errorNum, msg);181182}183184/*185* Throw SocketException if no specific exception for this186* error.187*/188if (excP == NULL) {189excP = "SocketException";190}191sprintf(exc, "%s%s", JNU_JAVANETPKG, excP);192JNU_ThrowByName(env, exc, fullMsg);193}194195void196NET_ThrowCurrent(JNIEnv *env, char *msg)197{198NET_ThrowNew(env, WSAGetLastError(), msg);199}200201void202NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,203const char *defaultDetail) {204JNU_ThrowByNameWithMessageAndLastError(env, name, defaultDetail);205}206207jfieldID208NET_GetFileDescriptorID(JNIEnv *env)209{210jclass cls = (*env)->FindClass(env, "java/io/FileDescriptor");211CHECK_NULL_RETURN(cls, NULL);212return (*env)->GetFieldID(env, cls, "fd", "I");213}214215jint IPv4_supported()216{217/* TODO: properly check for IPv4 support on Windows */218return JNI_TRUE;219}220221jint IPv6_supported()222{223SOCKET s = socket(AF_INET6, SOCK_STREAM, 0) ;224if (s == INVALID_SOCKET) {225return JNI_FALSE;226}227closesocket(s);228229return JNI_TRUE;230}231232jint reuseport_supported()233{234/* SO_REUSEPORT is not supported on Windows */235return JNI_FALSE;236}237238/* call NET_MapSocketOptionV6 for the IPv6 fd only239* and NET_MapSocketOption for the IPv4 fd240*/241JNIEXPORT int JNICALL242NET_MapSocketOptionV6(jint cmd, int *level, int *optname) {243244switch (cmd) {245case java_net_SocketOptions_IP_MULTICAST_IF:246case java_net_SocketOptions_IP_MULTICAST_IF2:247*level = IPPROTO_IPV6;248*optname = IPV6_MULTICAST_IF;249return 0;250251case java_net_SocketOptions_IP_MULTICAST_LOOP:252*level = IPPROTO_IPV6;253*optname = IPV6_MULTICAST_LOOP;254return 0;255}256return NET_MapSocketOption (cmd, level, optname);257}258259/*260* Map the Java level socket option to the platform specific261* level and option name.262*/263264JNIEXPORT int JNICALL265NET_MapSocketOption(jint cmd, int *level, int *optname) {266267typedef struct {268jint cmd;269int level;270int optname;271} sockopts;272273static sockopts opts[] = {274{ java_net_SocketOptions_TCP_NODELAY, IPPROTO_TCP, TCP_NODELAY },275{ java_net_SocketOptions_SO_OOBINLINE, SOL_SOCKET, SO_OOBINLINE },276{ java_net_SocketOptions_SO_LINGER, SOL_SOCKET, SO_LINGER },277{ java_net_SocketOptions_SO_SNDBUF, SOL_SOCKET, SO_SNDBUF },278{ java_net_SocketOptions_SO_RCVBUF, SOL_SOCKET, SO_RCVBUF },279{ java_net_SocketOptions_SO_KEEPALIVE, SOL_SOCKET, SO_KEEPALIVE },280{ java_net_SocketOptions_SO_REUSEADDR, SOL_SOCKET, SO_REUSEADDR },281{ java_net_SocketOptions_SO_BROADCAST, SOL_SOCKET, SO_BROADCAST },282{ java_net_SocketOptions_IP_MULTICAST_IF, IPPROTO_IP, IP_MULTICAST_IF },283{ java_net_SocketOptions_IP_MULTICAST_LOOP, IPPROTO_IP, IP_MULTICAST_LOOP },284{ java_net_SocketOptions_IP_TOS, IPPROTO_IP, IP_TOS },285286};287288289int i;290291/*292* Map the Java level option to the native level293*/294for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) {295if (cmd == opts[i].cmd) {296*level = opts[i].level;297*optname = opts[i].optname;298return 0;299}300}301302/* not found */303return -1;304}305306307/*308* Wrapper for setsockopt dealing with Windows specific issues :-309*310* IP_TOS and IP_MULTICAST_LOOP can't be set on some Windows311* editions.312*313* The value for the type-of-service (TOS) needs to be masked314* to get consistent behaviour with other operating systems.315*/316JNIEXPORT int JNICALL317NET_SetSockOpt(int s, int level, int optname, const void *optval,318int optlen)319{320int rv = 0;321int parg = 0;322int plen = sizeof(parg);323324if (level == IPPROTO_IP && optname == IP_TOS) {325int *tos = (int *)optval;326*tos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);327}328329if (optname == SO_REUSEADDR) {330/*331* Do not set SO_REUSEADDE if SO_EXCLUSIVEADDUSE is already set332*/333rv = NET_GetSockOpt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *)&parg, &plen);334if (rv == 0 && parg == 1) {335return rv;336}337}338339rv = setsockopt(s, level, optname, optval, optlen);340341if (rv == SOCKET_ERROR) {342/*343* IP_TOS & IP_MULTICAST_LOOP can't be set on some versions344* of Windows.345*/346if ((WSAGetLastError() == WSAENOPROTOOPT) &&347(level == IPPROTO_IP) &&348(optname == IP_TOS || optname == IP_MULTICAST_LOOP)) {349rv = 0;350}351352/*353* IP_TOS can't be set on unbound UDP sockets.354*/355if ((WSAGetLastError() == WSAEINVAL) &&356(level == IPPROTO_IP) &&357(optname == IP_TOS)) {358rv = 0;359}360}361362return rv;363}364365/*366* Wrapper for setsockopt dealing with Windows specific issues :-367*368* IP_TOS is not supported on some versions of Windows so369* instead return the default value for the OS.370*/371JNIEXPORT int JNICALL372NET_GetSockOpt(int s, int level, int optname, void *optval,373int *optlen)374{375int rv;376377if (level == IPPROTO_IPV6 && optname == IPV6_TCLASS) {378int *intopt = (int *)optval;379*intopt = 0;380*optlen = sizeof(*intopt);381return 0;382}383384rv = getsockopt(s, level, optname, optval, optlen);385386387/*388* IPPROTO_IP/IP_TOS is not supported on some Windows389* editions so return the default type-of-service390* value.391*/392if (rv == SOCKET_ERROR) {393394if (WSAGetLastError() == WSAENOPROTOOPT &&395level == IPPROTO_IP && optname == IP_TOS) {396397*((int *)optval) = 0;398rv = 0;399}400}401402return rv;403}404405JNIEXPORT int JNICALL406NET_SocketAvailable(int s, int *pbytes) {407u_long arg;408if (ioctlsocket((SOCKET)s, FIONREAD, &arg) == SOCKET_ERROR) {409return -1;410} else {411*pbytes = (int) arg;412return 0;413}414}415416/*417* Sets SO_ECLUSIVEADDRUSE if SO_REUSEADDR is not already set.418*/419void setExclusiveBind(int fd) {420int parg = 0;421int plen = sizeof(parg);422int rv = 0;423rv = NET_GetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&parg, &plen);424if (rv == 0 && parg == 0) {425parg = 1;426rv = NET_SetSockOpt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&parg, plen);427}428}429430/*431* Wrapper for bind winsock call - transparent converts an432* error related to binding to a port that has exclusive access433* into an error indicating the port is in use (facilitates434* better error reporting).435*436* Should be only called by the wrapper method NET_WinBind437*/438JNIEXPORT int JNICALL439NET_Bind(int s, SOCKETADDRESS *sa, int len)440{441int rv = 0;442rv = bind(s, &sa->sa, len);443444if (rv == SOCKET_ERROR) {445/*446* If bind fails with WSAEACCES it means that a privileged447* process has done an exclusive bind (NT SP4/2000/XP only).448*/449if (WSAGetLastError() == WSAEACCES) {450WSASetLastError(WSAEADDRINUSE);451}452}453454return rv;455}456457/*458* Wrapper for NET_Bind call. Sets SO_EXCLUSIVEADDRUSE459* if required, and then calls NET_BIND460*/461JNIEXPORT int JNICALL462NET_WinBind(int s, SOCKETADDRESS *sa, int len, jboolean exclBind)463{464if (exclBind == JNI_TRUE)465setExclusiveBind(s);466return NET_Bind(s, sa, len);467}468469JNIEXPORT int JNICALL470NET_SocketClose(int fd) {471struct linger l = {0, 0};472int ret = 0;473int len = sizeof (l);474if (getsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&l, &len) == 0) {475if (l.l_onoff == 0) {476shutdown(fd, SD_SEND);477}478}479ret = closesocket (fd);480return ret;481}482483JNIEXPORT int JNICALL484NET_Timeout(int fd, long timeout) {485int ret;486fd_set tbl;487struct timeval t;488t.tv_sec = timeout / 1000;489t.tv_usec = (timeout % 1000) * 1000;490FD_ZERO(&tbl);491FD_SET(fd, &tbl);492ret = select (fd + 1, &tbl, 0, 0, &t);493return ret;494}495496497/*498* differs from NET_Timeout() as follows:499*500* If timeout = -1, it blocks forever.501*502* returns 1 or 2 depending if only one or both sockets503* fire at same time.504*505* *fdret is (one of) the active fds. If both sockets506* fire at same time, *fdret = fd always.507*/508JNIEXPORT int JNICALL509NET_Timeout2(int fd, int fd1, long timeout, int *fdret) {510int ret;511fd_set tbl;512struct timeval t, *tP = &t;513if (timeout == -1) {514tP = 0;515} else {516t.tv_sec = timeout / 1000;517t.tv_usec = (timeout % 1000) * 1000;518}519FD_ZERO(&tbl);520FD_SET(fd, &tbl);521FD_SET(fd1, &tbl);522ret = select (0, &tbl, 0, 0, tP);523switch (ret) {524case 0:525return 0; /* timeout */526case 1:527if (FD_ISSET (fd, &tbl)) {528*fdret= fd;529} else {530*fdret= fd1;531}532return 1;533case 2:534*fdret= fd;535return 2;536}537return -1;538}539540541void dumpAddr (char *str, void *addr) {542struct sockaddr_in6 *a = (struct sockaddr_in6 *)addr;543int family = a->sin6_family;544printf ("%s\n", str);545if (family == AF_INET) {546struct sockaddr_in *him = (struct sockaddr_in *)addr;547printf ("AF_INET: port %d: %x\n", ntohs(him->sin_port),548ntohl(him->sin_addr.s_addr));549} else {550int i;551struct in6_addr *in = &a->sin6_addr;552printf ("AF_INET6 ");553printf ("port %d ", ntohs (a->sin6_port));554printf ("flow %d ", a->sin6_flowinfo);555printf ("addr ");556for (i=0; i<7; i++) {557printf ("%04x:", ntohs(in->s6_words[i]));558}559printf ("%04x", ntohs(in->s6_words[7]));560printf (" scope %d\n", a->sin6_scope_id);561}562}563564/* Macro, which cleans-up the iv6bind structure,565* closes the two sockets (if open),566* and returns SOCKET_ERROR. Used in NET_BindV6 only.567*/568569#define CLOSE_SOCKETS_AND_RETURN do { \570if (fd != -1) { \571closesocket (fd); \572fd = -1; \573} \574if (ofd != -1) { \575closesocket (ofd); \576ofd = -1; \577} \578if (close_fd != -1) { \579closesocket (close_fd); \580close_fd = -1; \581} \582if (close_ofd != -1) { \583closesocket (close_ofd); \584close_ofd = -1; \585} \586b->ipv4_fd = b->ipv6_fd = -1; \587return SOCKET_ERROR; \588} while(0)589590/*591* if ipv6 is available, call NET_BindV6 to bind to the required address/port.592* Because the same port number may need to be reserved in both v4 and v6 space,593* this may require socket(s) to be re-opened. Therefore, all of this information594* is passed in and returned through the ipv6bind structure.595*596* If the request is to bind to a specific address, then this (by definition) means597* only bind in either v4 or v6, and this is just the same as normal. ie. a single598* call to bind() will suffice. The other socket is closed in this case.599*600* The more complicated case is when the requested address is ::0 or 0.0.0.0.601*602* Two further cases:603* 2. If the requested port is 0 (ie. any port) then we try to bind in v4 space604* first with a wild-card port argument. We then try to bind in v6 space605* using the returned port number. If this fails, we repeat the process606* until a free port common to both spaces becomes available.607*608* 3. If the requested port is a specific port, then we just try to get that609* port in both spaces, and if it is not free in both, then the bind fails.610*611* On failure, sockets are closed and an error returned with CLOSE_SOCKETS_AND_RETURN612*/613614JNIEXPORT int JNICALL615NET_BindV6(struct ipv6bind *b, jboolean exclBind) {616int fd=-1, ofd=-1, rv, len;617/* need to defer close until new sockets created */618int close_fd=-1, close_ofd=-1;619SOCKETADDRESS oaddr; /* other address to bind */620int family = b->addr->sa.sa_family;621int ofamily;622u_short port; /* requested port parameter */623u_short bound_port;624625if (family == AF_INET && (b->addr->sa4.sin_addr.s_addr != INADDR_ANY)) {626/* bind to v4 only */627int ret;628ret = NET_WinBind((int)b->ipv4_fd, b->addr,629sizeof(SOCKETADDRESS), exclBind);630if (ret == SOCKET_ERROR) {631CLOSE_SOCKETS_AND_RETURN;632}633closesocket (b->ipv6_fd);634b->ipv6_fd = -1;635return 0;636}637if (family == AF_INET6 && (!IN6_IS_ADDR_ANY(&b->addr->sa6.sin6_addr))) {638/* bind to v6 only */639int ret;640ret = NET_WinBind((int)b->ipv6_fd, b->addr,641sizeof(SOCKETADDRESS), exclBind);642if (ret == SOCKET_ERROR) {643CLOSE_SOCKETS_AND_RETURN;644}645closesocket (b->ipv4_fd);646b->ipv4_fd = -1;647return 0;648}649650/* We need to bind on both stacks, with the same port number */651652memset (&oaddr, 0, sizeof(oaddr));653if (family == AF_INET) {654ofamily = AF_INET6;655fd = (int)b->ipv4_fd;656ofd = (int)b->ipv6_fd;657port = (u_short)GET_PORT (b->addr);658IN6ADDR_SETANY(&oaddr.sa6);659oaddr.sa6.sin6_port = port;660} else {661ofamily = AF_INET;662ofd = (int)b->ipv4_fd;663fd = (int)b->ipv6_fd;664port = (u_short)GET_PORT (b->addr);665oaddr.sa4.sin_family = AF_INET;666oaddr.sa4.sin_port = port;667oaddr.sa4.sin_addr.s_addr = INADDR_ANY;668}669670rv = NET_WinBind(fd, b->addr, sizeof(SOCKETADDRESS), exclBind);671if (rv == SOCKET_ERROR) {672CLOSE_SOCKETS_AND_RETURN;673}674675/* get the port and set it in the other address */676len = sizeof(SOCKETADDRESS);677if (getsockname(fd, (struct sockaddr *)b->addr, &len) == -1) {678CLOSE_SOCKETS_AND_RETURN;679}680bound_port = GET_PORT (b->addr);681SET_PORT (&oaddr, bound_port);682if ((rv = NET_WinBind(ofd, &oaddr,683sizeof(SOCKETADDRESS), exclBind)) == SOCKET_ERROR) {684int retries;685int sotype, arglen=sizeof(sotype);686687/* no retries unless, the request was for any free port */688689if (port != 0) {690CLOSE_SOCKETS_AND_RETURN;691}692693getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen);694695#define SOCK_RETRIES 50696/* 50 is an arbitrary limit, just to ensure that this697* cannot be an endless loop. Would expect socket creation to698* succeed sooner.699*/700for (retries = 0; retries < SOCK_RETRIES; retries ++) {701int len;702close_fd = fd; fd = -1;703close_ofd = ofd; ofd = -1;704b->ipv4_fd = SOCKET_ERROR;705b->ipv6_fd = SOCKET_ERROR;706707/* create two new sockets */708fd = (int)socket (family, sotype, 0);709if (fd == SOCKET_ERROR) {710CLOSE_SOCKETS_AND_RETURN;711}712ofd = (int)socket (ofamily, sotype, 0);713if (ofd == SOCKET_ERROR) {714CLOSE_SOCKETS_AND_RETURN;715}716717/* bind random port on first socket */718SET_PORT (&oaddr, 0);719rv = NET_WinBind(ofd, &oaddr, sizeof(SOCKETADDRESS), exclBind);720if (rv == SOCKET_ERROR) {721CLOSE_SOCKETS_AND_RETURN;722}723/* close the original pair of sockets before continuing */724closesocket (close_fd);725closesocket (close_ofd);726close_fd = close_ofd = -1;727728/* bind new port on second socket */729len = sizeof(SOCKETADDRESS);730if (getsockname(ofd, &oaddr.sa, &len) == -1) {731CLOSE_SOCKETS_AND_RETURN;732}733bound_port = GET_PORT (&oaddr);734SET_PORT (b->addr, bound_port);735rv = NET_WinBind(fd, b->addr, sizeof(SOCKETADDRESS), exclBind);736737if (rv != SOCKET_ERROR) {738if (family == AF_INET) {739b->ipv4_fd = fd;740b->ipv6_fd = ofd;741} else {742b->ipv4_fd = ofd;743b->ipv6_fd = fd;744}745return 0;746}747}748CLOSE_SOCKETS_AND_RETURN;749}750return 0;751}752753/**754* Enables SIO_LOOPBACK_FAST_PATH755*/756JNIEXPORT jint JNICALL757NET_EnableFastTcpLoopback(int fd) {758int enabled = 1;759DWORD result_byte_count = -1;760int result = WSAIoctl(fd,761SIO_LOOPBACK_FAST_PATH,762&enabled,763sizeof(enabled),764NULL,7650,766&result_byte_count,767NULL,768NULL);769return result == SOCKET_ERROR ? WSAGetLastError() : 0;770}771772int773IsWindows10RS3OrGreater() {774OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 };775DWORDLONG const cond_mask = VerSetConditionMask(776VerSetConditionMask(777VerSetConditionMask(7780, VER_MAJORVERSION, VER_GREATER_EQUAL),779VER_MINORVERSION, VER_GREATER_EQUAL),780VER_BUILDNUMBER, VER_GREATER_EQUAL);781782osvi.dwMajorVersion = HIBYTE(_WIN32_WINNT_WIN10);783osvi.dwMinorVersion = LOBYTE(_WIN32_WINNT_WIN10);784osvi.dwBuildNumber = 16299; // RS3 (Redstone 3)785786return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER, cond_mask) != 0;787}788789/**790* Shortens the default Windows socket791* connect timeout. Recommended for usage792* on the loopback adapter only.793*/794JNIEXPORT jint JNICALL795NET_EnableFastTcpLoopbackConnect(int fd) {796TCP_INITIAL_RTO_PARAMETERS rto = {797TCP_INITIAL_RTO_UNSPECIFIED_RTT, // Use the default or overriden by the Administrator7981 // Minimum possible value before Windows 10 RS3799};800801/**802* In Windows 10 RS3+ we can use the no retransmissions flag to803* completely remove the timeout delay, which is fixed to 500ms804* if Windows receives RST when the destination port is not open.805*/806if (IsWindows10RS3OrGreater()) {807rto.MaxSynRetransmissions = TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS;808}809810DWORD result_byte_count = -1;811int result = WSAIoctl(fd, // descriptor identifying a socket812SIO_TCP_INITIAL_RTO, // dwIoControlCode813&rto, // pointer to TCP_INITIAL_RTO_PARAMETERS structure814sizeof(rto), // size, in bytes, of the input buffer815NULL, // pointer to output buffer8160, // size of output buffer817&result_byte_count, // number of bytes returned818NULL, // OVERLAPPED structure819NULL); // completion routine820return (result == SOCKET_ERROR) ? WSAGetLastError() : 0;821}822823/**824* See net_util.h for documentation825*/826JNIEXPORT int JNICALL827NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port,828SOCKETADDRESS *sa, int *len,829jboolean v4MappedAddress)830{831jint family = getInetAddress_family(env, iaObj);832JNU_CHECK_EXCEPTION_RETURN(env, -1);833memset((char *)sa, 0, sizeof(SOCKETADDRESS));834835if (ipv6_available() &&836!(family == java_net_InetAddress_IPv4 &&837v4MappedAddress == JNI_FALSE))838{839jbyte caddr[16];840jint address;841unsigned int scopeid = 0;842843if (family == java_net_InetAddress_IPv4) {844// convert to IPv4-mapped address845memset((char *)caddr, 0, 16);846address = getInetAddress_addr(env, iaObj);847JNU_CHECK_EXCEPTION_RETURN(env, -1);848if (address == INADDR_ANY) {849/* we would always prefer IPv6 wildcard address850* caddr[10] = 0xff;851* caddr[11] = 0xff; */852} else {853caddr[10] = 0xff;854caddr[11] = 0xff;855caddr[12] = ((address >> 24) & 0xff);856caddr[13] = ((address >> 16) & 0xff);857caddr[14] = ((address >> 8) & 0xff);858caddr[15] = (address & 0xff);859}860} else {861getInet6Address_ipaddress(env, iaObj, (char *)caddr);862scopeid = getInet6Address_scopeid(env, iaObj);863}864sa->sa6.sin6_port = (u_short)htons((u_short)port);865memcpy((void *)&sa->sa6.sin6_addr, caddr, sizeof(struct in6_addr));866sa->sa6.sin6_family = AF_INET6;867sa->sa6.sin6_scope_id = scopeid;868if (len != NULL) {869*len = sizeof(struct sockaddr_in6);870}871} else {872jint address;873if (family != java_net_InetAddress_IPv4) {874JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable");875return -1;876}877address = getInetAddress_addr(env, iaObj);878JNU_CHECK_EXCEPTION_RETURN(env, -1);879sa->sa4.sin_port = htons((short)port);880sa->sa4.sin_addr.s_addr = (u_long)htonl(address);881sa->sa4.sin_family = AF_INET;882if (len != NULL) {883*len = sizeof(struct sockaddr_in);884}885}886return 0;887}888889int890NET_IsIPv4Mapped(jbyte* caddr) {891int i;892for (i = 0; i < 10; i++) {893if (caddr[i] != 0x00) {894return 0; /* false */895}896}897898if (((caddr[10] & 0xff) == 0xff) && ((caddr[11] & 0xff) == 0xff)) {899return 1; /* true */900}901return 0; /* false */902}903904int905NET_IPv4MappedToIPv4(jbyte* caddr) {906return ((caddr[12] & 0xff) << 24) | ((caddr[13] & 0xff) << 16) | ((caddr[14] & 0xff) << 8)907| (caddr[15] & 0xff);908}909910int911NET_IsEqual(jbyte* caddr1, jbyte* caddr2) {912int i;913for (i = 0; i < 16; i++) {914if (caddr1[i] != caddr2[i]) {915return 0; /* false */916}917}918return 1;919}920921/**922* Wrapper for select/poll with timeout on a single file descriptor.923*924* flags (defined in net_util_md.h can be any combination of925* NET_WAIT_READ, NET_WAIT_WRITE & NET_WAIT_CONNECT.926*927* The function will return when either the socket is ready for one928* of the specified operation or the timeout expired.929*930* It returns the time left from the timeout, or -1 if it expired.931*/932933jint934NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout)935{936jlong prevTime = JVM_CurrentTimeMillis(env, 0);937jint read_rv;938939while (1) {940jlong newTime;941fd_set rd, wr, ex;942struct timeval t;943944t.tv_sec = timeout / 1000;945t.tv_usec = (timeout % 1000) * 1000;946947FD_ZERO(&rd);948FD_ZERO(&wr);949FD_ZERO(&ex);950if (flags & NET_WAIT_READ) {951FD_SET(fd, &rd);952}953if (flags & NET_WAIT_WRITE) {954FD_SET(fd, &wr);955}956if (flags & NET_WAIT_CONNECT) {957FD_SET(fd, &wr);958FD_SET(fd, &ex);959}960961errno = 0;962read_rv = select(fd+1, &rd, &wr, &ex, &t);963964newTime = JVM_CurrentTimeMillis(env, 0);965timeout -= (jint)(newTime - prevTime);966if (timeout <= 0) {967return read_rv > 0 ? 0 : -1;968}969newTime = prevTime;970971if (read_rv > 0) {972break;973}974975976} /* while */977978return timeout;979}980981int NET_Socket (int domain, int type, int protocol) {982SOCKET sock;983sock = socket (domain, type, protocol);984if (sock != INVALID_SOCKET) {985SetHandleInformation((HANDLE)(uintptr_t)sock, HANDLE_FLAG_INHERIT, FALSE);986}987return (int)sock;988}989990991