src/solaris/native/java/net/PlainSocketImpl.c

Print this page




  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 }