src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c

Print this page
rev 14282 : 8044773: Refactor jdk.net API so that it can be moved out of the base module
Reviewed-by:

*** 21,302 **** * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ - #include <jni.h> - #include <string.h> ! #include "net_util.h" ! #include "jdk_net_SocketFlow.h" - static jclass sf_status_class; /* Status enum type */ - - static jfieldID sf_status; static jfieldID sf_priority; static jfieldID sf_bandwidth; ! static jfieldID sf_fd_fdID; /* FileDescriptor.fd */ ! ! /* References to the literal enum values */ ! ! static jobject sfs_NOSTATUS; ! static jobject sfs_OK; ! static jobject sfs_NOPERMISSION; ! static jobject sfs_NOTCONNECTED; ! static jobject sfs_NOTSUPPORTED; ! static jobject sfs_ALREADYCREATED; ! static jobject sfs_INPROGRESS; ! static jobject sfs_OTHER; ! ! static jobject getEnumField(JNIEnv *env, char *name); ! static void setStatus(JNIEnv *env, jobject obj, int errval); ! ! /* OS specific code is implemented in these three functions */ ! ! static jboolean flowSupported0() ; /* ! * Class: sun_net_ExtendedOptionsImpl * Method: init * Signature: ()V */ ! JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init ! (JNIEnv *env, jclass UNUSED) { ! static int initialized = 0; ! jclass c; ! ! /* Global class references */ ! ! if (initialized) { ! return; ! } ! ! c = (*env)->FindClass(env, "jdk/net/SocketFlow$Status"); CHECK_NULL(c); - sf_status_class = (*env)->NewGlobalRef(env, c); - CHECK_NULL(sf_status_class); - - /* int "fd" field of java.io.FileDescriptor */ - - c = (*env)->FindClass(env, "java/io/FileDescriptor"); - CHECK_NULL(c); - sf_fd_fdID = (*env)->GetFieldID(env, c, "fd", "I"); - CHECK_NULL(sf_fd_fdID); - - - /* SocketFlow fields */ - - c = (*env)->FindClass(env, "jdk/net/SocketFlow"); - CHECK_NULL(c); - - /* status */ - - sf_status = (*env)->GetFieldID(env, c, "status", - "Ljdk/net/SocketFlow$Status;"); - CHECK_NULL(sf_status); - - /* priority */ - sf_priority = (*env)->GetFieldID(env, c, "priority", "I"); CHECK_NULL(sf_priority); - - /* bandwidth */ - sf_bandwidth = (*env)->GetFieldID(env, c, "bandwidth", "J"); CHECK_NULL(sf_bandwidth); ! ! /* Initialize the static enum values */ ! ! sfs_NOSTATUS = getEnumField(env, "NO_STATUS"); ! CHECK_NULL(sfs_NOSTATUS); ! sfs_OK = getEnumField(env, "OK"); ! CHECK_NULL(sfs_OK); ! sfs_NOPERMISSION = getEnumField(env, "NO_PERMISSION"); ! CHECK_NULL(sfs_NOPERMISSION); ! sfs_NOTCONNECTED = getEnumField(env, "NOT_CONNECTED"); ! CHECK_NULL(sfs_NOTCONNECTED); ! sfs_NOTSUPPORTED = getEnumField(env, "NOT_SUPPORTED"); ! CHECK_NULL(sfs_NOTSUPPORTED); ! sfs_ALREADYCREATED = getEnumField(env, "ALREADY_CREATED"); ! CHECK_NULL(sfs_ALREADYCREATED); ! sfs_INPROGRESS = getEnumField(env, "IN_PROGRESS"); ! CHECK_NULL(sfs_INPROGRESS); ! sfs_OTHER = getEnumField(env, "OTHER"); ! CHECK_NULL(sfs_OTHER); ! initialized = JNI_TRUE; ! } ! ! static jobject getEnumField(JNIEnv *env, char *name) ! { ! jobject f; ! jfieldID fID = (*env)->GetStaticFieldID(env, sf_status_class, name, ! "Ljdk/net/SocketFlow$Status;"); ! CHECK_NULL_RETURN(fID, NULL); ! ! f = (*env)->GetStaticObjectField(env, sf_status_class, fID); ! CHECK_NULL_RETURN(f, NULL); ! f = (*env)->NewGlobalRef(env, f); ! CHECK_NULL_RETURN(f, NULL); ! return f; ! } ! ! /* ! * Retrieve the int file-descriptor from a public socket type object. ! * Gets impl, then the FileDescriptor from the impl, and then the fd ! * from that. ! */ ! static int getFD(JNIEnv *env, jobject fileDesc) { ! return (*env)->GetIntField(env, fileDesc, sf_fd_fdID); } ! /** ! * Sets the status field of a SocketFlow to one of the ! * canned enum values ! */ ! static void setStatus (JNIEnv *env, jobject obj, int errval) { switch (errval) { ! case 0: /* OK */ ! (*env)->SetObjectField(env, obj, sf_status, sfs_OK); ! break; ! case EPERM: ! (*env)->SetObjectField(env, obj, sf_status, sfs_NOPERMISSION); ! break; ! case ENOTCONN: ! (*env)->SetObjectField(env, obj, sf_status, sfs_NOTCONNECTED); ! break; ! case EOPNOTSUPP: ! (*env)->SetObjectField(env, obj, sf_status, sfs_NOTSUPPORTED); ! break; ! case EALREADY: ! (*env)->SetObjectField(env, obj, sf_status, sfs_ALREADYCREATED); ! break; ! case EINPROGRESS: ! (*env)->SetObjectField(env, obj, sf_status, sfs_INPROGRESS); ! break; ! default: ! (*env)->SetObjectField(env, obj, sf_status, sfs_OTHER); ! break; } } ! #ifdef __solaris__ /* ! * Class: sun_net_ExtendedOptionsImpl ! * Method: setFlowOption ! * Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V */ ! JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption ! (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) { - int fd = getFD(env, fileDesc); - - if (fd < 0) { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed"); - return; - } else { - sock_flow_props_t props; - jlong bandwidth; int rv; ! ! jint priority = (*env)->GetIntField(env, flow, sf_priority); memset(&props, 0, sizeof(props)); props.sfp_version = SOCK_FLOW_PROP_VERSION1; if (priority != jdk_net_SocketFlow_UNSET) { props.sfp_mask |= SFP_PRIORITY; props.sfp_priority = priority; } ! bandwidth = (*env)->GetLongField(env, flow, sf_bandwidth); ! if (bandwidth > -1) { props.sfp_mask |= SFP_MAXBW; props.sfp_maxbw = (uint64_t) bandwidth; } rv = setsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props)); if (rv < 0) { if (errno == ENOPROTOOPT) { JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "unsupported socket option"); } else if (errno == EACCES || errno == EPERM) { ! NET_ERROR(env, JNU_JAVANETPKG "SocketException", ! "Permission denied"); } else { ! NET_ERROR(env, JNU_JAVANETPKG "SocketException", "set option SO_FLOW_SLA failed"); } ! return; ! } ! setStatus(env, flow, props.sfp_status); } } /* ! * Class: sun_net_ExtendedOptionsImpl ! * Method: getFlowOption ! * Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V */ ! JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption ! (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) { - int fd = getFD(env, fileDesc); - - if (fd < 0) { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed"); - return; - } else { sock_flow_props_t props; - int status; socklen_t sz = sizeof(props); int rv = getsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, &sz); if (rv < 0) { if (errno == ENOPROTOOPT) { JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "unsupported socket option"); } else if (errno == EACCES || errno == EPERM) { ! NET_ERROR(env, JNU_JAVANETPKG "SocketException", ! "Permission denied"); } else { ! NET_ERROR(env, JNU_JAVANETPKG "SocketException", ! "set option SO_FLOW_SLA failed"); } ! return; } /* first check status to see if flow exists */ ! status = props.sfp_status; ! setStatus(env, flow, status); ! if (status == 0) { /* OK */ /* can set the other fields now */ if (props.sfp_mask & SFP_PRIORITY) { (*env)->SetIntField(env, flow, sf_priority, props.sfp_priority); } if (props.sfp_mask & SFP_MAXBW) { (*env)->SetLongField(env, flow, sf_bandwidth, (jlong)props.sfp_maxbw); } } ! } } ! static jboolean flowsupported; ! static jboolean flowsupported_set = JNI_FALSE; ! ! static jboolean flowSupported0() { /* Do a simple dummy call, and try to figure out from that */ sock_flow_props_t props; int rv, s; ! if (flowsupported_set) { ! return flowsupported; ! } s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (s < 0) { - flowsupported = JNI_FALSE; - flowsupported_set = JNI_TRUE; return JNI_FALSE; } memset(&props, 0, sizeof(props)); props.sfp_version = SOCK_FLOW_PROP_VERSION1; props.sfp_mask |= SFP_PRIORITY; --- 21,166 ---- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ ! #include "SolarisSocketOptions.h" static jfieldID sf_priority; static jfieldID sf_bandwidth; ! static int initialized = 0; /* ! * Class: jdk_net_SolarisSocketOptions * Method: init * Signature: ()V */ ! JNIEXPORT void JNICALL Java_jdk_net_SolarisSocketOptions_init ! (JNIEnv *env, jclass unused) { ! if (!initialized) { ! jclass c = (*env)->FindClass(env, "jdk/net/SocketFlow"); CHECK_NULL(c); sf_priority = (*env)->GetFieldID(env, c, "priority", "I"); CHECK_NULL(sf_priority); sf_bandwidth = (*env)->GetFieldID(env, c, "bandwidth", "J"); CHECK_NULL(sf_bandwidth); ! initialized = 1; ! } } ! /** Return the Status value. */ ! static jint toStatus(int errval) { switch (errval) { ! case 0: return jdk_net_SocketFlow_OK_VALUE; ! case EPERM: return jdk_net_SocketFlow_NO_PERMISSION_VALUE; ! case ENOTCONN: return jdk_net_SocketFlow_NOT_CONNECTED_VALUE; ! case EOPNOTSUPP: return jdk_net_SocketFlow_NOT_SUPPORTED_VALUE; ! case EALREADY: return jdk_net_SocketFlow_ALREADY_CREATED_VALUE; ! case EINPROGRESS: return jdk_net_SocketFlow_IN_PROGRESS_VALUE; ! default: return jdk_net_SocketFlow_OTHER_VALUE; } } ! void throwByNameWithLastError ! (JNIEnv *env, const char *name, const char *defaultDetail) ! { ! char defaultMsg[255]; ! sprintf(defaultMsg, "errno: %d, %s", errno, defaultDetail); ! JNU_ThrowByNameWithLastError(env, name, defaultMsg); ! } /* ! * Class: jdk_net_SolarisSocketOptions ! * Method: setFlowOption0 ! * Signature: (IIJ)I */ ! JNIEXPORT jint JNICALL Java_jdk_net_SolarisSocketOptions_setFlowOption ! (JNIEnv *env, jobject unused, jint fd, jint priority, jlong bandwidth) { int rv; ! sock_flow_props_t props; memset(&props, 0, sizeof(props)); props.sfp_version = SOCK_FLOW_PROP_VERSION1; if (priority != jdk_net_SocketFlow_UNSET) { props.sfp_mask |= SFP_PRIORITY; props.sfp_priority = priority; } ! if (bandwidth > jdk_net_SocketFlow_UNSET) { props.sfp_mask |= SFP_MAXBW; props.sfp_maxbw = (uint64_t) bandwidth; } + rv = setsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props)); + if (rv < 0) { if (errno == ENOPROTOOPT) { JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "unsupported socket option"); } else if (errno == EACCES || errno == EPERM) { ! JNU_ThrowByName(env, "java/net/SocketException", "Permission denied"); } else { ! throwByNameWithLastError(env, "java/net/SocketException", "set option SO_FLOW_SLA failed"); } ! return 0; } + return toStatus(props.sfp_status); } /* ! * Class: jdk_net_SolarisSocketOptions ! * Method: getFlowOption0 ! * Signature: (ILjdk/net/SocketFlow;)I */ ! JNIEXPORT jint JNICALL Java_jdk_net_SolarisSocketOptions_getFlowOption ! (JNIEnv *env, jobject unused, jint fd, jobject flow) { sock_flow_props_t props; socklen_t sz = sizeof(props); int rv = getsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, &sz); + if (rv < 0) { if (errno == ENOPROTOOPT) { JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "unsupported socket option"); } else if (errno == EACCES || errno == EPERM) { ! JNU_ThrowByName(env, "java/net/SocketException", "Permission denied"); } else { ! throwByNameWithLastError(env, "java/net/SocketException", ! "get option SO_FLOW_SLA failed"); } ! return -1; } /* first check status to see if flow exists */ ! if (props.sfp_status == 0) { /* OK */ /* can set the other fields now */ if (props.sfp_mask & SFP_PRIORITY) { (*env)->SetIntField(env, flow, sf_priority, props.sfp_priority); } if (props.sfp_mask & SFP_MAXBW) { (*env)->SetLongField(env, flow, sf_bandwidth, (jlong)props.sfp_maxbw); } } ! return toStatus(props.sfp_status); } ! JNIEXPORT jboolean JNICALL Java_jdk_net_SolarisSocketOptions_flowSupported ! (JNIEnv *env, jobject unused) { /* Do a simple dummy call, and try to figure out from that */ sock_flow_props_t props; int rv, s; ! s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (s < 0) { return JNI_FALSE; } memset(&props, 0, sizeof(props)); props.sfp_version = SOCK_FLOW_PROP_VERSION1; props.sfp_mask |= SFP_PRIORITY;
*** 306,344 **** rv = JNI_FALSE; } else { rv = JNI_TRUE; } close(s); ! flowsupported = rv; ! flowsupported_set = JNI_TRUE; ! return flowsupported; ! } ! ! #else /* __solaris__ */ ! ! /* Non Solaris. Functionality is not supported. So, throw UnsupportedOpExc */ ! ! JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption ! (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) ! { ! JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", ! "unsupported socket option"); ! } ! ! JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption ! (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) ! { ! JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", ! "unsupported socket option"); ! } ! ! static jboolean flowSupported0() { ! return JNI_FALSE; ! } ! ! #endif /* __solaris__ */ ! ! JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported ! (JNIEnv *env, jclass UNUSED) ! { ! return flowSupported0(); } --- 170,176 ---- rv = JNI_FALSE; } else { rv = JNI_TRUE; } close(s); ! return rv; }