94 * Create the marker file descriptor by establishing a loopback connection
95 * which we shutdown but do not close the fd. The result is an fd that
96 * can be used for read/write.
97 */
98 static int getMarkerFD()
99 {
100 int sv[2];
101
102 #ifdef AF_UNIX
103 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
104 return -1;
105 }
106 #else
107 return -1;
108 #endif
109
110 /*
111 * Finally shutdown sv[0] (any reads to this fd will get
112 * EOF; any writes will get an error).
113 */
114 JVM_SocketShutdown(sv[0], 2);
115 JVM_SocketClose(sv[1]);
116
117 return sv[0];
118 }
119
120 /*
121 * Return the file descriptor given a PlainSocketImpl
122 */
123 static int getFD(JNIEnv *env, jobject this) {
124 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
125 CHECK_NULL_RETURN(fdObj, -1);
126 return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
127 }
128
129 /*
130 * The initroto function is called whenever PlainSocketImpl is
131 * loaded, to cache field IDs for efficiency. This is called every time
132 * the Java class is loaded.
133 *
134 * Class: java_net_PlainSocketImpl
135 * Method: initProto
188 int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
189 #ifdef AF_INET6
190 int domain = ipv6_available() ? AF_INET6 : AF_INET;
191 #else
192 int domain = AF_INET;
193 #endif
194
195 if (socketExceptionCls == NULL) {
196 jclass c = (*env)->FindClass(env, "java/net/SocketException");
197 CHECK_NULL(c);
198 socketExceptionCls = (jclass)(*env)->NewGlobalRef(env, c);
199 CHECK_NULL(socketExceptionCls);
200 }
201 fdObj = (*env)->GetObjectField(env, this, psi_fdID);
202
203 if (fdObj == NULL) {
204 (*env)->ThrowNew(env, socketExceptionCls, "null fd object");
205 return;
206 }
207
208 if ((fd = JVM_Socket(domain, type, 0)) == JVM_IO_ERR) {
209 /* note: if you run out of fds, you may not be able to load
210 * the exception class, and get a NoClassDefFoundError
211 * instead.
212 */
213 NET_ThrowNew(env, errno, "can't create socket");
214 return;
215 }
216
217 #ifdef AF_INET6
218 /* Disable IPV6_V6ONLY to ensure dual-socket support */
219 if (domain == AF_INET6) {
220 int arg = 0;
221 if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
222 sizeof(int)) < 0) {
223 NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
224 close(fd);
225 return;
226 }
227 }
228 #endif /* AF_INET6 */
229
230 /*
231 * If this is a server socket then enable SO_REUSEADDR
232 * automatically and set to non blocking.
233 */
234 ssObj = (*env)->GetObjectField(env, this, psi_serverSocketID);
235 if (ssObj != NULL) {
236 int arg = 1;
237 SET_NONBLOCKING(fd);
238 if (JVM_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
239 sizeof(arg)) < 0) {
240 NET_ThrowNew(env, errno, "cannot set SO_REUSEADDR");
241 close(fd);
242 return;
243 }
244 }
245
246 (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
247 }
248
249 /*
250 * inetAddress is the address object passed to the socket connect
251 * call.
252 *
253 * Class: java_net_PlainSocketImpl
254 * Method: socketConnect
255 * Signature: (Ljava/net/InetAddress;I)V
256 */
257 JNIEXPORT void JNICALL
258 Java_java_net_PlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
286 }
287 if (IS_NULL(iaObj)) {
288 JNU_ThrowNullPointerException(env, "inet address argument null.");
289 return;
290 }
291
292 /* connect */
293 if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&him, &len, JNI_TRUE) != 0) {
294 return;
295 }
296 setDefaultScopeID(env, (struct sockaddr *)&him);
297
298 #ifdef AF_INET6
299 if (trafficClass != 0 && ipv6_available()) {
300 NET_SetTrafficClass((struct sockaddr *)&him, trafficClass);
301 }
302 #endif /* AF_INET6 */
303 if (timeout <= 0) {
304 connect_rv = NET_Connect(fd, (struct sockaddr *)&him, len);
305 #ifdef __solaris__
306 if (connect_rv == JVM_IO_ERR && errno == EINPROGRESS ) {
307
308 /* This can happen if a blocking connect is interrupted by a signal.
309 * See 6343810.
310 */
311 while (1) {
312 #ifndef USE_SELECT
313 {
314 struct pollfd pfd;
315 pfd.fd = fd;
316 pfd.events = POLLOUT;
317
318 connect_rv = NET_Poll(&pfd, 1, -1);
319 }
320 #else
321 {
322 fd_set wr, ex;
323
324 FD_ZERO(&wr);
325 FD_SET(fd, &wr);
326 FD_ZERO(&ex);
327 FD_SET(fd, &ex);
328
329 connect_rv = NET_Select(fd+1, 0, &wr, &ex, 0);
330 }
331 #endif
332
333 if (connect_rv == JVM_IO_ERR) {
334 if (errno == EINTR) {
335 continue;
336 } else {
337 break;
338 }
339 }
340 if (connect_rv > 0) {
341 int optlen;
342 /* has connection been established */
343 optlen = sizeof(connect_rv);
344 if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR,
345 (void*)&connect_rv, &optlen) <0) {
346 connect_rv = errno;
347 }
348
349 if (connect_rv != 0) {
350 /* restore errno */
351 errno = connect_rv;
352 connect_rv = JVM_IO_ERR;
353 }
354 break;
355 }
356 }
357 }
358 #endif
359 } else {
360 /*
361 * A timeout was specified. We put the socket into non-blocking
362 * mode, connect, and then wait for the connection to be
363 * established, fail, or timeout.
364 */
365 SET_NONBLOCKING(fd);
366
367 /* no need to use NET_Connect as non-blocking */
368 connect_rv = connect(fd, (struct sockaddr *)&him, len);
369
370 /* connection not established immediately */
371 if (connect_rv != 0) {
372 int optlen;
373 jlong prevTime = JVM_CurrentTimeMillis(env, 0);
374
375 if (errno != EINPROGRESS) {
376 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
377 "connect failed");
378 SET_BLOCKING(fd);
379 return;
380 }
381
382 /*
383 * Wait for the connection to be established or a
384 * timeout occurs. poll/select needs to handle EINTR in
385 * case lwp sig handler redirects any process signals to
386 * this thread.
387 */
388 while (1) {
389 jlong newTime;
390 #ifndef USE_SELECT
391 {
392 struct pollfd pfd;
429 timeout -= (newTime - prevTime);
430 if (timeout <= 0) {
431 connect_rv = 0;
432 break;
433 }
434 prevTime = newTime;
435
436 } /* while */
437
438 if (connect_rv == 0) {
439 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
440 "connect timed out");
441
442 /*
443 * Timeout out but connection may still be established.
444 * At the high level it should be closed immediately but
445 * just in case we make the socket blocking again and
446 * shutdown input & output.
447 */
448 SET_BLOCKING(fd);
449 JVM_SocketShutdown(fd, 2);
450 return;
451 }
452
453 /* has connection been established */
454 optlen = sizeof(connect_rv);
455 if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
456 &optlen) <0) {
457 connect_rv = errno;
458 }
459 }
460
461 /* make socket blocking again */
462 SET_BLOCKING(fd);
463
464 /* restore errno */
465 if (connect_rv != 0) {
466 errno = connect_rv;
467 connect_rv = JVM_IO_ERR;
468 }
469 }
470
471 /* report the appropriate exception */
472 if (connect_rv < 0) {
473
474 #ifdef __linux__
475 /*
476 * Linux/GNU distribution setup /etc/hosts so that
477 * InetAddress.getLocalHost gets back the loopback address
478 * rather than the host address. Thus a socket can be
479 * bound to the loopback address and the connect will
480 * fail with EADDRNOTAVAIL. In addition the Linux kernel
481 * returns the wrong error in this case - it returns EINVAL
482 * instead of EADDRNOTAVAIL. We handle this here so that
483 * a more descriptive exception text is used.
484 */
485 if (connect_rv == JVM_IO_ERR && errno == EINVAL) {
486 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
487 "Invalid argument or cannot assign requested address");
488 return;
489 }
490 #endif
491 if (connect_rv == JVM_IO_INTR) {
492 JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
493 "operation interrupted");
494 #if defined(EPROTO)
495 } else if (errno == EPROTO) {
496 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ProtocolException",
497 "Protocol error");
498 #endif
499 } else if (errno == ECONNREFUSED) {
500 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
501 "Connection refused");
502 } else if (errno == ETIMEDOUT) {
503 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
504 "Connection timed out");
505 } else if (errno == EHOSTUNREACH) {
506 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException",
507 "Host unreachable");
508 } else if (errno == EADDRNOTAVAIL) {
509 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException",
510 "Address not available");
511 } else if ((errno == EISCONN) || (errno == EBADF)) {
512 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
513 "Socket closed");
514 } else {
515 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "connect failed");
516 }
517 return;
518 }
519
520 (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
521
522 /* set the remote peer address and port */
523 (*env)->SetObjectField(env, this, psi_addressID, iaObj);
524 (*env)->SetIntField(env, this, psi_portID, port);
525
526 /*
527 * we need to initialize the local port field if bind was called
528 * previously to the connect (by the client) then localport field
529 * will already be initialized
530 */
531 if (localport == 0) {
532 /* Now that we're a connected socket, let's extract the port number
533 * that the system chose for us and store it in the Socket object.
534 */
535 len = SOCKADDR_LEN;
536 if (JVM_GetSockName(fd, (struct sockaddr *)&him, &len) == -1) {
537 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
538 "Error getting socket name");
539 } else {
540 localport = NET_GetPortFromSockaddr((struct sockaddr *)&him);
541 (*env)->SetIntField(env, this, psi_localportID, localport);
542 }
543 }
544 }
545
546 /*
547 * Class: java_net_PlainSocketImpl
548 * Method: socketBind
549 * Signature: (Ljava/net/InetAddress;I)V
550 */
551 JNIEXPORT void JNICALL
552 Java_java_net_PlainSocketImpl_socketBind(JNIEnv *env, jobject this,
553 jobject iaObj, jint localport) {
554
555 /* fdObj is the FileDescriptor field on this */
556 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
577 }
578 setDefaultScopeID(env, (struct sockaddr *)&him);
579
580 if (NET_Bind(fd, (struct sockaddr *)&him, len) < 0) {
581 if (errno == EADDRINUSE || errno == EADDRNOTAVAIL ||
582 errno == EPERM || errno == EACCES) {
583 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "BindException",
584 "Bind failed");
585 } else {
586 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
587 "Bind failed");
588 }
589 return;
590 }
591
592 /* set the address */
593 (*env)->SetObjectField(env, this, psi_addressID, iaObj);
594
595 /* initialize the local port */
596 if (localport == 0) {
597 /* Now that we're a connected socket, let's extract the port number
598 * that the system chose for us and store it in the Socket object.
599 */
600 if (JVM_GetSockName(fd, (struct sockaddr *)&him, &len) == -1) {
601 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
602 "Error getting socket name");
603 return;
604 }
605 localport = NET_GetPortFromSockaddr((struct sockaddr *)&him);
606 (*env)->SetIntField(env, this, psi_localportID, localport);
607 } else {
608 (*env)->SetIntField(env, this, psi_localportID, localport);
609 }
610 }
611
612 /*
613 * Class: java_net_PlainSocketImpl
614 * Method: socketListen
615 * Signature: (I)V
616 */
617 JNIEXPORT void JNICALL
618 Java_java_net_PlainSocketImpl_socketListen (JNIEnv *env, jobject this,
619 jint count)
620 {
621 /* this FileDescriptor fd field */
622 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
623 /* fdObj's int fd field */
624 int fd;
625
626 if (IS_NULL(fdObj)) {
627 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
628 "Socket closed");
629 return;
630 } else {
631 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
632 }
633
634 /*
635 * Workaround for bugid 4101691 in Solaris 2.6. See 4106600.
636 * If listen backlog is Integer.MAX_VALUE then subtract 1.
637 */
638 if (count == 0x7fffffff)
639 count -= 1;
640
641 if (JVM_Listen(fd, count) == JVM_IO_ERR) {
642 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
643 "Listen failed");
644 }
645 }
646
647 /*
648 * Class: java_net_PlainSocketImpl
649 * Method: socketAccept
650 * Signature: (Ljava/net/SocketImpl;)V
651 */
652 JNIEXPORT void JNICALL
653 Java_java_net_PlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
654 jobject socket)
655 {
656 /* fields on this */
657 int port;
658 jint timeout = (*env)->GetIntField(env, this, psi_timeoutID);
659 jlong prevTime = 0;
660 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
661
662 /* the FileDescriptor field on socket */
663 jobject socketFdObj;
664 /* the InetAddress field on socket */
665 jobject socketAddressObj;
666
667 /* the ServerSocket fd int field on fdObj */
668 jint fd;
669
670 /* accepted fd */
671 jint newfd;
672
673 SOCKADDR him;
674 int len;
675
676 len = SOCKADDR_LEN;
677
678 if (IS_NULL(fdObj)) {
679 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
680 "Socket closed");
681 return;
682 } else {
683 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
684 }
685 if (IS_NULL(socket)) {
686 JNU_ThrowNullPointerException(env, "socket is null");
687 return;
688 }
689
690 /*
691 * accept connection but ignore ECONNABORTED indicating that
692 * connection was eagerly accepted by the OS but was reset
693 * before accept() was called.
694 *
695 * If accept timeout in place and timeout is adjusted with
696 * each ECONNABORTED or EWOULDBLOCK to ensure that semantics
699 for (;;) {
700 int ret;
701
702 /* first usage pick up current time */
703 if (prevTime == 0 && timeout > 0) {
704 prevTime = JVM_CurrentTimeMillis(env, 0);
705 }
706
707 /* passing a timeout of 0 to poll will return immediately,
708 but in the case of ServerSocket 0 means infinite. */
709 if (timeout <= 0) {
710 ret = NET_Timeout(fd, -1);
711 } else {
712 ret = NET_Timeout(fd, timeout);
713 }
714
715 if (ret == 0) {
716 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
717 "Accept timed out");
718 return;
719 } else if (ret == JVM_IO_ERR) {
720 if (errno == EBADF) {
721 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
722 } else {
723 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Accept failed");
724 }
725 return;
726 } else if (ret == JVM_IO_INTR) {
727 JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
728 "operation interrupted");
729 return;
730 }
731
732 newfd = NET_Accept(fd, (struct sockaddr *)&him, (jint*)&len);
733
734 /* connection accepted */
735 if (newfd >= 0) {
736 SET_BLOCKING(newfd);
737 break;
738 }
739
740 /* non (ECONNABORTED or EWOULDBLOCK) error */
741 if (!(errno == ECONNABORTED || errno == EWOULDBLOCK)) {
742 break;
743 }
744
745 /* ECONNABORTED or EWOULDBLOCK error so adjust timeout if there is one. */
746 if (timeout) {
747 jlong currTime = JVM_CurrentTimeMillis(env, 0);
748 timeout -= (currTime - prevTime);
749
750 if (timeout <= 0) {
751 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
752 "Accept timed out");
799
800 /*
801 * Class: java_net_PlainSocketImpl
802 * Method: socketAvailable
803 * Signature: ()I
804 */
805 JNIEXPORT jint JNICALL
806 Java_java_net_PlainSocketImpl_socketAvailable(JNIEnv *env, jobject this) {
807
808 jint ret = -1;
809 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
810 jint fd;
811
812 if (IS_NULL(fdObj)) {
813 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
814 "Socket closed");
815 return -1;
816 } else {
817 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
818 }
819 /* JVM_SocketAvailable returns 0 for failure, 1 for success */
820 if (!JVM_SocketAvailable(fd, &ret)){
821 if (errno == ECONNRESET) {
822 JNU_ThrowByName(env, "sun/net/ConnectionResetException", "");
823 } else {
824 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
825 "ioctl FIONREAD failed");
826 }
827 }
828 return ret;
829 }
830
831 /*
832 * Class: java_net_PlainSocketImpl
833 * Method: socketClose0
834 * Signature: (Z)V
835 */
836 JNIEXPORT void JNICALL
837 Java_java_net_PlainSocketImpl_socketClose0(JNIEnv *env, jobject this,
838 jboolean useDeferredClose) {
839
840 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
864 */
865 JNIEXPORT void JNICALL
866 Java_java_net_PlainSocketImpl_socketShutdown(JNIEnv *env, jobject this,
867 jint howto)
868 {
869
870 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
871 jint fd;
872
873 /*
874 * WARNING: THIS NEEDS LOCKING. ALSO: SHOULD WE CHECK for fd being
875 * -1 already?
876 */
877 if (IS_NULL(fdObj)) {
878 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
879 "socket already closed");
880 return;
881 } else {
882 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
883 }
884 JVM_SocketShutdown(fd, howto);
885 }
886
887
888 /*
889 * Class: java_net_PlainSocketImpl
890 * Method: socketSetOption
891 * Signature: (IZLjava/lang/Object;)V
892 */
893 JNIEXPORT void JNICALL
894 Java_java_net_PlainSocketImpl_socketSetOption(JNIEnv *env, jobject this,
895 jint cmd, jboolean on,
896 jobject value) {
897 int fd;
898 int level, optname, optlen;
899 union {
900 int i;
901 struct linger ling;
902 } optval;
903
904 /*
1084 jint data) {
1085 /* The fd field */
1086 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
1087 int n, fd;
1088 unsigned char d = data & 0xFF;
1089
1090 if (IS_NULL(fdObj)) {
1091 JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
1092 return;
1093 } else {
1094 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
1095 /* Bug 4086704 - If the Socket associated with this file descriptor
1096 * was closed (sysCloseFD), the the file descriptor is set to -1.
1097 */
1098 if (fd == -1) {
1099 JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
1100 return;
1101 }
1102
1103 }
1104 n = JVM_Send(fd, (char *)&d, 1, MSG_OOB);
1105 if (n == JVM_IO_ERR) {
1106 NET_ThrowByNameWithLastError(env, "java/io/IOException", "Write failed");
1107 return;
1108 }
1109 if (n == JVM_IO_INTR) {
1110 JNU_ThrowByName(env, "java/io/InterruptedIOException", 0);
1111 return;
1112 }
1113 }
|
94 * Create the marker file descriptor by establishing a loopback connection
95 * which we shutdown but do not close the fd. The result is an fd that
96 * can be used for read/write.
97 */
98 static int getMarkerFD()
99 {
100 int sv[2];
101
102 #ifdef AF_UNIX
103 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
104 return -1;
105 }
106 #else
107 return -1;
108 #endif
109
110 /*
111 * Finally shutdown sv[0] (any reads to this fd will get
112 * EOF; any writes will get an error).
113 */
114 shutdown(sv[0], 2);
115 close(sv[1]);
116
117 return sv[0];
118 }
119
120 /*
121 * Return the file descriptor given a PlainSocketImpl
122 */
123 static int getFD(JNIEnv *env, jobject this) {
124 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
125 CHECK_NULL_RETURN(fdObj, -1);
126 return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
127 }
128
129 /*
130 * The initroto function is called whenever PlainSocketImpl is
131 * loaded, to cache field IDs for efficiency. This is called every time
132 * the Java class is loaded.
133 *
134 * Class: java_net_PlainSocketImpl
135 * Method: initProto
188 int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
189 #ifdef AF_INET6
190 int domain = ipv6_available() ? AF_INET6 : AF_INET;
191 #else
192 int domain = AF_INET;
193 #endif
194
195 if (socketExceptionCls == NULL) {
196 jclass c = (*env)->FindClass(env, "java/net/SocketException");
197 CHECK_NULL(c);
198 socketExceptionCls = (jclass)(*env)->NewGlobalRef(env, c);
199 CHECK_NULL(socketExceptionCls);
200 }
201 fdObj = (*env)->GetObjectField(env, this, psi_fdID);
202
203 if (fdObj == NULL) {
204 (*env)->ThrowNew(env, socketExceptionCls, "null fd object");
205 return;
206 }
207
208 if ((fd = socket(domain, type, 0)) == -1) {
209 /* note: if you run out of fds, you may not be able to load
210 * the exception class, and get a NoClassDefFoundError
211 * instead.
212 */
213 NET_ThrowNew(env, errno, "can't create socket");
214 return;
215 }
216
217 #ifdef AF_INET6
218 /* Disable IPV6_V6ONLY to ensure dual-socket support */
219 if (domain == AF_INET6) {
220 int arg = 0;
221 if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
222 sizeof(int)) < 0) {
223 NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
224 close(fd);
225 return;
226 }
227 }
228 #endif /* AF_INET6 */
229
230 /*
231 * If this is a server socket then enable SO_REUSEADDR
232 * automatically and set to non blocking.
233 */
234 ssObj = (*env)->GetObjectField(env, this, psi_serverSocketID);
235 if (ssObj != NULL) {
236 int arg = 1;
237 SET_NONBLOCKING(fd);
238 if (NET_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
239 sizeof(arg)) < 0) {
240 NET_ThrowNew(env, errno, "cannot set SO_REUSEADDR");
241 close(fd);
242 return;
243 }
244 }
245
246 (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
247 }
248
249 /*
250 * inetAddress is the address object passed to the socket connect
251 * call.
252 *
253 * Class: java_net_PlainSocketImpl
254 * Method: socketConnect
255 * Signature: (Ljava/net/InetAddress;I)V
256 */
257 JNIEXPORT void JNICALL
258 Java_java_net_PlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
286 }
287 if (IS_NULL(iaObj)) {
288 JNU_ThrowNullPointerException(env, "inet address argument null.");
289 return;
290 }
291
292 /* connect */
293 if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&him, &len, JNI_TRUE) != 0) {
294 return;
295 }
296 setDefaultScopeID(env, (struct sockaddr *)&him);
297
298 #ifdef AF_INET6
299 if (trafficClass != 0 && ipv6_available()) {
300 NET_SetTrafficClass((struct sockaddr *)&him, trafficClass);
301 }
302 #endif /* AF_INET6 */
303 if (timeout <= 0) {
304 connect_rv = NET_Connect(fd, (struct sockaddr *)&him, len);
305 #ifdef __solaris__
306 if (connect_rv == -1 && errno == EINPROGRESS ) {
307
308 /* This can happen if a blocking connect is interrupted by a signal.
309 * See 6343810.
310 */
311 while (1) {
312 #ifndef USE_SELECT
313 {
314 struct pollfd pfd;
315 pfd.fd = fd;
316 pfd.events = POLLOUT;
317
318 connect_rv = NET_Poll(&pfd, 1, -1);
319 }
320 #else
321 {
322 fd_set wr, ex;
323
324 FD_ZERO(&wr);
325 FD_SET(fd, &wr);
326 FD_ZERO(&ex);
327 FD_SET(fd, &ex);
328
329 connect_rv = NET_Select(fd+1, 0, &wr, &ex, 0);
330 }
331 #endif
332
333 if (connect_rv == -1) {
334 if (errno == EINTR) {
335 continue;
336 } else {
337 break;
338 }
339 }
340 if (connect_rv > 0) {
341 socklen_t optlen;
342 /* has connection been established */
343 optlen = sizeof(connect_rv);
344 if (getsockopt(fd, SOL_SOCKET, SO_ERROR,
345 (void*)&connect_rv, &optlen) <0) {
346 connect_rv = errno;
347 }
348
349 if (connect_rv != 0) {
350 /* restore errno */
351 errno = connect_rv;
352 connect_rv = -1;
353 }
354 break;
355 }
356 }
357 }
358 #endif
359 } else {
360 /*
361 * A timeout was specified. We put the socket into non-blocking
362 * mode, connect, and then wait for the connection to be
363 * established, fail, or timeout.
364 */
365 SET_NONBLOCKING(fd);
366
367 /* no need to use NET_Connect as non-blocking */
368 connect_rv = connect(fd, (struct sockaddr *)&him, len);
369
370 /* connection not established immediately */
371 if (connect_rv != 0) {
372 socklen_t optlen;
373 jlong prevTime = JVM_CurrentTimeMillis(env, 0);
374
375 if (errno != EINPROGRESS) {
376 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
377 "connect failed");
378 SET_BLOCKING(fd);
379 return;
380 }
381
382 /*
383 * Wait for the connection to be established or a
384 * timeout occurs. poll/select needs to handle EINTR in
385 * case lwp sig handler redirects any process signals to
386 * this thread.
387 */
388 while (1) {
389 jlong newTime;
390 #ifndef USE_SELECT
391 {
392 struct pollfd pfd;
429 timeout -= (newTime - prevTime);
430 if (timeout <= 0) {
431 connect_rv = 0;
432 break;
433 }
434 prevTime = newTime;
435
436 } /* while */
437
438 if (connect_rv == 0) {
439 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
440 "connect timed out");
441
442 /*
443 * Timeout out but connection may still be established.
444 * At the high level it should be closed immediately but
445 * just in case we make the socket blocking again and
446 * shutdown input & output.
447 */
448 SET_BLOCKING(fd);
449 shutdown(fd, 2);
450 return;
451 }
452
453 /* has connection been established */
454 optlen = sizeof(connect_rv);
455 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
456 &optlen) <0) {
457 connect_rv = errno;
458 }
459 }
460
461 /* make socket blocking again */
462 SET_BLOCKING(fd);
463
464 /* restore errno */
465 if (connect_rv != 0) {
466 errno = connect_rv;
467 connect_rv = -1;
468 }
469 }
470
471 /* report the appropriate exception */
472 if (connect_rv < 0) {
473
474 #ifdef __linux__
475 /*
476 * Linux/GNU distribution setup /etc/hosts so that
477 * InetAddress.getLocalHost gets back the loopback address
478 * rather than the host address. Thus a socket can be
479 * bound to the loopback address and the connect will
480 * fail with EADDRNOTAVAIL. In addition the Linux kernel
481 * returns the wrong error in this case - it returns EINVAL
482 * instead of EADDRNOTAVAIL. We handle this here so that
483 * a more descriptive exception text is used.
484 */
485 if (connect_rv == -1 && errno == EINVAL) {
486 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
487 "Invalid argument or cannot assign requested address");
488 return;
489 }
490 #endif
491 #if defined(EPROTO)
492 if (errno == EPROTO) {
493 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ProtocolException",
494 "Protocol error");
495 return;
496 }
497 #endif
498 if (errno == ECONNREFUSED) {
499 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
500 "Connection refused");
501 } else if (errno == ETIMEDOUT) {
502 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
503 "Connection timed out");
504 } else if (errno == EHOSTUNREACH) {
505 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException",
506 "Host unreachable");
507 } else if (errno == EADDRNOTAVAIL) {
508 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException",
509 "Address not available");
510 } else if ((errno == EISCONN) || (errno == EBADF)) {
511 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
512 "Socket closed");
513 } else {
514 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "connect failed");
515 }
516 return;
517 }
518
519 (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
520
521 /* set the remote peer address and port */
522 (*env)->SetObjectField(env, this, psi_addressID, iaObj);
523 (*env)->SetIntField(env, this, psi_portID, port);
524
525 /*
526 * we need to initialize the local port field if bind was called
527 * previously to the connect (by the client) then localport field
528 * will already be initialized
529 */
530 if (localport == 0) {
531 /* Now that we're a connected socket, let's extract the port number
532 * that the system chose for us and store it in the Socket object.
533 */
534 socklen_t slen = SOCKADDR_LEN;
535 if (getsockname(fd, (struct sockaddr *)&him, &slen) == -1) {
536 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
537 "Error getting socket name");
538 } else {
539 localport = NET_GetPortFromSockaddr((struct sockaddr *)&him);
540 (*env)->SetIntField(env, this, psi_localportID, localport);
541 }
542 }
543 }
544
545 /*
546 * Class: java_net_PlainSocketImpl
547 * Method: socketBind
548 * Signature: (Ljava/net/InetAddress;I)V
549 */
550 JNIEXPORT void JNICALL
551 Java_java_net_PlainSocketImpl_socketBind(JNIEnv *env, jobject this,
552 jobject iaObj, jint localport) {
553
554 /* fdObj is the FileDescriptor field on this */
555 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
576 }
577 setDefaultScopeID(env, (struct sockaddr *)&him);
578
579 if (NET_Bind(fd, (struct sockaddr *)&him, len) < 0) {
580 if (errno == EADDRINUSE || errno == EADDRNOTAVAIL ||
581 errno == EPERM || errno == EACCES) {
582 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "BindException",
583 "Bind failed");
584 } else {
585 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
586 "Bind failed");
587 }
588 return;
589 }
590
591 /* set the address */
592 (*env)->SetObjectField(env, this, psi_addressID, iaObj);
593
594 /* initialize the local port */
595 if (localport == 0) {
596 socklen_t slen = sizeof(him);
597 /* Now that we're a connected socket, let's extract the port number
598 * that the system chose for us and store it in the Socket object.
599 */
600 if (getsockname(fd, (struct sockaddr *)&him, &slen) == -1) {
601 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
602 "Error getting socket name");
603 return;
604 }
605 localport = NET_GetPortFromSockaddr((struct sockaddr *)&him);
606 (*env)->SetIntField(env, this, psi_localportID, localport);
607 } else {
608 (*env)->SetIntField(env, this, psi_localportID, localport);
609 }
610 }
611
612 /*
613 * Class: java_net_PlainSocketImpl
614 * Method: socketListen
615 * Signature: (I)V
616 */
617 JNIEXPORT void JNICALL
618 Java_java_net_PlainSocketImpl_socketListen (JNIEnv *env, jobject this,
619 jint count)
620 {
621 /* this FileDescriptor fd field */
622 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
623 /* fdObj's int fd field */
624 int fd;
625
626 if (IS_NULL(fdObj)) {
627 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
628 "Socket closed");
629 return;
630 } else {
631 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
632 }
633
634 /*
635 * Workaround for bugid 4101691 in Solaris 2.6. See 4106600.
636 * If listen backlog is Integer.MAX_VALUE then subtract 1.
637 */
638 if (count == 0x7fffffff)
639 count -= 1;
640
641 if (listen(fd, count) == -1) {
642 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
643 "Listen failed");
644 }
645 }
646
647 /*
648 * Class: java_net_PlainSocketImpl
649 * Method: socketAccept
650 * Signature: (Ljava/net/SocketImpl;)V
651 */
652 JNIEXPORT void JNICALL
653 Java_java_net_PlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
654 jobject socket)
655 {
656 /* fields on this */
657 int port;
658 jint timeout = (*env)->GetIntField(env, this, psi_timeoutID);
659 jlong prevTime = 0;
660 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
661
662 /* the FileDescriptor field on socket */
663 jobject socketFdObj;
664 /* the InetAddress field on socket */
665 jobject socketAddressObj;
666
667 /* the ServerSocket fd int field on fdObj */
668 jint fd;
669
670 /* accepted fd */
671 jint newfd;
672
673 SOCKADDR him;
674 socklen_t slen = SOCKADDR_LEN;
675
676 if (IS_NULL(fdObj)) {
677 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
678 "Socket closed");
679 return;
680 } else {
681 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
682 }
683 if (IS_NULL(socket)) {
684 JNU_ThrowNullPointerException(env, "socket is null");
685 return;
686 }
687
688 /*
689 * accept connection but ignore ECONNABORTED indicating that
690 * connection was eagerly accepted by the OS but was reset
691 * before accept() was called.
692 *
693 * If accept timeout in place and timeout is adjusted with
694 * each ECONNABORTED or EWOULDBLOCK to ensure that semantics
697 for (;;) {
698 int ret;
699
700 /* first usage pick up current time */
701 if (prevTime == 0 && timeout > 0) {
702 prevTime = JVM_CurrentTimeMillis(env, 0);
703 }
704
705 /* passing a timeout of 0 to poll will return immediately,
706 but in the case of ServerSocket 0 means infinite. */
707 if (timeout <= 0) {
708 ret = NET_Timeout(fd, -1);
709 } else {
710 ret = NET_Timeout(fd, timeout);
711 }
712
713 if (ret == 0) {
714 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
715 "Accept timed out");
716 return;
717 } else if (ret == -1) {
718 if (errno == EBADF) {
719 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
720 } else {
721 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Accept failed");
722 }
723 return;
724 }
725
726 newfd = NET_Accept(fd, (struct sockaddr *)&him, &slen);
727
728 /* connection accepted */
729 if (newfd >= 0) {
730 SET_BLOCKING(newfd);
731 break;
732 }
733
734 /* non (ECONNABORTED or EWOULDBLOCK) error */
735 if (!(errno == ECONNABORTED || errno == EWOULDBLOCK)) {
736 break;
737 }
738
739 /* ECONNABORTED or EWOULDBLOCK error so adjust timeout if there is one. */
740 if (timeout) {
741 jlong currTime = JVM_CurrentTimeMillis(env, 0);
742 timeout -= (currTime - prevTime);
743
744 if (timeout <= 0) {
745 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
746 "Accept timed out");
793
794 /*
795 * Class: java_net_PlainSocketImpl
796 * Method: socketAvailable
797 * Signature: ()I
798 */
799 JNIEXPORT jint JNICALL
800 Java_java_net_PlainSocketImpl_socketAvailable(JNIEnv *env, jobject this) {
801
802 jint ret = -1;
803 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
804 jint fd;
805
806 if (IS_NULL(fdObj)) {
807 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
808 "Socket closed");
809 return -1;
810 } else {
811 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
812 }
813 /* NET_SocketAvailable returns 0 for failure, 1 for success */
814 if (NET_SocketAvailable(fd, &ret) == 0){
815 if (errno == ECONNRESET) {
816 JNU_ThrowByName(env, "sun/net/ConnectionResetException", "");
817 } else {
818 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
819 "ioctl FIONREAD failed");
820 }
821 }
822 return ret;
823 }
824
825 /*
826 * Class: java_net_PlainSocketImpl
827 * Method: socketClose0
828 * Signature: (Z)V
829 */
830 JNIEXPORT void JNICALL
831 Java_java_net_PlainSocketImpl_socketClose0(JNIEnv *env, jobject this,
832 jboolean useDeferredClose) {
833
834 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
858 */
859 JNIEXPORT void JNICALL
860 Java_java_net_PlainSocketImpl_socketShutdown(JNIEnv *env, jobject this,
861 jint howto)
862 {
863
864 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
865 jint fd;
866
867 /*
868 * WARNING: THIS NEEDS LOCKING. ALSO: SHOULD WE CHECK for fd being
869 * -1 already?
870 */
871 if (IS_NULL(fdObj)) {
872 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
873 "socket already closed");
874 return;
875 } else {
876 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
877 }
878 shutdown(fd, howto);
879 }
880
881
882 /*
883 * Class: java_net_PlainSocketImpl
884 * Method: socketSetOption
885 * Signature: (IZLjava/lang/Object;)V
886 */
887 JNIEXPORT void JNICALL
888 Java_java_net_PlainSocketImpl_socketSetOption(JNIEnv *env, jobject this,
889 jint cmd, jboolean on,
890 jobject value) {
891 int fd;
892 int level, optname, optlen;
893 union {
894 int i;
895 struct linger ling;
896 } optval;
897
898 /*
1078 jint data) {
1079 /* The fd field */
1080 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
1081 int n, fd;
1082 unsigned char d = data & 0xFF;
1083
1084 if (IS_NULL(fdObj)) {
1085 JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
1086 return;
1087 } else {
1088 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
1089 /* Bug 4086704 - If the Socket associated with this file descriptor
1090 * was closed (sysCloseFD), the the file descriptor is set to -1.
1091 */
1092 if (fd == -1) {
1093 JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
1094 return;
1095 }
1096
1097 }
1098 n = NET_Send(fd, (char *)&d, 1, MSG_OOB);
1099 if (n == -1) {
1100 NET_ThrowByNameWithLastError(env, "java/io/IOException", "Write failed");
1101 }
1102 }
|