< prev index next >

src/java.base/unix/native/libnet/PlainSocketImpl.c

Print this page
rev 14618 : 8158023: SocketExceptions contain too little information sometimes
   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 }
< prev index next >