1 /*
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
341 }
342 }
343 #endif
344 } else {
345 /*
346 * A timeout was specified. We put the socket into non-blocking
347 * mode, connect, and then wait for the connection to be
348 * established, fail, or timeout.
349 */
350 SET_NONBLOCKING(fd);
351
352 /* no need to use NET_Connect as non-blocking */
353 connect_rv = connect(fd, (struct sockaddr *)&him, len);
354
355 /* connection not established immediately */
356 if (connect_rv != 0) {
357 socklen_t optlen;
358 jlong prevTime = JVM_CurrentTimeMillis(env, 0);
359
360 if (errno != EINPROGRESS) {
361 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
362 "connect failed");
363 SET_BLOCKING(fd);
364 return;
365 }
366
367 /*
368 * Wait for the connection to be established or a
369 * timeout occurs. poll needs to handle EINTR in
370 * case lwp sig handler redirects any process signals to
371 * this thread.
372 */
373 while (1) {
374 jlong newTime;
375 struct pollfd pfd;
376 pfd.fd = fd;
377 pfd.events = POLLOUT;
378
379 errno = 0;
380 connect_rv = NET_Poll(&pfd, 1, timeout);
381
382 if (connect_rv >= 0) {
438
439 #ifdef __linux__
440 /*
441 * Linux/GNU distribution setup /etc/hosts so that
442 * InetAddress.getLocalHost gets back the loopback address
443 * rather than the host address. Thus a socket can be
444 * bound to the loopback address and the connect will
445 * fail with EADDRNOTAVAIL. In addition the Linux kernel
446 * returns the wrong error in this case - it returns EINVAL
447 * instead of EADDRNOTAVAIL. We handle this here so that
448 * a more descriptive exception text is used.
449 */
450 if (connect_rv == -1 && errno == EINVAL) {
451 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
452 "Invalid argument or cannot assign requested address");
453 return;
454 }
455 #endif
456 #if defined(EPROTO)
457 if (errno == EPROTO) {
458 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ProtocolException",
459 "Protocol error");
460 return;
461 }
462 #endif
463 if (errno == ECONNREFUSED) {
464 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
465 "Connection refused");
466 } else if (errno == ETIMEDOUT) {
467 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
468 "Connection timed out");
469 } else if (errno == EHOSTUNREACH) {
470 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException",
471 "Host unreachable");
472 } else if (errno == EADDRNOTAVAIL) {
473 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException",
474 "Address not available");
475 } else if ((errno == EISCONN) || (errno == EBADF)) {
476 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
477 "Socket closed");
478 } else {
479 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "connect failed");
480 }
481 return;
482 }
483
484 (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
485
486 /* set the remote peer address and port */
487 (*env)->SetObjectField(env, this, psi_addressID, iaObj);
488 (*env)->SetIntField(env, this, psi_portID, port);
489
490 /*
491 * we need to initialize the local port field if bind was called
492 * previously to the connect (by the client) then localport field
493 * will already be initialized
494 */
495 if (localport == 0) {
496 /* Now that we're a connected socket, let's extract the port number
497 * that the system chose for us and store it in the Socket object.
498 */
499 socklen_t slen = SOCKADDR_LEN;
500 if (getsockname(fd, (struct sockaddr *)&him, &slen) == -1) {
501 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
502 "Error getting socket name");
503 } else {
504 localport = NET_GetPortFromSockaddr((struct sockaddr *)&him);
505 (*env)->SetIntField(env, this, psi_localportID, localport);
506 }
507 }
508 }
509
510 /*
511 * Class: java_net_PlainSocketImpl
512 * Method: socketBind
513 * Signature: (Ljava/net/InetAddress;I)V
514 */
515 JNIEXPORT void JNICALL
516 Java_java_net_PlainSocketImpl_socketBind(JNIEnv *env, jobject this,
517 jobject iaObj, jint localport) {
518
519 /* fdObj is the FileDescriptor field on this */
520 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
521 /* fd is an int field on fdObj */
522 int fd;
523 int len;
524 SOCKADDR him;
525
526 if (IS_NULL(fdObj)) {
527 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
528 "Socket closed");
529 return;
530 } else {
531 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
532 }
533 if (IS_NULL(iaObj)) {
534 JNU_ThrowNullPointerException(env, "iaObj is null.");
535 return;
536 }
537
538 /* bind */
539 if (NET_InetAddressToSockaddr(env, iaObj, localport, (struct sockaddr *)&him, &len, JNI_TRUE) != 0) {
540 return;
541 }
542 setDefaultScopeID(env, (struct sockaddr *)&him);
543
544 if (NET_Bind(fd, (struct sockaddr *)&him, len) < 0) {
545 if (errno == EADDRINUSE || errno == EADDRNOTAVAIL ||
546 errno == EPERM || errno == EACCES) {
547 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "BindException",
548 "Bind failed");
549 } else {
550 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
551 "Bind failed");
552 }
553 return;
554 }
555
556 /* set the address */
557 (*env)->SetObjectField(env, this, psi_addressID, iaObj);
558
559 /* initialize the local port */
560 if (localport == 0) {
561 socklen_t slen = sizeof(him);
562 /* Now that we're a connected socket, let's extract the port number
563 * that the system chose for us and store it in the Socket object.
564 */
565 if (getsockname(fd, (struct sockaddr *)&him, &slen) == -1) {
566 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
567 "Error getting socket name");
568 return;
569 }
570 localport = NET_GetPortFromSockaddr((struct sockaddr *)&him);
571 (*env)->SetIntField(env, this, psi_localportID, localport);
572 } else {
573 (*env)->SetIntField(env, this, psi_localportID, localport);
574 }
575 }
576
577 /*
578 * Class: java_net_PlainSocketImpl
579 * Method: socketListen
580 * Signature: (I)V
581 */
582 JNIEXPORT void JNICALL
583 Java_java_net_PlainSocketImpl_socketListen (JNIEnv *env, jobject this,
584 jint count)
585 {
586 /* this FileDescriptor fd field */
587 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
588 /* fdObj's int fd field */
589 int fd;
590
591 if (IS_NULL(fdObj)) {
592 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
593 "Socket closed");
594 return;
595 } else {
596 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
597 }
598
599 /*
600 * Workaround for bugid 4101691 in Solaris 2.6. See 4106600.
601 * If listen backlog is Integer.MAX_VALUE then subtract 1.
602 */
603 if (count == 0x7fffffff)
604 count -= 1;
605
606 if (listen(fd, count) == -1) {
607 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
608 "Listen failed");
609 }
610 }
611
612 /*
613 * Class: java_net_PlainSocketImpl
614 * Method: socketAccept
615 * Signature: (Ljava/net/SocketImpl;)V
616 */
617 JNIEXPORT void JNICALL
618 Java_java_net_PlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
619 jobject socket)
620 {
621 /* fields on this */
622 int port;
623 jint timeout = (*env)->GetIntField(env, this, psi_timeoutID);
624 jlong prevTime = 0;
625 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
626
627 /* the FileDescriptor field on socket */
628 jobject socketFdObj;
667 prevTime = JVM_CurrentTimeMillis(env, 0);
668 }
669
670 /* passing a timeout of 0 to poll will return immediately,
671 but in the case of ServerSocket 0 means infinite. */
672 if (timeout <= 0) {
673 ret = NET_Timeout(fd, -1);
674 } else {
675 ret = NET_Timeout(fd, timeout);
676 }
677 if (ret == 0) {
678 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
679 "Accept timed out");
680 return;
681 } else if (ret == -1) {
682 if (errno == EBADF) {
683 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
684 } else if (errno == ENOMEM) {
685 JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
686 } else {
687 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Accept failed");
688 }
689 return;
690 }
691
692 newfd = NET_Accept(fd, (struct sockaddr *)&him, &slen);
693
694 /* connection accepted */
695 if (newfd >= 0) {
696 SET_BLOCKING(newfd);
697 break;
698 }
699
700 /* non (ECONNABORTED or EWOULDBLOCK) error */
701 if (!(errno == ECONNABORTED || errno == EWOULDBLOCK)) {
702 break;
703 }
704
705 /* ECONNABORTED or EWOULDBLOCK error so adjust timeout if there is one. */
706 if (timeout) {
707 jlong currTime = JVM_CurrentTimeMillis(env, 0);
710 if (timeout <= 0) {
711 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
712 "Accept timed out");
713 return;
714 }
715 prevTime = currTime;
716 }
717 }
718
719 if (newfd < 0) {
720 if (newfd == -2) {
721 JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
722 "operation interrupted");
723 } else {
724 if (errno == EINVAL) {
725 errno = EBADF;
726 }
727 if (errno == EBADF) {
728 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
729 } else {
730 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Accept failed");
731 }
732 }
733 return;
734 }
735
736 /*
737 * fill up the remote peer port and address in the new socket structure.
738 */
739 socketAddressObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
740 if (socketAddressObj == NULL) {
741 /* should be pending exception */
742 close(newfd);
743 return;
744 }
745
746 /*
747 * Populate SocketImpl.fd.fd
748 */
749 socketFdObj = (*env)->GetObjectField(env, socket, psi_fdID);
750 (*env)->SetIntField(env, socketFdObj, IO_fd_fdID, newfd);
764 */
765 JNIEXPORT jint JNICALL
766 Java_java_net_PlainSocketImpl_socketAvailable(JNIEnv *env, jobject this) {
767
768 jint ret = -1;
769 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
770 jint fd;
771
772 if (IS_NULL(fdObj)) {
773 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
774 "Socket closed");
775 return -1;
776 } else {
777 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
778 }
779 /* NET_SocketAvailable returns 0 for failure, 1 for success */
780 if (NET_SocketAvailable(fd, &ret) == 0){
781 if (errno == ECONNRESET) {
782 JNU_ThrowByName(env, "sun/net/ConnectionResetException", "");
783 } else {
784 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
785 "ioctl FIONREAD failed");
786 }
787 }
788 return ret;
789 }
790
791 /*
792 * Class: java_net_PlainSocketImpl
793 * Method: socketClose0
794 * Signature: (Z)V
795 */
796 JNIEXPORT void JNICALL
797 Java_java_net_PlainSocketImpl_socketClose0(JNIEnv *env, jobject this,
798 jboolean useDeferredClose) {
799
800 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
801 jint fd;
802
803 if (IS_NULL(fdObj)) {
804 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
805 "socket already closed");
919 }
920
921 /* Boolean -> int */
922 default :
923 optval.i = (on ? 1 : 0);
924 optlen = sizeof(optval.i);
925
926 }
927
928 if (NET_SetSockOpt(fd, level, optname, (const void *)&optval, optlen) < 0) {
929 #if defined(__solaris__) || defined(_AIX)
930 if (errno == EINVAL) {
931 // On Solaris setsockopt will set errno to EINVAL if the socket
932 // is closed. The default error message is then confusing
933 char fullMsg[128];
934 jio_snprintf(fullMsg, sizeof(fullMsg), "Invalid option or socket reset by remote peer");
935 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg);
936 return;
937 }
938 #endif /* __solaris__ */
939 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
940 "Error setting socket option");
941 }
942 }
943
944 /*
945 * Class: java_net_PlainSocketImpl
946 * Method: socketGetOption
947 * Signature: (I)I
948 */
949 JNIEXPORT jint JNICALL
950 Java_java_net_PlainSocketImpl_socketGetOption(JNIEnv *env, jobject this,
951 jint cmd, jobject iaContainerObj) {
952
953 int fd;
954 int level, optname, optlen;
955 union {
956 int i;
957 struct linger ling;
958 } optval;
959
960 /*
964 if (fd < 0) {
965 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
966 "Socket closed");
967 return -1;
968 }
969
970 /*
971 * SO_BINDADDR isn't a socket option
972 */
973 if (cmd == java_net_SocketOptions_SO_BINDADDR) {
974 SOCKADDR him;
975 socklen_t len = 0;
976 int port;
977 jobject iaObj;
978 jclass iaCntrClass;
979 jfieldID iaFieldID;
980
981 len = SOCKADDR_LEN;
982
983 if (getsockname(fd, (struct sockaddr *)&him, &len) < 0) {
984 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
985 "Error getting socket name");
986 return -1;
987 }
988 iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
989 CHECK_NULL_RETURN(iaObj, -1);
990
991 iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj);
992 iaFieldID = (*env)->GetFieldID(env, iaCntrClass, "addr", "Ljava/net/InetAddress;");
993 CHECK_NULL_RETURN(iaFieldID, -1);
994 (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
995 return 0; /* notice change from before */
996 }
997
998 /*
999 * Map the Java level socket option to the platform specific
1000 * level and option name.
1001 */
1002 if (NET_MapSocketOption(cmd, &level, &optname)) {
1003 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
1004 return -1;
1005 }
1006
1007 /*
1008 * Args are int except for SO_LINGER
1009 */
1010 if (cmd == java_net_SocketOptions_SO_LINGER) {
1011 optlen = sizeof(optval.ling);
1012 } else {
1013 optlen = sizeof(optval.i);
1014 }
1015
1016 if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) {
1017 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
1018 "Error getting socket option");
1019 return -1;
1020 }
1021
1022 switch (cmd) {
1023 case java_net_SocketOptions_SO_LINGER:
1024 return (optval.ling.l_onoff ? optval.ling.l_linger: -1);
1025
1026 case java_net_SocketOptions_SO_SNDBUF:
1027 case java_net_SocketOptions_SO_RCVBUF:
1028 case java_net_SocketOptions_IP_TOS:
1029 return optval.i;
1030
1031 default :
1032 return (optval.i == 0) ? -1 : 1;
1033 }
1034 }
1035
1036
1037 /*
1038 * Class: java_net_PlainSocketImpl
1046 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
1047 int n, fd;
1048 unsigned char d = data & 0xFF;
1049
1050 if (IS_NULL(fdObj)) {
1051 JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
1052 return;
1053 } else {
1054 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
1055 /* Bug 4086704 - If the Socket associated with this file descriptor
1056 * was closed (sysCloseFD), the file descriptor is set to -1.
1057 */
1058 if (fd == -1) {
1059 JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
1060 return;
1061 }
1062
1063 }
1064 n = NET_Send(fd, (char *)&d, 1, MSG_OOB);
1065 if (n == -1) {
1066 NET_ThrowByNameWithLastError(env, "java/io/IOException", "Write failed");
1067 }
1068 }
|
1 /*
2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
341 }
342 }
343 #endif
344 } else {
345 /*
346 * A timeout was specified. We put the socket into non-blocking
347 * mode, connect, and then wait for the connection to be
348 * established, fail, or timeout.
349 */
350 SET_NONBLOCKING(fd);
351
352 /* no need to use NET_Connect as non-blocking */
353 connect_rv = connect(fd, (struct sockaddr *)&him, len);
354
355 /* connection not established immediately */
356 if (connect_rv != 0) {
357 socklen_t optlen;
358 jlong prevTime = JVM_CurrentTimeMillis(env, 0);
359
360 if (errno != EINPROGRESS) {
361 JNU_ThrowByNameWithLastError
362 (env, JNU_JAVANETPKG "ConnectException", "connect failed");
363 SET_BLOCKING(fd);
364 return;
365 }
366
367 /*
368 * Wait for the connection to be established or a
369 * timeout occurs. poll needs to handle EINTR in
370 * case lwp sig handler redirects any process signals to
371 * this thread.
372 */
373 while (1) {
374 jlong newTime;
375 struct pollfd pfd;
376 pfd.fd = fd;
377 pfd.events = POLLOUT;
378
379 errno = 0;
380 connect_rv = NET_Poll(&pfd, 1, timeout);
381
382 if (connect_rv >= 0) {
438
439 #ifdef __linux__
440 /*
441 * Linux/GNU distribution setup /etc/hosts so that
442 * InetAddress.getLocalHost gets back the loopback address
443 * rather than the host address. Thus a socket can be
444 * bound to the loopback address and the connect will
445 * fail with EADDRNOTAVAIL. In addition the Linux kernel
446 * returns the wrong error in this case - it returns EINVAL
447 * instead of EADDRNOTAVAIL. We handle this here so that
448 * a more descriptive exception text is used.
449 */
450 if (connect_rv == -1 && errno == EINVAL) {
451 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
452 "Invalid argument or cannot assign requested address");
453 return;
454 }
455 #endif
456 #if defined(EPROTO)
457 if (errno == EPROTO) {
458 JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ProtocolException",
459 "Protocol error");
460 return;
461 }
462 #endif
463 if (errno == ECONNREFUSED) {
464 JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
465 "Connection refused");
466 } else if (errno == ETIMEDOUT) {
467 JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
468 "Connection timed out");
469 } else if (errno == EHOSTUNREACH) {
470 JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException",
471 "Host unreachable");
472 } else if (errno == EADDRNOTAVAIL) {
473 JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException",
474 "Address not available");
475 } else if ((errno == EISCONN) || (errno == EBADF)) {
476 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
477 "Socket closed");
478 } else {
479 JNU_ThrowByNameWithMessageAndLastError
480 (env, JNU_JAVANETPKG "SocketException", "connect failed");
481 }
482 return;
483 }
484
485 (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
486
487 /* set the remote peer address and port */
488 (*env)->SetObjectField(env, this, psi_addressID, iaObj);
489 (*env)->SetIntField(env, this, psi_portID, port);
490
491 /*
492 * we need to initialize the local port field if bind was called
493 * previously to the connect (by the client) then localport field
494 * will already be initialized
495 */
496 if (localport == 0) {
497 /* Now that we're a connected socket, let's extract the port number
498 * that the system chose for us and store it in the Socket object.
499 */
500 socklen_t slen = SOCKADDR_LEN;
501 if (getsockname(fd, (struct sockaddr *)&him, &slen) == -1) {
502 JNU_ThrowByNameWithMessageAndLastError
503 (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
504 } else {
505 localport = NET_GetPortFromSockaddr((struct sockaddr *)&him);
506 (*env)->SetIntField(env, this, psi_localportID, localport);
507 }
508 }
509 }
510
511 /*
512 * Class: java_net_PlainSocketImpl
513 * Method: socketBind
514 * Signature: (Ljava/net/InetAddress;I)V
515 */
516 JNIEXPORT void JNICALL
517 Java_java_net_PlainSocketImpl_socketBind(JNIEnv *env, jobject this,
518 jobject iaObj, jint localport) {
519
520 /* fdObj is the FileDescriptor field on this */
521 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
522 /* fd is an int field on fdObj */
523 int fd;
524 int len;
525 SOCKADDR him;
526
527 if (IS_NULL(fdObj)) {
528 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
529 "Socket closed");
530 return;
531 } else {
532 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
533 }
534 if (IS_NULL(iaObj)) {
535 JNU_ThrowNullPointerException(env, "iaObj is null.");
536 return;
537 }
538
539 /* bind */
540 if (NET_InetAddressToSockaddr(env, iaObj, localport, (struct sockaddr *)&him,
541 &len, JNI_TRUE) != 0) {
542 return;
543 }
544 setDefaultScopeID(env, (struct sockaddr *)&him);
545
546 if (NET_Bind(fd, (struct sockaddr *)&him, len) < 0) {
547 if (errno == EADDRINUSE || errno == EADDRNOTAVAIL ||
548 errno == EPERM || errno == EACCES) {
549 JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "BindException",
550 "Bind failed");
551 } else {
552 JNU_ThrowByNameWithMessageAndLastError
553 (env, JNU_JAVANETPKG "SocketException", "Bind failed");
554 }
555 return;
556 }
557
558 /* set the address */
559 (*env)->SetObjectField(env, this, psi_addressID, iaObj);
560
561 /* initialize the local port */
562 if (localport == 0) {
563 socklen_t slen = sizeof(him);
564 /* Now that we're a connected socket, let's extract the port number
565 * that the system chose for us and store it in the Socket object.
566 */
567 if (getsockname(fd, (struct sockaddr *)&him, &slen) == -1) {
568 JNU_ThrowByNameWithMessageAndLastError
569 (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
570 return;
571 }
572 localport = NET_GetPortFromSockaddr((struct sockaddr *)&him);
573 (*env)->SetIntField(env, this, psi_localportID, localport);
574 } else {
575 (*env)->SetIntField(env, this, psi_localportID, localport);
576 }
577 }
578
579 /*
580 * Class: java_net_PlainSocketImpl
581 * Method: socketListen
582 * Signature: (I)V
583 */
584 JNIEXPORT void JNICALL
585 Java_java_net_PlainSocketImpl_socketListen(JNIEnv *env, jobject this,
586 jint count)
587 {
588 /* this FileDescriptor fd field */
589 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
590 /* fdObj's int fd field */
591 int fd;
592
593 if (IS_NULL(fdObj)) {
594 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
595 "Socket closed");
596 return;
597 } else {
598 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
599 }
600
601 /*
602 * Workaround for bugid 4101691 in Solaris 2.6. See 4106600.
603 * If listen backlog is Integer.MAX_VALUE then subtract 1.
604 */
605 if (count == 0x7fffffff)
606 count -= 1;
607
608 if (listen(fd, count) == -1) {
609 JNU_ThrowByNameWithMessageAndLastError
610 (env, JNU_JAVANETPKG "SocketException", "Listen failed");
611 }
612 }
613
614 /*
615 * Class: java_net_PlainSocketImpl
616 * Method: socketAccept
617 * Signature: (Ljava/net/SocketImpl;)V
618 */
619 JNIEXPORT void JNICALL
620 Java_java_net_PlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
621 jobject socket)
622 {
623 /* fields on this */
624 int port;
625 jint timeout = (*env)->GetIntField(env, this, psi_timeoutID);
626 jlong prevTime = 0;
627 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
628
629 /* the FileDescriptor field on socket */
630 jobject socketFdObj;
669 prevTime = JVM_CurrentTimeMillis(env, 0);
670 }
671
672 /* passing a timeout of 0 to poll will return immediately,
673 but in the case of ServerSocket 0 means infinite. */
674 if (timeout <= 0) {
675 ret = NET_Timeout(fd, -1);
676 } else {
677 ret = NET_Timeout(fd, timeout);
678 }
679 if (ret == 0) {
680 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
681 "Accept timed out");
682 return;
683 } else if (ret == -1) {
684 if (errno == EBADF) {
685 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
686 } else if (errno == ENOMEM) {
687 JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
688 } else {
689 JNU_ThrowByNameWithMessageAndLastError
690 (env, JNU_JAVANETPKG "SocketException", "Accept failed");
691 }
692 return;
693 }
694
695 newfd = NET_Accept(fd, (struct sockaddr *)&him, &slen);
696
697 /* connection accepted */
698 if (newfd >= 0) {
699 SET_BLOCKING(newfd);
700 break;
701 }
702
703 /* non (ECONNABORTED or EWOULDBLOCK) error */
704 if (!(errno == ECONNABORTED || errno == EWOULDBLOCK)) {
705 break;
706 }
707
708 /* ECONNABORTED or EWOULDBLOCK error so adjust timeout if there is one. */
709 if (timeout) {
710 jlong currTime = JVM_CurrentTimeMillis(env, 0);
713 if (timeout <= 0) {
714 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
715 "Accept timed out");
716 return;
717 }
718 prevTime = currTime;
719 }
720 }
721
722 if (newfd < 0) {
723 if (newfd == -2) {
724 JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
725 "operation interrupted");
726 } else {
727 if (errno == EINVAL) {
728 errno = EBADF;
729 }
730 if (errno == EBADF) {
731 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
732 } else {
733 JNU_ThrowByNameWithMessageAndLastError
734 (env, JNU_JAVANETPKG "SocketException", "Accept failed");
735 }
736 }
737 return;
738 }
739
740 /*
741 * fill up the remote peer port and address in the new socket structure.
742 */
743 socketAddressObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
744 if (socketAddressObj == NULL) {
745 /* should be pending exception */
746 close(newfd);
747 return;
748 }
749
750 /*
751 * Populate SocketImpl.fd.fd
752 */
753 socketFdObj = (*env)->GetObjectField(env, socket, psi_fdID);
754 (*env)->SetIntField(env, socketFdObj, IO_fd_fdID, newfd);
768 */
769 JNIEXPORT jint JNICALL
770 Java_java_net_PlainSocketImpl_socketAvailable(JNIEnv *env, jobject this) {
771
772 jint ret = -1;
773 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
774 jint fd;
775
776 if (IS_NULL(fdObj)) {
777 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
778 "Socket closed");
779 return -1;
780 } else {
781 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
782 }
783 /* NET_SocketAvailable returns 0 for failure, 1 for success */
784 if (NET_SocketAvailable(fd, &ret) == 0){
785 if (errno == ECONNRESET) {
786 JNU_ThrowByName(env, "sun/net/ConnectionResetException", "");
787 } else {
788 JNU_ThrowByNameWithMessageAndLastError
789 (env, JNU_JAVANETPKG "SocketException", "ioctl FIONREAD failed");
790 }
791 }
792 return ret;
793 }
794
795 /*
796 * Class: java_net_PlainSocketImpl
797 * Method: socketClose0
798 * Signature: (Z)V
799 */
800 JNIEXPORT void JNICALL
801 Java_java_net_PlainSocketImpl_socketClose0(JNIEnv *env, jobject this,
802 jboolean useDeferredClose) {
803
804 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
805 jint fd;
806
807 if (IS_NULL(fdObj)) {
808 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
809 "socket already closed");
923 }
924
925 /* Boolean -> int */
926 default :
927 optval.i = (on ? 1 : 0);
928 optlen = sizeof(optval.i);
929
930 }
931
932 if (NET_SetSockOpt(fd, level, optname, (const void *)&optval, optlen) < 0) {
933 #if defined(__solaris__) || defined(_AIX)
934 if (errno == EINVAL) {
935 // On Solaris setsockopt will set errno to EINVAL if the socket
936 // is closed. The default error message is then confusing
937 char fullMsg[128];
938 jio_snprintf(fullMsg, sizeof(fullMsg), "Invalid option or socket reset by remote peer");
939 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg);
940 return;
941 }
942 #endif /* __solaris__ */
943 JNU_ThrowByNameWithMessageAndLastError
944 (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
945 }
946 }
947
948 /*
949 * Class: java_net_PlainSocketImpl
950 * Method: socketGetOption
951 * Signature: (I)I
952 */
953 JNIEXPORT jint JNICALL
954 Java_java_net_PlainSocketImpl_socketGetOption(JNIEnv *env, jobject this,
955 jint cmd, jobject iaContainerObj) {
956
957 int fd;
958 int level, optname, optlen;
959 union {
960 int i;
961 struct linger ling;
962 } optval;
963
964 /*
968 if (fd < 0) {
969 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
970 "Socket closed");
971 return -1;
972 }
973
974 /*
975 * SO_BINDADDR isn't a socket option
976 */
977 if (cmd == java_net_SocketOptions_SO_BINDADDR) {
978 SOCKADDR him;
979 socklen_t len = 0;
980 int port;
981 jobject iaObj;
982 jclass iaCntrClass;
983 jfieldID iaFieldID;
984
985 len = SOCKADDR_LEN;
986
987 if (getsockname(fd, (struct sockaddr *)&him, &len) < 0) {
988 JNU_ThrowByNameWithMessageAndLastError
989 (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
990 return -1;
991 }
992 iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
993 CHECK_NULL_RETURN(iaObj, -1);
994
995 iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj);
996 iaFieldID = (*env)->GetFieldID(env, iaCntrClass, "addr", "Ljava/net/InetAddress;");
997 CHECK_NULL_RETURN(iaFieldID, -1);
998 (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
999 return 0; /* notice change from before */
1000 }
1001
1002 /*
1003 * Map the Java level socket option to the platform specific
1004 * level and option name.
1005 */
1006 if (NET_MapSocketOption(cmd, &level, &optname)) {
1007 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
1008 return -1;
1009 }
1010
1011 /*
1012 * Args are int except for SO_LINGER
1013 */
1014 if (cmd == java_net_SocketOptions_SO_LINGER) {
1015 optlen = sizeof(optval.ling);
1016 } else {
1017 optlen = sizeof(optval.i);
1018 }
1019
1020 if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) {
1021 JNU_ThrowByNameWithMessageAndLastError
1022 (env, JNU_JAVANETPKG "SocketException", "Error getting socket option");
1023 return -1;
1024 }
1025
1026 switch (cmd) {
1027 case java_net_SocketOptions_SO_LINGER:
1028 return (optval.ling.l_onoff ? optval.ling.l_linger: -1);
1029
1030 case java_net_SocketOptions_SO_SNDBUF:
1031 case java_net_SocketOptions_SO_RCVBUF:
1032 case java_net_SocketOptions_IP_TOS:
1033 return optval.i;
1034
1035 default :
1036 return (optval.i == 0) ? -1 : 1;
1037 }
1038 }
1039
1040
1041 /*
1042 * Class: java_net_PlainSocketImpl
1050 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
1051 int n, fd;
1052 unsigned char d = data & 0xFF;
1053
1054 if (IS_NULL(fdObj)) {
1055 JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
1056 return;
1057 } else {
1058 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
1059 /* Bug 4086704 - If the Socket associated with this file descriptor
1060 * was closed (sysCloseFD), the file descriptor is set to -1.
1061 */
1062 if (fd == -1) {
1063 JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
1064 return;
1065 }
1066
1067 }
1068 n = NET_Send(fd, (char *)&d, 1, MSG_OOB);
1069 if (n == -1) {
1070 JNU_ThrowIOExceptionWithLastError(env, "Write failed");
1071 }
1072 }
|