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);
|