< prev index next >

src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c

Print this page
rev 49701 : [mq]: 8201510-Merge-TwoStacksPlainSocketImpl-into-DualStackPlainSocketImpl

*** 1,7 **** /* ! * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 58,82 **** * Class: java_net_DualStackPlainSocketImpl * Method: socket0 * Signature: (ZZ)I */ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_socket0 ! (JNIEnv *env, jclass clazz, jboolean stream, jboolean v6Only /*unused*/) { int fd, rv, opt=0; - fd = NET_Socket(AF_INET6, (stream ? SOCK_STREAM : SOCK_DGRAM), 0); if (fd == INVALID_SOCKET) { NET_ThrowNew(env, WSAGetLastError(), "create"); return -1; } ! rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt, sizeof(opt)); if (rv == SOCKET_ERROR) { NET_ThrowNew(env, WSAGetLastError(), "create"); } - - SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE); return fd; } /* --- 58,88 ---- * Class: java_net_DualStackPlainSocketImpl * Method: socket0 * Signature: (ZZ)I */ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_socket0 ! (JNIEnv *env, jclass clazz, jboolean stream) { int fd, rv, opt=0; + int type = (stream ? SOCK_STREAM : SOCK_DGRAM); + int domain = ipv6_available() ? AF_INET6 : AF_INET; + + fd = NET_Socket(domain, type, 0); if (fd == INVALID_SOCKET) { NET_ThrowNew(env, WSAGetLastError(), "create"); return -1; } ! if (domain == AF_INET6) { ! rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt, ! sizeof(opt)); if (rv == SOCKET_ERROR) { NET_ThrowNew(env, WSAGetLastError(), "create"); + closesocket(fd); + return -1; + } } return fd; } /*
*** 88,100 **** (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port, jboolean exclBind) { SOCKETADDRESS sa; int rv, sa_len = 0; if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, ! &sa_len, JNI_TRUE) != 0) { return; } rv = NET_WinBind(fd, &sa, sa_len, exclBind); --- 94,107 ---- (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port, jboolean exclBind) { SOCKETADDRESS sa; int rv, sa_len = 0; + jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE; if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, ! &sa_len, v4MappedAddress) != 0) { return; } rv = NET_WinBind(fd, &sa, sa_len, exclBind);
*** 109,132 **** */ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_connect0 (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) { SOCKETADDRESS sa; int rv, sa_len = 0; if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, ! &sa_len, JNI_TRUE) != 0) { return -1; } rv = connect(fd, &sa.sa, sa_len); if (rv == SOCKET_ERROR) { int err = WSAGetLastError(); if (err == WSAEWOULDBLOCK) { return java_net_DualStackPlainSocketImpl_WOULDBLOCK; } else if (err == WSAEADDRNOTAVAIL) { JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException", ! "connect: Address is invalid on local machine, or port is not valid on remote machine"); } else { NET_ThrowNew(env, err, "connect"); } return -1; // return value not important. } --- 116,141 ---- */ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_connect0 (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) { SOCKETADDRESS sa; int rv, sa_len = 0; + jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE; if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, ! &sa_len, v4MappedAddress) != 0) { return -1; } rv = connect(fd, &sa.sa, sa_len); if (rv == SOCKET_ERROR) { int err = WSAGetLastError(); if (err == WSAEWOULDBLOCK) { return java_net_DualStackPlainSocketImpl_WOULDBLOCK; } else if (err == WSAEADDRNOTAVAIL) { JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException", ! "connect: Address is invalid on local machine," ! " or port is not valid on remote machine"); } else { NET_ThrowNew(env, err, "connect"); } return -1; // return value not important. }
*** 198,207 **** --- 207,220 ---- } if (rv == 0) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Unable to establish connection"); + } else if (!ipv6_available() && rv == WSAEADDRNOTAVAIL) { + JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException", + "connect: Address is invalid on local machine," + " or port is not valid on remote machine"); } else { NET_ThrowNew(env, rv, "connect"); } }
*** 282,305 **** memset((char *)&sa, 0, len); newfd = accept(fd, &sa.sa, &len); if (newfd == INVALID_SOCKET) { ! if (WSAGetLastError() == -2) { ! JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", ! "operation interrupted"); ! } else { ! JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", ! "socket closed"); ! } return -1; } SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0); ia = NET_SockaddrToInetAddress(env, &sa, &port); isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port); (*env)->SetObjectArrayElement(env, isaa, 0, isa); return newfd; } --- 295,316 ---- memset((char *)&sa, 0, len); newfd = accept(fd, &sa.sa, &len); if (newfd == INVALID_SOCKET) { ! NET_ThrowNew(env, WSAGetLastError(), "accept failed"); return -1; } SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0); ia = NET_SockaddrToInetAddress(env, &sa, &port); isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port); + if (isa == NULL) { + closesocket(newfd); + return -1; + } (*env)->SetObjectArrayElement(env, isaa, 0, isa); return newfd; }
*** 400,409 **** --- 411,465 ---- } } /* * Class: java_net_DualStackPlainSocketImpl + * Method: setSoTimeout0 + * Signature: (II)V + */ + JNIEXPORT void JNICALL + Java_java_net_DualStackPlainSocketImpl_setSoTimeout0 + (JNIEnv *env, jclass clazz, jint fd, jint timeout) + { + /* + * SO_TIMEOUT is the socket option used to specify the timeout + * for ServerSocket.accept and Socket.getInputStream().read. + * It does not typically map to a native level socket option. + * For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO + * socket option to specify a receive timeout on the socket. This + * receive timeout is applicable to Socket only and the socket + * option should not be set on ServerSocket. + */ + + /* + * SO_RCVTIMEO is only supported on Microsoft's implementation + * of Windows Sockets so if WSAENOPROTOOPT returned then + * reset flag and timeout will be implemented using + * select() -- see SocketInputStream.socketRead. + */ + if (isRcvTimeoutSupported) { + /* + * Disable SO_RCVTIMEO if timeout is <= 5 second. + */ + if (timeout <= 5000) { + timeout = 0; + } + + if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, + sizeof(timeout)) < 0) { + int err = WSAGetLastError(); + if (err == WSAENOPROTOOPT) { + isRcvTimeoutSupported = JNI_FALSE; + } else { + NET_ThrowNew(env, err, "setsockopt SO_RCVTIMEO"); + } + } + } + } + + /* + * Class: java_net_DualStackPlainSocketImpl * Method: getIntOption * Signature: (II)I */ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_getIntOption (JNIEnv *env, jclass clazz, jint fd, jint cmd)
< prev index next >