src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c
changeset 49833 06a6ae39d892
parent 49431 5812849b5027
equal deleted inserted replaced
49832:9c52da3b7819 49833:06a6ae39d892
     1 /*
     1 /*
     2  * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    25 #include "net_util.h"
    25 #include "net_util.h"
    26 
    26 
    27 #include "java_net_DualStackPlainSocketImpl.h"
    27 #include "java_net_DualStackPlainSocketImpl.h"
    28 #include "java_net_SocketOptions.h"
    28 #include "java_net_SocketOptions.h"
    29 
    29 
    30 #define SET_BLOCKING 0
    30 #define SET_BLOCKING     0
    31 #define SET_NONBLOCKING 1
    31 #define SET_NONBLOCKING  1
    32 
    32 
    33 static jclass isa_class;        /* java.net.InetSocketAddress */
    33 static jclass isa_class;        /* java.net.InetSocketAddress */
    34 static jmethodID isa_ctorID;    /* InetSocketAddress(InetAddress, int) */
    34 static jmethodID isa_ctorID;    /* InetSocketAddress(InetAddress, int) */
    35 
    35 
    36 /*
    36 /*
    58  * Class:     java_net_DualStackPlainSocketImpl
    58  * Class:     java_net_DualStackPlainSocketImpl
    59  * Method:    socket0
    59  * Method:    socket0
    60  * Signature: (ZZ)I
    60  * Signature: (ZZ)I
    61  */
    61  */
    62 JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_socket0
    62 JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_socket0
    63   (JNIEnv *env, jclass clazz, jboolean stream, jboolean v6Only /*unused*/) {
    63   (JNIEnv *env, jclass clazz, jboolean stream) {
    64     int fd, rv, opt=0;
    64     int fd, rv, opt=0;
    65 
    65     int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
    66     fd = NET_Socket(AF_INET6, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
    66     int domain = ipv6_available() ? AF_INET6 : AF_INET;
       
    67 
       
    68     fd = NET_Socket(domain, type, 0);
       
    69 
    67     if (fd == INVALID_SOCKET) {
    70     if (fd == INVALID_SOCKET) {
    68         NET_ThrowNew(env, WSAGetLastError(), "create");
    71         NET_ThrowNew(env, WSAGetLastError(), "create");
    69         return -1;
    72         return -1;
    70     }
    73     }
    71 
    74 
    72     rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt, sizeof(opt));
    75     if (domain == AF_INET6) {
    73     if (rv == SOCKET_ERROR) {
    76         rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt,
    74         NET_ThrowNew(env, WSAGetLastError(), "create");
    77                         sizeof(opt));
    75     }
    78         if (rv == SOCKET_ERROR) {
    76 
    79             NET_ThrowNew(env, WSAGetLastError(), "create");
    77     SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
    80             closesocket(fd);
       
    81             return -1;
       
    82         }
       
    83     }
    78 
    84 
    79     return fd;
    85     return fd;
    80 }
    86 }
    81 
    87 
    82 /*
    88 /*
    88   (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port,
    94   (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port,
    89    jboolean exclBind)
    95    jboolean exclBind)
    90 {
    96 {
    91     SOCKETADDRESS sa;
    97     SOCKETADDRESS sa;
    92     int rv, sa_len = 0;
    98     int rv, sa_len = 0;
       
    99     jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE;
    93 
   100 
    94     if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
   101     if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
    95                                   &sa_len, JNI_TRUE) != 0) {
   102                                   &sa_len, v4MappedAddress) != 0) {
    96       return;
   103         return;
    97     }
   104     }
    98 
   105 
    99     rv = NET_WinBind(fd, &sa, sa_len, exclBind);
   106     rv = NET_WinBind(fd, &sa, sa_len, exclBind);
   100 
   107 
   101     if (rv == SOCKET_ERROR)
   108     if (rv == SOCKET_ERROR)
   109  */
   116  */
   110 JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_connect0
   117 JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_connect0
   111   (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
   118   (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
   112     SOCKETADDRESS sa;
   119     SOCKETADDRESS sa;
   113     int rv, sa_len = 0;
   120     int rv, sa_len = 0;
       
   121     jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE;
   114 
   122 
   115     if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
   123     if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
   116                                   &sa_len, JNI_TRUE) != 0) {
   124                                   &sa_len, v4MappedAddress) != 0) {
   117       return -1;
   125         return -1;
   118     }
   126     }
   119 
   127 
   120     rv = connect(fd, &sa.sa, sa_len);
   128     rv = connect(fd, &sa.sa, sa_len);
   121     if (rv == SOCKET_ERROR) {
   129     if (rv == SOCKET_ERROR) {
   122         int err = WSAGetLastError();
   130         int err = WSAGetLastError();
   123         if (err == WSAEWOULDBLOCK) {
   131         if (err == WSAEWOULDBLOCK) {
   124             return java_net_DualStackPlainSocketImpl_WOULDBLOCK;
   132             return java_net_DualStackPlainSocketImpl_WOULDBLOCK;
   125         } else if (err == WSAEADDRNOTAVAIL) {
   133         } else if (err == WSAEADDRNOTAVAIL) {
   126             JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
   134             JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
   127                 "connect: Address is invalid on local machine, or port is not valid on remote machine");
   135                 "connect: Address is invalid on local machine,"
       
   136                 " or port is not valid on remote machine");
   128         } else {
   137         } else {
   129             NET_ThrowNew(env, err, "connect");
   138             NET_ThrowNew(env, err, "connect");
   130         }
   139         }
   131         return -1;  // return value not important.
   140         return -1;  // return value not important.
   132     }
   141     }
   198     }
   207     }
   199 
   208 
   200     if (rv == 0) {
   209     if (rv == 0) {
   201         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   210         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   202                         "Unable to establish connection");
   211                         "Unable to establish connection");
       
   212     } else if (!ipv6_available() && rv == WSAEADDRNOTAVAIL) {
       
   213         JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
       
   214                         "connect: Address is invalid on local machine,"
       
   215                         " or port is not valid on remote machine");
   203     } else {
   216     } else {
   204         NET_ThrowNew(env, rv, "connect");
   217         NET_ThrowNew(env, rv, "connect");
   205     }
   218     }
   206 }
   219 }
   207 
   220 
   282 
   295 
   283     memset((char *)&sa, 0, len);
   296     memset((char *)&sa, 0, len);
   284     newfd = accept(fd, &sa.sa, &len);
   297     newfd = accept(fd, &sa.sa, &len);
   285 
   298 
   286     if (newfd == INVALID_SOCKET) {
   299     if (newfd == INVALID_SOCKET) {
   287         if (WSAGetLastError() == -2) {
   300         NET_ThrowNew(env, WSAGetLastError(), "accept failed");
   288             JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
       
   289                             "operation interrupted");
       
   290         } else {
       
   291             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
       
   292                             "socket closed");
       
   293         }
       
   294         return -1;
   301         return -1;
   295     }
   302     }
   296 
   303 
   297     SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
   304     SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
   298 
   305 
   299     ia = NET_SockaddrToInetAddress(env, &sa, &port);
   306     ia = NET_SockaddrToInetAddress(env, &sa, &port);
   300     isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
   307     isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
       
   308     if (isa == NULL) {
       
   309         closesocket(newfd);
       
   310         return -1;
       
   311     }
   301     (*env)->SetObjectArrayElement(env, isaa, 0, isa);
   312     (*env)->SetObjectArrayElement(env, isaa, 0, isa);
   302 
   313 
   303     return newfd;
   314     return newfd;
   304 }
   315 }
   305 
   316 
   400     }
   411     }
   401 }
   412 }
   402 
   413 
   403 /*
   414 /*
   404  * Class:     java_net_DualStackPlainSocketImpl
   415  * Class:     java_net_DualStackPlainSocketImpl
       
   416  * Method:    setSoTimeout0
       
   417  * Signature: (II)V
       
   418  */
       
   419 JNIEXPORT void JNICALL
       
   420 Java_java_net_DualStackPlainSocketImpl_setSoTimeout0
       
   421   (JNIEnv *env, jclass clazz, jint fd, jint timeout)
       
   422 {
       
   423     /*
       
   424      * SO_TIMEOUT is the socket option used to specify the timeout
       
   425      * for ServerSocket.accept and Socket.getInputStream().read.
       
   426      * It does not typically map to a native level socket option.
       
   427      * For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO
       
   428      * socket option to specify a receive timeout on the socket. This
       
   429      * receive timeout is applicable to Socket only and the socket
       
   430      * option should not be set on ServerSocket.
       
   431      */
       
   432 
       
   433     /*
       
   434      * SO_RCVTIMEO is only supported on Microsoft's implementation
       
   435      * of Windows Sockets so if WSAENOPROTOOPT returned then
       
   436      * reset flag and timeout will be implemented using
       
   437      * select() -- see SocketInputStream.socketRead.
       
   438      */
       
   439     if (isRcvTimeoutSupported) {
       
   440         /*
       
   441          * Disable SO_RCVTIMEO if timeout is <= 5 second.
       
   442          */
       
   443         if (timeout <= 5000) {
       
   444             timeout = 0;
       
   445         }
       
   446 
       
   447         if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
       
   448             sizeof(timeout)) < 0) {
       
   449             int err = WSAGetLastError();
       
   450             if (err == WSAENOPROTOOPT) {
       
   451                 isRcvTimeoutSupported = JNI_FALSE;
       
   452             } else {
       
   453                 NET_ThrowNew(env, err, "setsockopt SO_RCVTIMEO");
       
   454             }
       
   455         }
       
   456     }
       
   457 }
       
   458 
       
   459 /*
       
   460  * Class:     java_net_DualStackPlainSocketImpl
   405  * Method:    getIntOption
   461  * Method:    getIntOption
   406  * Signature: (II)I
   462  * Signature: (II)I
   407  */
   463  */
   408 JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_getIntOption
   464 JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_getIntOption
   409   (JNIEnv *env, jclass clazz, jint fd, jint cmd)
   465   (JNIEnv *env, jclass clazz, jint fd, jint cmd)
   464   (JNIEnv *env, jclass clazz, jint fd, jboolean blocking) {
   520   (JNIEnv *env, jclass clazz, jint fd, jboolean blocking) {
   465     u_long arg;
   521     u_long arg;
   466     int result;
   522     int result;
   467 
   523 
   468     if (blocking == JNI_TRUE) {
   524     if (blocking == JNI_TRUE) {
   469         arg = SET_BLOCKING;    // 0
   525         arg = SET_BLOCKING;      // 0
   470     } else {
   526     } else {
   471         arg = SET_NONBLOCKING;   // 1
   527         arg = SET_NONBLOCKING;   // 1
   472     }
   528     }
   473 
   529 
   474     result = ioctlsocket(fd, FIONBIO, &arg);
   530     result = ioctlsocket(fd, FIONBIO, &arg);