< prev index next >

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

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -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 quickack_available();
 
 /*
  * 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,122 @@
     return JNI_FALSE;
 }
 
 #endif /* __solaris__ */
 
+#ifdef __linux__
+
+/*
+ * Class:     sun_net_ExtendedOptionsImpl
+ * Method:    setQuickAckOption
+ * Signature: (Ljava/io/FileDescriptor;Ljava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setQuickAckOption
+(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");
+    } else {
+        int rv;
+        optval = (on ? 1 : 0);
+        rv = setsockopt(fd, SOL_SOCKET, SO_QUICKACK, &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");
+            }
+        }
+    }
+}
+
+/*
+ * Class:     sun_net_ExtendedOptionsImpl
+ * Method:    getQuickAckOption
+ * Signature: (Ljava/io/FileDescriptor;)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_sun_net_ExtendedOptionsImpl_getQuickAckOption
+  (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_QUICKACK, &on, &sz);
+        if (rv < 0) {
+            if (errno == ENOPROTOOPT) {
+                JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+                        "unsupported socket option");
+            } else {
+                NET_ERROR(env, JNU_JAVANETPKG "SocketException",
+                        "setoption SO_QUICKACK failed");
+            }
+        }
+        return createBoolean(env, on);
+    }
+}
+
+static jboolean isQuickAckAvailable;
+static jboolean isQuickAckAvailableChecked = JNI_FALSE;
+static jboolean quickack_available() {
+    int one = 1;
+    int rv, s;
+    if (isQuickAckAvailableChecked) {
+        return isQuickAckAvailable;
+    }
+    s = socket(PF_INET, SOCK_STREAM, 0);
+    if (s < 0) {
+        isQuickAckAvailable = JNI_FALSE;
+        isQuickAckAvailableChecked = JNI_TRUE;
+        return JNI_FALSE;
+    }
+    rv = setsockopt(s, SOL_SOCKET, SO_QUICKACK, (void *) &one, sizeof (one));
+    isQuickAckAvailableChecked = JNI_TRUE;
+    if (rv != 0 && errno == ENOPROTOOPT) {
+        isQuickAckAvailable = JNI_FALSE;
+    } else {
+        isQuickAckAvailable = JNI_TRUE;
+    }
+    close(s);
+    return isQuickAckAvailable;
+}
+
+#else
+
+JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setQuickAckOption
+  (JNIEnv *env, jclass UNUSED, jobject fileDesc, jboolean on)
+{
+    JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+        "unsupported socket option");
+}
+
+JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_getQuickAckOption
+  (JNIEnv *env, jclass UNUSED, jobject fileDesc)
+{
+    JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+        "unsupported socket option");
+    return JNI_FALSE;
+}
+
+static jboolean quickack_available()  {
+    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_isQuickAckAvailable0
+  (JNIEnv *env, jclass UNUSED)
+{
+    return quickack_available();
+}
< prev index next >