src/windows/native/java/net/TwoStacksPlainSocketImpl.c

Print this page




 191 {
 192     jint localport = (*env)->GetIntField(env, this, psi_localportID);
 193 
 194     /* family and localport are int fields of iaObj */
 195     int family;
 196     jint fd, fd1=-1;
 197     jint len;
 198     int  ipv6_supported = ipv6_available();
 199 
 200     /* fd initially points to the IPv4 socket and fd1 to the IPv6 socket
 201      * If we want to connect to IPv6 then we swap the two sockets/objects
 202      * This way, fd is always the connected socket, and fd1 always gets closed.
 203      */
 204     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
 205     jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
 206 
 207     SOCKETADDRESS him;
 208 
 209     /* The result of the connection */
 210     int connect_res;

 211 
 212     if (!IS_NULL(fdObj)) {
 213         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 214     }
 215 
 216     if (ipv6_supported && !IS_NULL(fd1Obj)) {
 217         fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
 218     }
 219 
 220     if (IS_NULL(iaObj)) {
 221         JNU_ThrowNullPointerException(env, "inet address argument is null.");
 222         return;
 223     }
 224 
 225     if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&him, &len, JNI_FALSE) != 0) {
 226       return;
 227     }
 228 
 229     family = him.him.sa_family;
 230     if (family == AF_INET6) {


 383             return;
 384         }
 385         port = ntohs ((u_short)GET_PORT(&him));
 386         (*env)->SetIntField(env, this, psi_localportID, (int) port);
 387     }
 388 }
 389 
 390 /*
 391  * Class:     java_net_TwoStacksPlainSocketImpl
 392  * Method:    socketBind
 393  * Signature: (Ljava/net/InetAddress;I)V
 394  */
 395 JNIEXPORT void JNICALL
 396 Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this,
 397                                          jobject iaObj, jint localport,
 398                                          jboolean exclBind) {
 399 
 400     /* fdObj is the FileDescriptor field on this */
 401     jobject fdObj, fd1Obj;
 402     /* fd is an int field on fdObj */
 403     int fd, fd1, len;
 404     int ipv6_supported = ipv6_available();
 405 
 406     /* family is an int field of iaObj */
 407     int family;
 408     int rv;
 409 
 410     SOCKETADDRESS him;
 411 
 412     fdObj = (*env)->GetObjectField(env, this, psi_fdID);
 413     fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
 414 
 415     family = getInetAddress_family(env, iaObj);
 416 
 417     if (family == IPv6 && !ipv6_supported) {
 418         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 419                         "Protocol family not supported");
 420         return;
 421     }
 422 
 423     if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) {


 826     if (fd1 != -1) {
 827         (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1);
 828         NET_SocketClose(fd1);
 829     }
 830 }
 831 
 832 /*
 833  * Socket options for plainsocketImpl
 834  *
 835  *
 836  * Class:     java_net_TwoStacksPlainSocketImpl
 837  * Method:    socketNativeSetOption
 838  * Signature: (IZLjava/lang/Object;)V
 839  */
 840 JNIEXPORT void JNICALL
 841 Java_java_net_TwoStacksPlainSocketImpl_socketNativeSetOption(JNIEnv *env,
 842                                               jobject this,
 843                                               jint cmd, jboolean on,
 844                                               jobject value) {
 845     int fd, fd1;
 846     int level, optname, optlen;
 847     union {
 848         int i;
 849         struct linger ling;
 850     } optval;
 851 

 852     /*
 853      * Get SOCKET and check that it hasn't been closed
 854      */
 855     fd = getFD(env, this);
 856     fd1 = getFD1(env, this);
 857     if (fd < 0 && fd1 < 0) {
 858         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
 859         return;
 860     }
 861 
 862     /*
 863      * SO_TIMEOUT is the socket option used to specify the timeout
 864      * for ServerSocket.accept and Socket.getInputStream().read.
 865      * It does not typically map to a native level socket option.
 866      * For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO
 867      * socket option to specify a receive timeout on the socket. This
 868      * receive timeout is applicable to Socket only and the socket
 869      * option should not be set on ServerSocket.
 870      */
 871     if (cmd == java_net_SocketOptions_SO_TIMEOUT) {


 992     }
 993 
 994     if (fd1 != -1) {
 995         if (NET_SetSockOpt(fd1, level, optname, (void *)&optval, optlen) < 0) {
 996             NET_ThrowCurrent(env, "setsockopt");
 997         }
 998     }
 999 }
1000 
1001 
1002 /*
1003  * Class:     java_net_TwoStacksPlainSocketImpl
1004  * Method:    socketGetOption
1005  * Signature: (I)I
1006  */
1007 JNIEXPORT jint JNICALL
1008 Java_java_net_TwoStacksPlainSocketImpl_socketGetOption(JNIEnv *env, jobject this,
1009                                               jint opt, jobject iaContainerObj) {
1010 
1011     int fd, fd1;
1012     int level, optname, optlen;
1013     union {
1014         int i;
1015         struct linger ling;
1016     } optval;
1017 
1018     /*
1019      * Get SOCKET and check it hasn't been closed
1020      */
1021     fd = getFD(env, this);
1022     fd1 = getFD1(env, this);

1023 
1024     if (fd < 0 && fd1 < 0) {
1025         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
1026         return -1;
1027     }
1028     if (fd < 0) {
1029         fd = fd1;
1030     }
1031 
1032     /* For IPv6, we assume both sockets have the same setting always */
1033 
1034     /*
1035      * SO_BINDADDR isn't a socket option
1036      */
1037     if (opt == java_net_SocketOptions_SO_BINDADDR) {
1038         SOCKETADDRESS him;
1039         int len;
1040         int port;
1041         jobject iaObj;
1042         jclass iaCntrClass;
1043         jfieldID iaFieldID;
1044 
1045         len = sizeof(him);

1046 
1047         if (fd == -1) {
1048             /* must be an IPV6 only socket. Case where both sockets are != -1
1049              * is handled in java
1050              */
1051             fd = getFD1 (env, this);
1052         }
1053 
1054         if (getsockname(fd, (struct sockaddr *)&him, &len) < 0) {
1055             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1056                              "Error getting socket name");
1057             return -1;
1058         }
1059         iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
1060         CHECK_NULL_RETURN(iaObj, -1);
1061 
1062         iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj);
1063         iaFieldID = (*env)->GetFieldID(env, iaCntrClass, "addr", "Ljava/net/InetAddress;");
1064         CHECK_NULL_RETURN(iaFieldID, -1);
1065         (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);




 191 {
 192     jint localport = (*env)->GetIntField(env, this, psi_localportID);
 193 
 194     /* family and localport are int fields of iaObj */
 195     int family;
 196     jint fd, fd1=-1;
 197     jint len;
 198     int  ipv6_supported = ipv6_available();
 199 
 200     /* fd initially points to the IPv4 socket and fd1 to the IPv6 socket
 201      * If we want to connect to IPv6 then we swap the two sockets/objects
 202      * This way, fd is always the connected socket, and fd1 always gets closed.
 203      */
 204     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
 205     jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
 206 
 207     SOCKETADDRESS him;
 208 
 209     /* The result of the connection */
 210     int connect_res;
 211     memset((char *)&him, 0, sizeof(him));
 212 
 213     if (!IS_NULL(fdObj)) {
 214         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 215     }
 216 
 217     if (ipv6_supported && !IS_NULL(fd1Obj)) {
 218         fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
 219     }
 220 
 221     if (IS_NULL(iaObj)) {
 222         JNU_ThrowNullPointerException(env, "inet address argument is null.");
 223         return;
 224     }
 225 
 226     if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&him, &len, JNI_FALSE) != 0) {
 227       return;
 228     }
 229 
 230     family = him.him.sa_family;
 231     if (family == AF_INET6) {


 384             return;
 385         }
 386         port = ntohs ((u_short)GET_PORT(&him));
 387         (*env)->SetIntField(env, this, psi_localportID, (int) port);
 388     }
 389 }
 390 
 391 /*
 392  * Class:     java_net_TwoStacksPlainSocketImpl
 393  * Method:    socketBind
 394  * Signature: (Ljava/net/InetAddress;I)V
 395  */
 396 JNIEXPORT void JNICALL
 397 Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this,
 398                                          jobject iaObj, jint localport,
 399                                          jboolean exclBind) {
 400 
 401     /* fdObj is the FileDescriptor field on this */
 402     jobject fdObj, fd1Obj;
 403     /* fd is an int field on fdObj */
 404     int fd, fd1, len = 0;
 405     int ipv6_supported = ipv6_available();
 406 
 407     /* family is an int field of iaObj */
 408     int family;
 409     int rv;
 410 
 411     SOCKETADDRESS him;
 412 
 413     fdObj = (*env)->GetObjectField(env, this, psi_fdID);
 414     fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
 415 
 416     family = getInetAddress_family(env, iaObj);
 417 
 418     if (family == IPv6 && !ipv6_supported) {
 419         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 420                         "Protocol family not supported");
 421         return;
 422     }
 423 
 424     if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) {


 827     if (fd1 != -1) {
 828         (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1);
 829         NET_SocketClose(fd1);
 830     }
 831 }
 832 
 833 /*
 834  * Socket options for plainsocketImpl
 835  *
 836  *
 837  * Class:     java_net_TwoStacksPlainSocketImpl
 838  * Method:    socketNativeSetOption
 839  * Signature: (IZLjava/lang/Object;)V
 840  */
 841 JNIEXPORT void JNICALL
 842 Java_java_net_TwoStacksPlainSocketImpl_socketNativeSetOption(JNIEnv *env,
 843                                               jobject this,
 844                                               jint cmd, jboolean on,
 845                                               jobject value) {
 846     int fd, fd1;
 847     int level = 0, optname = 0, optlen = 0;
 848     union {
 849         int i;
 850         struct linger ling;
 851     } optval;
 852 
 853     memset((char *)&optval, 0, sizeof(optval));
 854     /*
 855      * Get SOCKET and check that it hasn't been closed
 856      */
 857     fd = getFD(env, this);
 858     fd1 = getFD1(env, this);
 859     if (fd < 0 && fd1 < 0) {
 860         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
 861         return;
 862     }
 863 
 864     /*
 865      * SO_TIMEOUT is the socket option used to specify the timeout
 866      * for ServerSocket.accept and Socket.getInputStream().read.
 867      * It does not typically map to a native level socket option.
 868      * For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO
 869      * socket option to specify a receive timeout on the socket. This
 870      * receive timeout is applicable to Socket only and the socket
 871      * option should not be set on ServerSocket.
 872      */
 873     if (cmd == java_net_SocketOptions_SO_TIMEOUT) {


 994     }
 995 
 996     if (fd1 != -1) {
 997         if (NET_SetSockOpt(fd1, level, optname, (void *)&optval, optlen) < 0) {
 998             NET_ThrowCurrent(env, "setsockopt");
 999         }
1000     }
1001 }
1002 
1003 
1004 /*
1005  * Class:     java_net_TwoStacksPlainSocketImpl
1006  * Method:    socketGetOption
1007  * Signature: (I)I
1008  */
1009 JNIEXPORT jint JNICALL
1010 Java_java_net_TwoStacksPlainSocketImpl_socketGetOption(JNIEnv *env, jobject this,
1011                                               jint opt, jobject iaContainerObj) {
1012 
1013     int fd, fd1;
1014     int level = 0, optname = 0, optlen = 0;
1015     union {
1016         int i;
1017         struct linger ling;
1018     } optval;

1019     /*
1020      * Get SOCKET and check it hasn't been closed
1021      */
1022     fd = getFD(env, this);
1023     fd1 = getFD1(env, this);
1024     memset((char *)&optval, 0, sizeof(optval));
1025 
1026     if (fd < 0 && fd1 < 0) {
1027         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
1028         return -1;
1029     }
1030     if (fd < 0) {
1031         fd = fd1;
1032     }
1033 
1034     /* For IPv6, we assume both sockets have the same setting always */
1035 
1036     /*
1037      * SO_BINDADDR isn't a socket option
1038      */
1039     if (opt == java_net_SocketOptions_SO_BINDADDR) {
1040         SOCKETADDRESS him;
1041         int len;
1042         int port;
1043         jobject iaObj;
1044         jclass iaCntrClass;
1045         jfieldID iaFieldID;
1046 
1047         len = sizeof(him);
1048         memset((char *)&him, 0, len);
1049 
1050         if (fd == -1) {
1051             /* must be an IPV6 only socket. Case where both sockets are != -1
1052              * is handled in java
1053              */
1054             fd = getFD1 (env, this);
1055         }
1056 
1057         if (getsockname(fd, (struct sockaddr *)&him, &len) < 0) {
1058             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1059                              "Error getting socket name");
1060             return -1;
1061         }
1062         iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
1063         CHECK_NULL_RETURN(iaObj, -1);
1064 
1065         iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj);
1066         iaFieldID = (*env)->GetFieldID(env, iaCntrClass, "addr", "Ljava/net/InetAddress;");
1067         CHECK_NULL_RETURN(iaFieldID, -1);
1068         (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);