< 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 >