/* * Class: java_net_DualStackPlainSocketImpl * Method: getIntOption * Signature: (II)I */ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_getIntOption (JNIEnv *env, jclass clazz, jint fd, jint cmd) { int level, opt; int result=0; struct linger linger; char *arg; int arglen; if (NET_MapSocketOption(cmd, &level, &opt) < 0) { JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Unsupported socket option"); return -1; } if (opt == java_net_SocketOptions_SO_LINGER) { arg = (char *)&linger; arglen = sizeof(linger); } else { arg = (char *)&result; arglen = sizeof(result); } if (NET_GetSockOpt(fd, level, opt, arg, &arglen) < 0) { NET_ThrowNew(env, WSAGetLastError(), "getsockopt"); return -1; } if (opt == java_net_SocketOptions_SO_LINGER) return linger.l_onoff ? linger.l_linger : -1; else return result; }
/* * Class: sun_nio_ch_sctp_SctpNet * Method: getIntOption0 * Signature: (II)I */ JNIEXPORT int JNICALL Java_sun_nio_ch_sctp_SctpNet_getIntOption0 (JNIEnv *env, jclass klass, jint fd, jint opt) { int klevel, kopt; int result; struct linger linger; void *arg; int arglen; memset((char *) &linger, 0, sizeof(linger)); if (mapSocketOption(opt, &klevel, &kopt) < 0) { JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Unsupported socket option"); return -1; } if (opt == sun_nio_ch_sctp_SctpStdSocketOption_SO_LINGER) { arg = (void *)&linger; arglen = sizeof(linger); } else { arg = (void *)&result; arglen = sizeof(result); } if (NET_GetSockOpt(fd, klevel, kopt, arg, &arglen) < 0) { JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "sun.nio.ch.Net.getIntOption"); return -1; } if (opt == sun_nio_ch_sctp_SctpStdSocketOption_SO_LINGER) return linger.l_onoff ? linger.l_linger : -1; else return result; }
JNIEXPORT jint JNICALL Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo, jboolean mayNeedConversion, jint level, jint opt) { int result; struct linger linger; u_char carg; void *arg; socklen_t arglen; int n; /* Option value is an int except for a few specific cases */ arg = (void *)&result; arglen = sizeof(result); if (level == IPPROTO_IP && (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) { arg = (void*)&carg; arglen = sizeof(carg); } if (level == SOL_SOCKET && opt == SO_LINGER) { arg = (void *)&linger; arglen = sizeof(linger); } if (mayNeedConversion) { n = NET_GetSockOpt(fdval(env, fdo), level, opt, arg, (int*)&arglen); } else { n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen); } if (n < 0) { JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "sun.nio.ch.Net.getIntOption"); return -1; } if (level == IPPROTO_IP && (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) { return (jint)carg; } if (level == SOL_SOCKET && opt == SO_LINGER) return linger.l_onoff ? (jint)linger.l_linger : (jint)-1; return (jint)result; }
/* * Class: java_net_DualStackPlainDatagramSocketImpl * Method: socketGetIntOption * Signature: (II)I */ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketGetIntOption (JNIEnv *env, jclass clazz, jint fd, jint cmd) { int level = 0, opt = 0, result=0; int result_len = sizeof(result); if (NET_MapSocketOption(cmd, &level, &opt) < 0) { JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Invalid option"); return -1; } if (NET_GetSockOpt(fd, level, opt, (void *)&result, &result_len) < 0) { NET_ThrowNew(env, WSAGetLastError(), "getsockopt"); return -1; } return result; }
JNIEXPORT jint JNICALL Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo, jboolean mayNeedConversion, jint level, jint opt) { int result = 0; struct linger linger; char *arg; int arglen, n; if (level == SOL_SOCKET && opt == SO_LINGER) { arg = (char *)&linger; arglen = sizeof(linger); } else { arg = (char *)&result; arglen = sizeof(result); } /** * HACK: IP_TOS is deprecated on Windows and querying the option * returns a protocol error. NET_GetSockOpt handles this and uses * a fallback mechanism. */ if (level == IPPROTO_IP && opt == IP_TOS) { mayNeedConversion = JNI_TRUE; } if (mayNeedConversion) { n = NET_GetSockOpt(fdval(env, fdo), level, opt, arg, &arglen); } else { n = getsockopt(fdval(env, fdo), level, opt, arg, &arglen); } if (n < 0) { handleSocketError(env, WSAGetLastError()); return IOS_THROWN; } if (level == SOL_SOCKET && opt == SO_LINGER) return linger.l_onoff ? linger.l_linger : -1; else return result; }
JNIEXPORT jint JNICALL Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo, jint opt) { int klevel, kopt; int result; struct linger linger; void *arg; int arglen; if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) { JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Unsupported socket option"); return -1; } if (opt == java_net_SocketOptions_SO_LINGER) { arg = (void *)&linger; arglen = sizeof(linger); } else { arg = (void *)&result; arglen = sizeof(result); } if (NET_GetSockOpt(fdval(env, fdo), klevel, kopt, arg, &arglen) < 0) { JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "sun.nio.ch.Net.getIntOption"); return -1; } if (opt == java_net_SocketOptions_SO_LINGER) return linger.l_onoff ? linger.l_linger : -1; else return result; }
/* * Class: java_net_DualStackPlainSocketImpl * Method: waitForConnect * Signature: (II)V */ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForConnect (JNIEnv *env, jclass clazz, jint fd, jint timeout) { int rv, retry; int optlen = sizeof(rv); fd_set wr, ex; struct timeval t; FD_ZERO(&wr); FD_ZERO(&ex); FD_SET(fd, &wr); FD_SET(fd, &ex); t.tv_sec = timeout / 1000; t.tv_usec = (timeout % 1000) * 1000; /* * Wait for timeout, connection established or * connection failed. */ rv = select(fd+1, 0, &wr, &ex, &t); /* * Timeout before connection is established/failed so * we throw exception and shutdown input/output to prevent * socket from being used. * The socket should be closed immediately by the caller. */ if (rv == 0) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", "connect timed out"); shutdown( fd, SD_BOTH ); return; } /* * Socket is writable or error occured. On some Windows editions * the socket will appear writable when the connect fails so we * check for error rather than writable. */ if (!FD_ISSET(fd, &ex)) { return; /* connection established */ } /* * Connection failed. The logic here is designed to work around * bug on Windows NT whereby using getsockopt to obtain the * last error (SO_ERROR) indicates there is no error. The workaround * on NT is to allow winsock to be scheduled and this is done by * yielding and retrying. As yielding is problematic in heavy * load conditions we attempt up to 3 times to get the error reason. */ for (retry=0; retry<3; retry++) { NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (char*)&rv, &optlen); if (rv) { break; } Sleep(0); } if (rv == 0) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Unable to establish connection"); } else { NET_ThrowNew(env, rv, "connect"); } }