src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c
changeset 48911 edaa989b4e67
parent 47216 71c04702a3d5
child 49413 0ee57b9b376c
equal deleted inserted replaced
48910:67cdc215ed70 48911:edaa989b4e67
     1 /*
     1 /*
     2  * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1997, 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
    35  */
    35  */
    36 
    36 
    37 static jfieldID IO_fd_fdID;
    37 static jfieldID IO_fd_fdID;
    38 
    38 
    39 jfieldID psi_fdID;
    39 jfieldID psi_fdID;
    40 jfieldID psi_fd1ID;
       
    41 jfieldID psi_addressID;
    40 jfieldID psi_addressID;
    42 jfieldID psi_portID;
    41 jfieldID psi_portID;
    43 jfieldID psi_localportID;
    42 jfieldID psi_localportID;
    44 jfieldID psi_timeoutID;
    43 jfieldID psi_timeoutID;
    45 jfieldID psi_trafficClassID;
    44 jfieldID psi_trafficClassID;
    46 jfieldID psi_serverSocketID;
    45 jfieldID psi_serverSocketID;
    47 jfieldID psi_lastfdID;
       
    48 
    46 
    49 /*
    47 /*
    50  * the level of the TCP protocol for setsockopt and getsockopt
    48  * the level of the TCP protocol for setsockopt and getsockopt
    51  * we only want to look this up once, from the static initializer
    49  * we only want to look this up once, from the static initializer
    52  * of TwoStacksPlainSocketImpl
    50  * of TwoStacksPlainSocketImpl
    53  */
    51  */
    54 static int tcp_level = -1;
    52 static int tcp_level = -1;
    55 
    53 
    56 static int getFD(JNIEnv *env, jobject this) {
    54 static int getFD(JNIEnv *env, jobject this) {
    57     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
    55     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
    58 
       
    59     if (fdObj == NULL) {
       
    60         return -1;
       
    61     }
       
    62     return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
       
    63 }
       
    64 
       
    65 static int getFD1(JNIEnv *env, jobject this) {
       
    66     jobject fdObj = (*env)->GetObjectField(env, this, psi_fd1ID);
       
    67 
    56 
    68     if (fdObj == NULL) {
    57     if (fdObj == NULL) {
    69         return -1;
    58         return -1;
    70     }
    59     }
    71     return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
    60     return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
    88     struct protoent *proto = getprotobyname("TCP");
    77     struct protoent *proto = getprotobyname("TCP");
    89     tcp_level = (proto == 0 ? IPPROTO_TCP: proto->p_proto);
    78     tcp_level = (proto == 0 ? IPPROTO_TCP: proto->p_proto);
    90 
    79 
    91     psi_fdID = (*env)->GetFieldID(env, cls , "fd", "Ljava/io/FileDescriptor;");
    80     psi_fdID = (*env)->GetFieldID(env, cls , "fd", "Ljava/io/FileDescriptor;");
    92     CHECK_NULL(psi_fdID);
    81     CHECK_NULL(psi_fdID);
    93     psi_fd1ID =(*env)->GetFieldID(env, cls , "fd1", "Ljava/io/FileDescriptor;");
       
    94     CHECK_NULL(psi_fd1ID);
       
    95     psi_addressID = (*env)->GetFieldID(env, cls, "address",
    82     psi_addressID = (*env)->GetFieldID(env, cls, "address",
    96                                           "Ljava/net/InetAddress;");
    83                                           "Ljava/net/InetAddress;");
    97     CHECK_NULL(psi_addressID);
    84     CHECK_NULL(psi_addressID);
    98     psi_portID = (*env)->GetFieldID(env, cls, "port", "I");
    85     psi_portID = (*env)->GetFieldID(env, cls, "port", "I");
    99     CHECK_NULL(psi_portID);
    86     CHECK_NULL(psi_portID);
   100     psi_lastfdID = (*env)->GetFieldID(env, cls, "lastfd", "I");
       
   101     CHECK_NULL(psi_lastfdID);
       
   102     psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I");
    87     psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I");
   103     CHECK_NULL(psi_localportID);
    88     CHECK_NULL(psi_localportID);
   104     psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I");
    89     psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I");
   105     CHECK_NULL(psi_timeoutID);
    90     CHECK_NULL(psi_timeoutID);
   106     psi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I");
    91     psi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I");
   118  * Signature: (Z)V
   103  * Signature: (Z)V
   119  */
   104  */
   120 JNIEXPORT void JNICALL
   105 JNIEXPORT void JNICALL
   121 Java_java_net_TwoStacksPlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
   106 Java_java_net_TwoStacksPlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
   122                                            jboolean stream) {
   107                                            jboolean stream) {
   123     jobject fdObj, fd1Obj;
   108     jobject fdObj;
   124     int fd, fd1;
   109     int fd;
   125 
   110 
   126     fdObj = (*env)->GetObjectField(env, this, psi_fdID);
   111     fdObj = (*env)->GetObjectField(env, this, psi_fdID);
   127 
   112 
   128     if (IS_NULL(fdObj)) {
   113     if (IS_NULL(fdObj)) {
   129         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   114         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   136         return;
   121         return;
   137     } else {
   122     } else {
   138         /* Set socket attribute so it is not passed to any child process */
   123         /* Set socket attribute so it is not passed to any child process */
   139         SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
   124         SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
   140         (*env)->SetIntField(env, fdObj, IO_fd_fdID, (int)fd);
   125         (*env)->SetIntField(env, fdObj, IO_fd_fdID, (int)fd);
   141     }
       
   142     if (ipv6_available()) {
       
   143         fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
       
   144 
       
   145         if (IS_NULL(fd1Obj)) {
       
   146             (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
       
   147             NET_SocketClose(fd);
       
   148             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
       
   149                             "null fd1 object");
       
   150             return;
       
   151         }
       
   152         fd1 = socket(AF_INET6, (stream ? SOCK_STREAM: SOCK_DGRAM), 0);
       
   153         if (fd1 == -1) {
       
   154             (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
       
   155             NET_SocketClose(fd);
       
   156             NET_ThrowCurrent(env, "create");
       
   157             return;
       
   158         } else {
       
   159             /* Set socket attribute so it is not passed to any child process */
       
   160             SetHandleInformation((HANDLE)(UINT_PTR)fd1, HANDLE_FLAG_INHERIT, FALSE);
       
   161             (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1);
       
   162         }
       
   163     } else {
       
   164         (*env)->SetObjectField(env, this, psi_fd1ID, NULL);
       
   165     }
   126     }
   166 }
   127 }
   167 
   128 
   168 /*
   129 /*
   169  * inetAddress is the address object passed to the socket connect
   130  * inetAddress is the address object passed to the socket connect
   180 {
   141 {
   181     jint localport = (*env)->GetIntField(env, this, psi_localportID);
   142     jint localport = (*env)->GetIntField(env, this, psi_localportID);
   182 
   143 
   183     /* family and localport are int fields of iaObj */
   144     /* family and localport are int fields of iaObj */
   184     int family;
   145     int family;
   185     jint fd = -1, fd1 = -1;
   146     jint fd = -1;
   186     jint len;
   147     jint len;
   187     int  ipv6_supported = ipv6_available();
   148 
   188 
       
   189     /* fd initially points to the IPv4 socket and fd1 to the IPv6 socket
       
   190      * If we want to connect to IPv6 then we swap the two sockets/objects
       
   191      * This way, fd is always the connected socket, and fd1 always gets closed.
       
   192      */
       
   193     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
   149     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
   194     jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
       
   195 
   150 
   196     SOCKETADDRESS sa;
   151     SOCKETADDRESS sa;
   197 
   152 
   198     /* The result of the connection */
   153     /* The result of the connection */
   199     int connect_res;
   154     int connect_res;
   201 
   156 
   202     if (!IS_NULL(fdObj)) {
   157     if (!IS_NULL(fdObj)) {
   203         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
   158         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
   204     }
   159     }
   205 
   160 
   206     if (ipv6_supported && !IS_NULL(fd1Obj)) {
       
   207         fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
       
   208     }
       
   209 
       
   210     if (IS_NULL(iaObj)) {
   161     if (IS_NULL(iaObj)) {
   211         JNU_ThrowNullPointerException(env, "inet address argument is null.");
   162         JNU_ThrowNullPointerException(env, "inet address argument is null.");
   212         return;
   163         return;
   213     }
   164     }
   214 
   165 
   216                                   JNI_FALSE) != 0) {
   167                                   JNI_FALSE) != 0) {
   217         return;
   168         return;
   218     }
   169     }
   219 
   170 
   220     family = sa.sa.sa_family;
   171     family = sa.sa.sa_family;
   221     if (family == AF_INET6) {
   172     if (family != AF_INET) {
   222         if (!ipv6_supported) {
   173         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   223             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   174                         "Protocol family not supported");
   224                             "Protocol family not supported");
   175     }
   225             return;
   176     if (fd == -1) {
   226         } else {
   177         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   227             if (fd1 == -1) {
   178                         "Destination unreachable");
   228                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   179         return;
   229                                 "Destination unreachable");
   180     }
   230                 return;
       
   231             }
       
   232             /* close the v4 socket, and set fd to be the v6 socket */
       
   233             (*env)->SetObjectField(env, this, psi_fdID, fd1Obj);
       
   234             (*env)->SetObjectField(env, this, psi_fd1ID, NULL);
       
   235             NET_SocketClose(fd);
       
   236             fd = fd1; fdObj = fd1Obj;
       
   237         }
       
   238     } else {
       
   239         if (fd1 != -1) {
       
   240             (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1);
       
   241             NET_SocketClose(fd1);
       
   242         }
       
   243         if (fd == -1) {
       
   244             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
       
   245                             "Destination unreachable");
       
   246             return;
       
   247         }
       
   248     }
       
   249     (*env)->SetObjectField(env, this, psi_fd1ID, NULL);
       
   250 
   181 
   251     if (timeout <= 0) {
   182     if (timeout <= 0) {
   252         connect_res = connect(fd, &sa.sa, sizeof(SOCKETADDRESS));
   183         connect_res = connect(fd, &sa.sa, sizeof(SOCKETADDRESS));
   253         if (connect_res == SOCKET_ERROR) {
   184         if (connect_res == SOCKET_ERROR) {
   254             connect_res = WSAGetLastError();
   185             connect_res = WSAGetLastError();
   386 Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this,
   317 Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this,
   387                                          jobject iaObj, jint localport,
   318                                          jobject iaObj, jint localport,
   388                                          jboolean exclBind) {
   319                                          jboolean exclBind) {
   389 
   320 
   390     /* fdObj is the FileDescriptor field on this */
   321     /* fdObj is the FileDescriptor field on this */
   391     jobject fdObj, fd1Obj;
   322     jobject fdObj;
   392     /* fd is an int field on fdObj */
   323     /* fd is an int field on fdObj */
   393     int fd, fd1 = -1, len = 0;
   324     int fd, len = 0;
   394     int ipv6_supported = ipv6_available();
       
   395 
   325 
   396     /* family is an int field of iaObj */
   326     /* family is an int field of iaObj */
   397     int family;
   327     int family;
   398     int rv;
   328     int rv;
   399 
   329 
   400     SOCKETADDRESS sa;
   330     SOCKETADDRESS sa;
   401 
   331 
   402     fdObj = (*env)->GetObjectField(env, this, psi_fdID);
   332     fdObj = (*env)->GetObjectField(env, this, psi_fdID);
   403     fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
       
   404 
   333 
   405     family = getInetAddress_family(env, iaObj);
   334     family = getInetAddress_family(env, iaObj);
   406 
   335 
   407     if (family == java_net_InetAddress_IPv6 && !ipv6_supported) {
   336     if (family != java_net_InetAddress_IPv4) {
   408         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   337         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   409                         "Protocol family not supported");
   338                         "Protocol family not supported");
   410         return;
   339         return;
   411     }
   340     }
   412 
   341 
   413     if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) {
   342     if (IS_NULL(fdObj)) {
   414         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   343         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   415                         "Socket closed");
   344                         "Socket closed");
   416         return;
   345         return;
   417     } else {
   346     } else {
   418         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
   347         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
   419         if (ipv6_supported) {
       
   420             fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
       
   421         }
       
   422     }
   348     }
   423     if (IS_NULL(iaObj)) {
   349     if (IS_NULL(iaObj)) {
   424         JNU_ThrowNullPointerException(env, "inet address argument");
   350         JNU_ThrowNullPointerException(env, "inet address argument");
   425         return;
   351         return;
   426     }
   352     }
   427 
   353 
   428     if (NET_InetAddressToSockaddr(env, iaObj, localport, &sa, &len,
   354     if (NET_InetAddressToSockaddr(env, iaObj, localport, &sa, &len,
   429                                   JNI_FALSE) != 0) {
   355                                   JNI_FALSE) != 0) {
   430         return;
   356         return;
   431     }
   357     }
   432     if (ipv6_supported) {
   358     rv = NET_WinBind(fd, &sa, len, exclBind);
   433         struct ipv6bind v6bind;
       
   434         v6bind.addr = &sa.sa;
       
   435         v6bind.ipv4_fd = fd;
       
   436         v6bind.ipv6_fd = fd1;
       
   437         rv = NET_BindV6(&v6bind, exclBind);
       
   438         if (rv != -1) {
       
   439             /* check if the fds have changed */
       
   440             if (v6bind.ipv4_fd != fd) {
       
   441                 fd = v6bind.ipv4_fd;
       
   442                 if (fd == -1) {
       
   443                     /* socket is closed. */
       
   444                     (*env)->SetObjectField(env, this, psi_fdID, NULL);
       
   445                 } else {
       
   446                     /* socket was re-created */
       
   447                     (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
       
   448                 }
       
   449             }
       
   450             if (v6bind.ipv6_fd != fd1) {
       
   451                 fd1 = v6bind.ipv6_fd;
       
   452                 if (fd1 == -1) {
       
   453                     /* socket is closed. */
       
   454                     (*env)->SetObjectField(env, this, psi_fd1ID, NULL);
       
   455                 } else {
       
   456                     /* socket was re-created */
       
   457                     (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1);
       
   458                 }
       
   459             }
       
   460         } else {
       
   461             /* NET_BindV6() closes both sockets upon a failure */
       
   462             (*env)->SetObjectField(env, this, psi_fdID, NULL);
       
   463             (*env)->SetObjectField(env, this, psi_fd1ID, NULL);
       
   464         }
       
   465     } else {
       
   466         rv = NET_WinBind(fd, &sa, len, exclBind);
       
   467     }
       
   468 
   359 
   469     if (rv == -1) {
   360     if (rv == -1) {
   470         NET_ThrowCurrent(env, "NET_Bind");
   361         NET_ThrowCurrent(env, "NET_Bind");
   471         return;
   362         return;
   472     }
   363     }
   480          * that the system chose for us and store it in the Socket object.
   371          * that the system chose for us and store it in the Socket object.
   481          */
   372          */
   482         int len = sizeof(SOCKETADDRESS);
   373         int len = sizeof(SOCKETADDRESS);
   483         u_short port;
   374         u_short port;
   484 
   375 
   485         if (getsockname(sa.sa.sa_family == AF_INET ? fd : fd1, &sa.sa, &len) == -1) {
   376         if (getsockname(fd, &sa.sa, &len) == -1) {
   486             NET_ThrowCurrent(env, "getsockname in plain socketBind");
   377             NET_ThrowCurrent(env, "getsockname in plain socketBind");
   487             return;
   378             return;
   488         }
   379         }
   489         port = ntohs((u_short) GET_PORT (&sa));
   380         port = ntohs((u_short) GET_PORT (&sa));
   490 
   381 
   503 Java_java_net_TwoStacksPlainSocketImpl_socketListen
   394 Java_java_net_TwoStacksPlainSocketImpl_socketListen
   504   (JNIEnv *env, jobject this, jint count)
   395   (JNIEnv *env, jobject this, jint count)
   505 {
   396 {
   506     /* this FileDescriptor fd field */
   397     /* this FileDescriptor fd field */
   507     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
   398     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
   508     jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
       
   509     jobject address;
   399     jobject address;
   510     /* fdObj's int fd field */
   400     /* fdObj's int fd field */
   511     int fd = INVALID_SOCKET, fd1 = INVALID_SOCKET;
   401     int fd = INVALID_SOCKET;
   512     SOCKETADDRESS addr;
   402     SOCKETADDRESS addr;
   513     int addrlen;
   403     int addrlen;
   514 
   404 
   515     if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) {
   405     if (IS_NULL(fdObj)) {
   516         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   406         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   517                         "socket closed");
   407                         "socket closed");
   518         return;
   408         return;
   519     }
   409     }
   520 
   410 
   521     if (!IS_NULL(fdObj)) {
   411     if (!IS_NULL(fdObj)) {
   522         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
   412         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
   523     }
   413     }
   524     /* Listen on V4 if address type is v4 or if v6 and address is ::0.
       
   525      * Listen on V6 if address type is v6 or if v4 and address is 0.0.0.0.
       
   526      * In cases, where we listen on one space only, we close the other socket.
       
   527      */
       
   528     address = (*env)->GetObjectField(env, this, psi_addressID);
   414     address = (*env)->GetObjectField(env, this, psi_addressID);
   529     if (IS_NULL(address)) {
   415     if (IS_NULL(address)) {
   530         JNU_ThrowNullPointerException(env, "socket address");
   416         JNU_ThrowNullPointerException(env, "socket address");
   531         return;
   417         return;
   532     }
   418     }
   533     if (NET_InetAddressToSockaddr(env, address, 0, &addr, &addrlen,
   419     if (NET_InetAddressToSockaddr(env, address, 0, &addr, &addrlen,
   534                                   JNI_FALSE) != 0) {
   420                                   JNI_FALSE) != 0) {
   535         return;
   421         return;
   536     }
   422     }
   537 
   423 
   538     if (addr.sa.sa_family == AF_INET || IN6ADDR_ISANY(&addr.sa6)) {
   424     if (addr.sa.sa_family == AF_INET) {
   539         /* listen on v4 */
   425         /* listen on v4 */
   540         if (listen(fd, count) == -1) {
   426         if (listen(fd, count) == -1) {
   541             NET_ThrowCurrent(env, "listen failed");
   427             NET_ThrowCurrent(env, "listen failed");
   542         }
   428         }
   543     } else {
   429     } else {
   544         NET_SocketClose (fd);
   430         NET_SocketClose(fd);
   545         (*env)->SetObjectField(env, this, psi_fdID, NULL);
   431         (*env)->SetObjectField(env, this, psi_fdID, NULL);
   546     }
       
   547     if (ipv6_available() && !IS_NULL(fd1Obj)) {
       
   548         fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
       
   549         if (addr.sa.sa_family == AF_INET6 || addr.sa4.sin_addr.s_addr == INADDR_ANY) {
       
   550             /* listen on v6 */
       
   551             if (listen(fd1, count) == -1) {
       
   552                 NET_ThrowCurrent(env, "listen failed");
       
   553             }
       
   554         } else {
       
   555             NET_SocketClose (fd1);
       
   556             (*env)->SetObjectField(env, this, psi_fd1ID, NULL);
       
   557         }
       
   558     }
   432     }
   559 }
   433 }
   560 
   434 
   561 /*
   435 /*
   562  * Class:     java_net_TwoStacksPlainSocketImpl
   436  * Class:     java_net_TwoStacksPlainSocketImpl
   569 {
   443 {
   570     /* fields on this */
   444     /* fields on this */
   571     jint port;
   445     jint port;
   572     jint timeout = (*env)->GetIntField(env, this, psi_timeoutID);
   446     jint timeout = (*env)->GetIntField(env, this, psi_timeoutID);
   573     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
   447     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
   574     jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
       
   575 
   448 
   576     /* the FileDescriptor field on socket */
   449     /* the FileDescriptor field on socket */
   577     jobject socketFdObj;
   450     jobject socketFdObj;
   578 
   451 
   579     /* cache the Inet4/6Address classes */
   452     /* cache the Inet4 class */
   580     static jclass inet4Cls;
   453     static jclass inet4Cls;
   581     static jclass inet6Cls;
       
   582 
   454 
   583     /* the InetAddress field on socket */
   455     /* the InetAddress field on socket */
   584     jobject socketAddressObj;
   456     jobject socketAddressObj;
   585 
   457 
   586     /* the fd int field on fdObj */
   458     /* the fd int field on fdObj */
   587     jint fd=-1, fd1=-1;
   459     jint fd=-1;
   588 
   460 
   589     SOCKETADDRESS sa;
   461     SOCKETADDRESS sa;
   590     jint len;
   462     jint len;
   591 
   463     int ret;
   592     if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) {
   464 
       
   465     if (IS_NULL(fdObj)) {
   593         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   466         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   594                         "Socket closed");
   467                         "Socket closed");
   595         return;
   468         return;
   596     }
   469     }
   597     if (!IS_NULL(fdObj)) {
   470 
   598         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
   471     fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
   599     }
   472 
   600     if (!IS_NULL(fd1Obj)) {
       
   601         fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
       
   602     }
       
   603     if (IS_NULL(socket)) {
   473     if (IS_NULL(socket)) {
   604         JNU_ThrowNullPointerException(env, "socket is null");
   474         JNU_ThrowNullPointerException(env, "socket is null");
   605         return;
   475         return;
   606     } else {
   476     } else {
   607         socketFdObj = (*env)->GetObjectField(env, socket, psi_fdID);
   477         socketFdObj = (*env)->GetObjectField(env, socket, psi_fdID);
   609     }
   479     }
   610     if ((IS_NULL(socketAddressObj)) || (IS_NULL(socketFdObj))) {
   480     if ((IS_NULL(socketAddressObj)) || (IS_NULL(socketFdObj))) {
   611         JNU_ThrowNullPointerException(env, "socket address or fd obj");
   481         JNU_ThrowNullPointerException(env, "socket address or fd obj");
   612         return;
   482         return;
   613     }
   483     }
   614     if (fd != -1 && fd1 != -1) {
   484 
   615         fd_set rfds;
   485     len = sizeof(struct sockaddr_in);
   616         struct timeval t, *tP=&t;
   486     if (timeout) {
   617         int lastfd, res, fd2;
   487         ret = NET_Timeout(fd, timeout);
   618         FD_ZERO(&rfds);
   488         if (ret == 0) {
   619         FD_SET(fd,&rfds);
       
   620         FD_SET(fd1,&rfds);
       
   621         if (timeout) {
       
   622             t.tv_sec = timeout/1000;
       
   623             t.tv_usec = (timeout%1000)*1000;
       
   624         } else {
       
   625             tP = NULL;
       
   626         }
       
   627         res = select (fd, &rfds, NULL, NULL, tP);
       
   628         if (res == 0) {
       
   629             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
   489             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
   630                             "Accept timed out");
   490                             "Accept timed out");
   631             return;
   491             return;
   632         } else if (res == 1) {
   492         } else if (ret == -1) {
   633             fd2 = FD_ISSET(fd, &rfds)? fd: fd1;
   493             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
   634         } else if (res == 2) {
   494         /* REMIND: SOCKET CLOSED PROBLEM */
   635             /* avoid starvation */
   495 /*        NET_ThrowCurrent(env, "Accept failed"); */
   636             lastfd = (*env)->GetIntField(env, this, psi_lastfdID);
       
   637             if (lastfd != -1) {
       
   638                 fd2 = lastfd==fd? fd1: fd;
       
   639             } else {
       
   640                 fd2 = fd;
       
   641             }
       
   642             (*env)->SetIntField(env, this, psi_lastfdID, fd2);
       
   643         } else {
       
   644             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
       
   645                             "select failed");
       
   646             return;
   496             return;
   647         }
   497         } else if (ret == -2) {
   648         if (fd2 == fd) { /* v4 */
   498             JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
   649             len = sizeof(struct sockaddr_in);
   499                             "operation interrupted");
   650         } else {
   500             return;
   651             len = sizeof(struct sockaddr_in6);
   501         }
   652         }
   502     }
   653         fd = fd2;
   503 
   654     } else {
       
   655         int ret;
       
   656         if (fd1 != -1) {
       
   657             fd = fd1;
       
   658             len = sizeof(struct sockaddr_in6);
       
   659         } else {
       
   660             len = sizeof(struct sockaddr_in);
       
   661         }
       
   662         if (timeout) {
       
   663             ret = NET_Timeout(fd, timeout);
       
   664             if (ret == 0) {
       
   665                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
       
   666                                 "Accept timed out");
       
   667                 return;
       
   668             } else if (ret == -1) {
       
   669                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
       
   670             /* REMIND: SOCKET CLOSED PROBLEM */
       
   671     /*        NET_ThrowCurrent(env, "Accept failed"); */
       
   672                 return;
       
   673             } else if (ret == -2) {
       
   674                 JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
       
   675                                 "operation interrupted");
       
   676                 return;
       
   677             }
       
   678         }
       
   679     }
       
   680     fd = accept(fd, &sa.sa, &len);
   504     fd = accept(fd, &sa.sa, &len);
   681     if (fd < 0) {
   505     if (fd < 0) {
   682         /* REMIND: SOCKET CLOSED PROBLEM */
   506         /* REMIND: SOCKET CLOSED PROBLEM */
   683         if (fd == -2) {
   507         if (fd == -2) {
   684             JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
   508             JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
   690         return;
   514         return;
   691     }
   515     }
   692     SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, 0);
   516     SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, 0);
   693     (*env)->SetIntField(env, socketFdObj, IO_fd_fdID, fd);
   517     (*env)->SetIntField(env, socketFdObj, IO_fd_fdID, fd);
   694 
   518 
   695     if (sa.sa.sa_family == AF_INET) {
   519     if (sa.sa.sa_family != AF_INET) {
   696         if (inet4Cls == NULL) {
   520         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   697             jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
   521                         "Protocol family not supported");
   698             if (c != NULL) {
   522         return;
   699                 inet4Cls = (*env)->NewGlobalRef(env, c);
   523     }
   700                 (*env)->DeleteLocalRef(env, c);
   524 
   701             }
   525     if (inet4Cls == NULL) {
   702         }
   526         jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
   703 
   527         if (c != NULL) {
       
   528             inet4Cls = (*env)->NewGlobalRef(env, c);
       
   529             (*env)->DeleteLocalRef(env, c);
       
   530         }
       
   531     }
       
   532 
       
   533     /*
       
   534      * fill up the remote peer port and address in the new socket structure
       
   535      */
       
   536     if (inet4Cls != NULL) {
       
   537         socketAddressObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID);
       
   538     } else {
       
   539         socketAddressObj = NULL;
       
   540     }
       
   541     if (socketAddressObj == NULL) {
   704         /*
   542         /*
   705          * fill up the remote peer port and address in the new socket structure
   543          * FindClass or NewObject failed so close connection and
       
   544          * exit (there will be a pending exception).
   706          */
   545          */
   707         if (inet4Cls != NULL) {
   546         NET_SocketClose(fd);
   708             socketAddressObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID);
   547         return;
   709         } else {
   548     }
   710             socketAddressObj = NULL;
   549 
   711         }
   550     setInetAddress_addr(env, socketAddressObj, ntohl(sa.sa4.sin_addr.s_addr));
   712         if (socketAddressObj == NULL) {
   551     setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv4);
   713             /*
   552     (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
   714              * FindClass or NewObject failed so close connection and
       
   715              * exist (there will be a pending exception).
       
   716              */
       
   717             NET_SocketClose(fd);
       
   718             return;
       
   719         }
       
   720 
       
   721         setInetAddress_addr(env, socketAddressObj, ntohl(sa.sa4.sin_addr.s_addr));
       
   722         setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv4);
       
   723         (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
       
   724     } else {
       
   725         /* AF_INET6 -> Inet6Address */
       
   726         if (inet6Cls == 0) {
       
   727             jclass c = (*env)->FindClass(env, "java/net/Inet6Address");
       
   728             if (c != NULL) {
       
   729                 inet6Cls = (*env)->NewGlobalRef(env, c);
       
   730                 (*env)->DeleteLocalRef(env, c);
       
   731             }
       
   732         }
       
   733 
       
   734         if (inet6Cls != NULL) {
       
   735             socketAddressObj = (*env)->NewObject(env, inet6Cls, ia6_ctrID);
       
   736         } else {
       
   737             socketAddressObj = NULL;
       
   738         }
       
   739         if (socketAddressObj == NULL) {
       
   740             /*
       
   741              * FindClass or NewObject failed so close connection and
       
   742              * exist (there will be a pending exception).
       
   743              */
       
   744             NET_SocketClose(fd);
       
   745             return;
       
   746         }
       
   747         setInet6Address_ipaddress(env, socketAddressObj, (char *)&sa.sa6.sin6_addr);
       
   748         setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv6);
       
   749         setInet6Address_scopeid(env, socketAddressObj, sa.sa6.sin6_scope_id);
       
   750 
       
   751     }
       
   752     /* fields common to AF_INET and AF_INET6 */
       
   753 
       
   754     port = ntohs ((u_short)GET_PORT(&sa));
   553     port = ntohs ((u_short)GET_PORT(&sa));
   755     (*env)->SetIntField(env, socket, psi_portID, (int)port);
   554     (*env)->SetIntField(env, socket, psi_portID, (int)port);
   756     port = (*env)->GetIntField(env, this, psi_localportID);
   555     port = (*env)->GetIntField(env, this, psi_localportID);
   757     (*env)->SetIntField(env, socket, psi_localportID, port);
   556     (*env)->SetIntField(env, socket, psi_localportID, port);
   758     (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
   557     (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
   793 JNIEXPORT void JNICALL
   592 JNIEXPORT void JNICALL
   794 Java_java_net_TwoStacksPlainSocketImpl_socketClose0(JNIEnv *env, jobject this,
   593 Java_java_net_TwoStacksPlainSocketImpl_socketClose0(JNIEnv *env, jobject this,
   795                                            jboolean useDeferredClose) {
   594                                            jboolean useDeferredClose) {
   796 
   595 
   797     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
   596     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
   798     jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
   597     jint fd=-1;
   799     jint fd=-1, fd1=-1;
   598 
   800 
   599     if (IS_NULL(fdObj)) {
   801     if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) {
       
   802         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   600         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
   803                         "socket already closed");
   601                         "socket already closed");
   804         return;
   602         return;
   805     }
   603     }
   806     if (!IS_NULL(fdObj)) {
   604     if (!IS_NULL(fdObj)) {
   807         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
   605         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
   808     }
       
   809     if (!IS_NULL(fd1Obj)) {
       
   810         fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
       
   811     }
   606     }
   812     if (fd != -1) {
   607     if (fd != -1) {
   813         (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
   608         (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
   814         NET_SocketClose(fd);
   609         NET_SocketClose(fd);
   815     }
       
   816     if (fd1 != -1) {
       
   817         (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1);
       
   818         NET_SocketClose(fd1);
       
   819     }
   610     }
   820 }
   611 }
   821 
   612 
   822 /*
   613 /*
   823  * Socket options for plainsocketImpl
   614  * Socket options for plainsocketImpl
   829  */
   620  */
   830 JNIEXPORT void JNICALL
   621 JNIEXPORT void JNICALL
   831 Java_java_net_TwoStacksPlainSocketImpl_socketNativeSetOption
   622 Java_java_net_TwoStacksPlainSocketImpl_socketNativeSetOption
   832   (JNIEnv *env, jobject this, jint cmd, jboolean on, jobject value)
   623   (JNIEnv *env, jobject this, jint cmd, jboolean on, jobject value)
   833 {
   624 {
   834     int fd, fd1;
   625     int fd;
   835     int level = 0, optname = 0, optlen = 0;
   626     int level = 0, optname = 0, optlen = 0;
   836     union {
   627     union {
   837         int i;
   628         int i;
   838         struct linger ling;
   629         struct linger ling;
   839     } optval;
   630     } optval;
   841     memset((char *)&optval, 0, sizeof(optval));
   632     memset((char *)&optval, 0, sizeof(optval));
   842     /*
   633     /*
   843      * Get SOCKET and check that it hasn't been closed
   634      * Get SOCKET and check that it hasn't been closed
   844      */
   635      */
   845     fd = getFD(env, this);
   636     fd = getFD(env, this);
   846     fd1 = getFD1(env, this);
   637     if (fd < 0) {
   847     if (fd < 0 && fd1 < 0) {
       
   848         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
   638         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
   849         return;
   639         return;
   850     }
   640     }
   851 
   641 
   852     /*
   642     /*
   897                 if (WSAGetLastError() == WSAENOPROTOOPT) {
   687                 if (WSAGetLastError() == WSAENOPROTOOPT) {
   898                     isRcvTimeoutSupported = JNI_FALSE;
   688                     isRcvTimeoutSupported = JNI_FALSE;
   899                 } else {
   689                 } else {
   900                     NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO");
   690                     NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO");
   901                     return;
   691                     return;
   902                 }
       
   903             }
       
   904             if (fd1 != -1) {
       
   905                 if (setsockopt(fd1, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
       
   906                                         sizeof(timeout)) < 0) {
       
   907                     NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO");
       
   908                 }
   692                 }
   909             }
   693             }
   910         }
   694         }
   911         return;
   695         return;
   912     }
   696     }
   978     if (fd != -1) {
   762     if (fd != -1) {
   979         if (NET_SetSockOpt(fd, level, optname, (void *)&optval, optlen) < 0) {
   763         if (NET_SetSockOpt(fd, level, optname, (void *)&optval, optlen) < 0) {
   980             NET_ThrowCurrent(env, "setsockopt");
   764             NET_ThrowCurrent(env, "setsockopt");
   981         }
   765         }
   982     }
   766     }
   983 
       
   984     if (fd1 != -1) {
       
   985         if (NET_SetSockOpt(fd1, level, optname, (void *)&optval, optlen) < 0) {
       
   986             NET_ThrowCurrent(env, "setsockopt");
       
   987         }
       
   988     }
       
   989 }
   767 }
   990 
   768 
   991 
   769 
   992 /*
   770 /*
   993  * Class:     java_net_TwoStacksPlainSocketImpl
   771  * Class:     java_net_TwoStacksPlainSocketImpl
   996  */
   774  */
   997 JNIEXPORT jint JNICALL
   775 JNIEXPORT jint JNICALL
   998 Java_java_net_TwoStacksPlainSocketImpl_socketGetOption
   776 Java_java_net_TwoStacksPlainSocketImpl_socketGetOption
   999   (JNIEnv *env, jobject this, jint opt, jobject iaContainerObj)
   777   (JNIEnv *env, jobject this, jint opt, jobject iaContainerObj)
  1000 {
   778 {
  1001     int fd, fd1;
   779     int fd;
  1002     int level = 0, optname = 0, optlen = 0;
   780     int level = 0, optname = 0, optlen = 0;
  1003     union {
   781     union {
  1004         int i;
   782         int i;
  1005         struct linger ling;
   783         struct linger ling;
  1006     } optval;
   784     } optval;
  1007 
   785 
  1008     /*
   786     /*
  1009      * Get SOCKET and check it hasn't been closed
   787      * Get SOCKET and check it hasn't been closed
  1010      */
   788      */
  1011     fd = getFD(env, this);
   789     fd = getFD(env, this);
  1012     fd1 = getFD1(env, this);
       
  1013     memset((char *)&optval, 0, sizeof(optval));
   790     memset((char *)&optval, 0, sizeof(optval));
  1014 
   791 
  1015     if (fd < 0 && fd1 < 0) {
   792     if (fd < 0) {
  1016         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
   793         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
  1017         return -1;
   794         return -1;
  1018     }
   795     }
  1019     if (fd < 0) {
       
  1020         fd = fd1;
       
  1021     }
       
  1022 
       
  1023     /* For IPv6, we assume both sockets have the same setting always */
       
  1024 
   796 
  1025     /*
   797     /*
  1026      * SO_BINDADDR isn't a socket option
   798      * SO_BINDADDR isn't a socket option
  1027      */
   799      */
  1028     if (opt == java_net_SocketOptions_SO_BINDADDR) {
   800     if (opt == java_net_SocketOptions_SO_BINDADDR) {
  1033         jclass iaCntrClass;
   805         jclass iaCntrClass;
  1034         jfieldID iaFieldID;
   806         jfieldID iaFieldID;
  1035 
   807 
  1036         memset((char *)&sa, 0, len);
   808         memset((char *)&sa, 0, len);
  1037 
   809 
  1038         if (fd == -1) {
       
  1039             /* must be an IPV6 only socket. Case where both sockets are != -1
       
  1040              * is handled in java
       
  1041              */
       
  1042             fd = getFD1 (env, this);
       
  1043         }
       
  1044 
       
  1045         if (getsockname(fd, &sa.sa, &len) < 0) {
   810         if (getsockname(fd, &sa.sa, &len) < 0) {
  1046             JNU_ThrowByNameWithMessageAndLastError
   811             JNU_ThrowByNameWithMessageAndLastError
  1047                 (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
   812                 (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
  1048             return -1;
   813             return -1;
  1049         }
   814         }