< prev index next >

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

Print this page

        

@@ -52,10 +52,11 @@
 static void setStatus(JNIEnv *env, jobject obj, int errval);
 
 /* OS specific code is implemented in these three functions */
 
 static jboolean flowSupported0() ;
+static jboolean reuseportSupported0() ;
 
 /*
  * Class:     sun_net_ExtendedOptionsImpl
  * Method:    init
  * Signature: ()V

@@ -140,10 +141,29 @@
     CHECK_NULL_RETURN(f, NULL);
     return f;
 }
 
 /*
+ * Returns a java.lang.Boolean based on 'b'
+ */
+static jobject createBoolean(JNIEnv *env, int b) {
+    static jclass b_class;
+    static jmethodID b_ctrID;
+
+    if (b_class == NULL) {
+        jclass c = (*env)->FindClass(env, "java/lang/Boolean");
+        CHECK_NULL_RETURN(c, NULL);
+        b_ctrID = (*env)->GetMethodID(env, c, "<init>", "(Z)V");
+        CHECK_NULL_RETURN(b_ctrID, NULL);
+        b_class = (*env)->NewGlobalRef(env, c);
+        CHECK_NULL_RETURN(b_class, NULL);
+    }
+
+    return( (*env)->NewObject(env, b_class, b_ctrID, (jboolean)(b!=0)) );
+}
+
+/*
  * 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) {

@@ -335,10 +355,133 @@
     return JNI_FALSE;
 }
 
 #endif /* __solaris__ */
 
+
+#ifdef __linux__
+/*
+ * Class:     sun_net_ExtendedOptionsImpl
+ * Method:    setReusePortOption
+ * Signature: (Ljava/io/FileDescriptor;Ljava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setReusePortOption
+  (JNIEnv *env, jclass UNUSED, jobject fileDesc, jboolean on)
+{
+    int fd = getFD(env, fileDesc);
+    int optval;
+ 
+    if (fd < 0) {
+        NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed");
+        return;
+    } else {
+        int rv;
+        optval = (on ? 1 : 0);
+        rv = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
+        if (rv < 0) {
+            if (errno == ENOPROTOOPT) {
+                JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+                        "unsupported socket option");
+            } else {
+                NET_ERROR(env, JNU_JAVANETPKG "SocketException",
+                                "set option SO_REUSEPORT failed");
+            }
+            return;
+        }
+    }
+}
+/*
+ * Class:     sun_net_ExtendedOptionsImpl
+ * Method:    getReusePortOption
+ * Signature: (Ljava/io/FileDescriptor;)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_sun_net_ExtendedOptionsImpl_getReusePortOption
+  (JNIEnv *env, jclass UNUSED, jobject fileDesc)
+{
+    int fd = getFD(env, fileDesc);
+
+    if (fd < 0) {
+        NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed");
+        return JNI_FALSE;
+    } else {
+        int on;
+        socklen_t sz = sizeof(on);
+
+        int rv = getsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, &sz);
+        if (rv < 0) {
+            if (errno == ENOPROTOOPT) {
+                JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+                        "unsupported socket option");
+            } else {
+                NET_ERROR(env, JNU_JAVANETPKG "SocketException",
+                                "set option SO_REUSEPORT failed");
+            }
+        }
+        printf("getReusePortOption returns %d\n", on);
+        return createBoolean(env, on);
+    }
+}
+
+static jboolean reuseportsupported;
+static jboolean reuseportsupported_set = JNI_FALSE;
+
+static jboolean reuseportSupported0()
+{
+    /* Do a simple dummy call, and try to figure out from that */
+    int one = 1;
+    int rv, s;
+    if (reuseportsupported_set) {
+        return reuseportsupported;
+    }
+    s = socket(PF_INET, SOCK_STREAM, 0);
+    if (s < 0) {
+        reuseportsupported = JNI_FALSE;
+        reuseportsupported_set = JNI_TRUE;
+        return JNI_FALSE;
+    }
+    rv = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void *)&one, sizeof(one));
+    if (rv != 0 && errno == ENOPROTOOPT) {
+        rv = JNI_FALSE;
+    } else {
+        rv = JNI_TRUE;
+    }
+    close(s);
+    reuseportsupported = rv;
+    reuseportsupported_set = JNI_TRUE;
+    return reuseportsupported;
+}
+
+#else /* __linux__ */
+
+/* Non Linux. Functionality is not supported. So, throw UnsupportedOpExc */
+
+JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setReusePortOption
+  (JNIEnv *env, jclass UNUSED, jobject fileDesc, jboolean on)
+{
+    JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+        "unsupported socket option");
+}
+
+JNIEXPORT jobject JNICALL Java_sun_net_ExtendedOptionsImpl_getReusePortOption
+  (JNIEnv *env, jclass UNUSED, jobject fileDesc)
+{
+    JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+        "unsupported socket option");
+    return JNI_FALSE;
+}
+
+static jboolean reuseportSupported0()  {
+    return JNI_FALSE;
+}
+#endif /* __linux__ */
+
 JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported
   (JNIEnv *env, jclass UNUSED)
 {
     return flowSupported0();
 }
+
+JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_reuseportSupported
+  (JNIEnv *env, jclass UNUSED)
+{
+    return reuseportSupported0();
+}
< prev index next >