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,282 +21,146 @@
  * 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"
+#include "SolarisSocketOptions.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() ;
+static int initialized = 0;
 
 /*
- * Class:     sun_net_ExtendedOptionsImpl
+ * Class:     jdk_net_SolarisSocketOptions
  * Method:    init
  * Signature: ()V
  */
-JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init
-  (JNIEnv *env, jclass UNUSED)
+JNIEXPORT void JNICALL Java_jdk_net_SolarisSocketOptions_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");
+    if (!initialized) {
+        jclass c = (*env)->FindClass(env, "jdk/net/SocketFlow");
     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);
+        initialized = 1;
+    }
 }
 
-/**
- * Sets the status field of a SocketFlow to one of the
- * canned enum values
- */
-static void setStatus (JNIEnv *env, jobject obj, int errval)
+/** Return the Status value. */
+static jint toStatus(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;
+      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;
     }
 }
 
-#ifdef __solaris__
+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:     sun_net_ExtendedOptionsImpl
- * Method:    setFlowOption
- * Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V
+ * Class:     jdk_net_SolarisSocketOptions
+ * Method:    setFlowOption0
+ * Signature: (IIJ)I
  */
-JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption
-  (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
+JNIEXPORT jint JNICALL Java_jdk_net_SolarisSocketOptions_setFlowOption
+  (JNIEnv *env, jobject unused, jint fd, jint priority, jlong bandwidth)
 {
-    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);
+    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;
         }
-        bandwidth = (*env)->GetLongField(env, flow, sf_bandwidth);
-        if (bandwidth > -1)  {
+    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) {
-                NET_ERROR(env, JNU_JAVANETPKG "SocketException",
-                                "Permission denied");
+            JNU_ThrowByName(env, "java/net/SocketException", "Permission denied");
             } else {
-                NET_ERROR(env, JNU_JAVANETPKG "SocketException",
+            throwByNameWithLastError(env, "java/net/SocketException",
                                 "set option SO_FLOW_SLA failed");
             }
-            return;
-        }
-        setStatus(env, flow, props.sfp_status);
+        return 0;
     }
+    return toStatus(props.sfp_status);
 }
 
 /*
- * Class:     sun_net_ExtendedOptionsImpl
- * Method:    getFlowOption
- * Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V
+ * Class:     jdk_net_SolarisSocketOptions
+ * Method:    getFlowOption0
+ * Signature: (ILjdk/net/SocketFlow;)I
  */
-JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption
-  (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
+JNIEXPORT jint JNICALL Java_jdk_net_SolarisSocketOptions_getFlowOption
+  (JNIEnv *env, jobject unused, jint fd, 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");
+            JNU_ThrowByName(env, "java/net/SocketException", "Permission denied");
             } else {
-                NET_ERROR(env, JNU_JAVANETPKG "SocketException",
-                                "set option SO_FLOW_SLA failed");
+            throwByNameWithLastError(env, "java/net/SocketException",
+                                     "get option SO_FLOW_SLA failed");
             }
-            return;
+        return -1;
         }
         /* first check status to see if flow exists */
-        status = props.sfp_status;
-        setStatus(env, flow, status);
-        if (status == 0) { /* OK */
+    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);
 }
 
-static jboolean flowsupported;
-static jboolean flowsupported_set = JNI_FALSE;
-
-static jboolean flowSupported0()
+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;
-    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;

@@ -306,39 +170,7 @@
         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();
+    return rv;
 }