37
38 static jfieldID sf_fd_fdID; /* FileDescriptor.fd */
39
40 /* References to the literal enum values */
41
42 static jobject sfs_NOSTATUS;
43 static jobject sfs_OK;
44 static jobject sfs_NOPERMISSION;
45 static jobject sfs_NOTCONNECTED;
46 static jobject sfs_NOTSUPPORTED;
47 static jobject sfs_ALREADYCREATED;
48 static jobject sfs_INPROGRESS;
49 static jobject sfs_OTHER;
50
51 static jobject getEnumField(JNIEnv *env, char *name);
52 static void setStatus(JNIEnv *env, jobject obj, int errval);
53
54 /* OS specific code is implemented in these three functions */
55
56 static jboolean flowSupported0() ;
57
58 /*
59 * Class: sun_net_ExtendedOptionsImpl
60 * Method: init
61 * Signature: ()V
62 */
63 JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init
64 (JNIEnv *env, jclass UNUSED)
65 {
66 static int initialized = 0;
67 jclass c;
68
69 /* Global class references */
70
71 if (initialized) {
72 return;
73 }
74
75 c = (*env)->FindClass(env, "jdk/net/SocketFlow$Status");
76 CHECK_NULL(c);
125 sfs_OTHER = getEnumField(env, "OTHER");
126 CHECK_NULL(sfs_OTHER);
127 initialized = JNI_TRUE;
128 }
129
130 static jobject getEnumField(JNIEnv *env, char *name)
131 {
132 jobject f;
133 jfieldID fID = (*env)->GetStaticFieldID(env, sf_status_class, name,
134 "Ljdk/net/SocketFlow$Status;");
135 CHECK_NULL_RETURN(fID, NULL);
136
137 f = (*env)->GetStaticObjectField(env, sf_status_class, fID);
138 CHECK_NULL_RETURN(f, NULL);
139 f = (*env)->NewGlobalRef(env, f);
140 CHECK_NULL_RETURN(f, NULL);
141 return f;
142 }
143
144 /*
145 * Retrieve the int file-descriptor from a public socket type object.
146 * Gets impl, then the FileDescriptor from the impl, and then the fd
147 * from that.
148 */
149 static int getFD(JNIEnv *env, jobject fileDesc) {
150 return (*env)->GetIntField(env, fileDesc, sf_fd_fdID);
151 }
152
153 /**
154 * Sets the status field of a SocketFlow to one of the
155 * canned enum values
156 */
157 static void setStatus (JNIEnv *env, jobject obj, int errval)
158 {
159 switch (errval) {
160 case 0: /* OK */
161 (*env)->SetObjectField(env, obj, sf_status, sfs_OK);
162 break;
163 case EPERM:
164 (*env)->SetObjectField(env, obj, sf_status, sfs_NOPERMISSION);
320 JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption
321 (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
322 {
323 JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
324 "unsupported socket option");
325 }
326
327 JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption
328 (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
329 {
330 JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
331 "unsupported socket option");
332 }
333
334 static jboolean flowSupported0() {
335 return JNI_FALSE;
336 }
337
338 #endif /* __solaris__ */
339
340 JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported
341 (JNIEnv *env, jclass UNUSED)
342 {
343 return flowSupported0();
344 }
|
37
38 static jfieldID sf_fd_fdID; /* FileDescriptor.fd */
39
40 /* References to the literal enum values */
41
42 static jobject sfs_NOSTATUS;
43 static jobject sfs_OK;
44 static jobject sfs_NOPERMISSION;
45 static jobject sfs_NOTCONNECTED;
46 static jobject sfs_NOTSUPPORTED;
47 static jobject sfs_ALREADYCREATED;
48 static jobject sfs_INPROGRESS;
49 static jobject sfs_OTHER;
50
51 static jobject getEnumField(JNIEnv *env, char *name);
52 static void setStatus(JNIEnv *env, jobject obj, int errval);
53
54 /* OS specific code is implemented in these three functions */
55
56 static jboolean flowSupported0() ;
57 static jboolean reuseportSupported0() ;
58
59 /*
60 * Class: sun_net_ExtendedOptionsImpl
61 * Method: init
62 * Signature: ()V
63 */
64 JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init
65 (JNIEnv *env, jclass UNUSED)
66 {
67 static int initialized = 0;
68 jclass c;
69
70 /* Global class references */
71
72 if (initialized) {
73 return;
74 }
75
76 c = (*env)->FindClass(env, "jdk/net/SocketFlow$Status");
77 CHECK_NULL(c);
126 sfs_OTHER = getEnumField(env, "OTHER");
127 CHECK_NULL(sfs_OTHER);
128 initialized = JNI_TRUE;
129 }
130
131 static jobject getEnumField(JNIEnv *env, char *name)
132 {
133 jobject f;
134 jfieldID fID = (*env)->GetStaticFieldID(env, sf_status_class, name,
135 "Ljdk/net/SocketFlow$Status;");
136 CHECK_NULL_RETURN(fID, NULL);
137
138 f = (*env)->GetStaticObjectField(env, sf_status_class, fID);
139 CHECK_NULL_RETURN(f, NULL);
140 f = (*env)->NewGlobalRef(env, f);
141 CHECK_NULL_RETURN(f, NULL);
142 return f;
143 }
144
145 /*
146 * Returns a java.lang.Boolean based on 'b'
147 */
148 static jobject createBoolean(JNIEnv *env, int b) {
149 static jclass b_class;
150 static jmethodID b_ctrID;
151
152 if (b_class == NULL) {
153 jclass c = (*env)->FindClass(env, "java/lang/Boolean");
154 CHECK_NULL_RETURN(c, NULL);
155 b_ctrID = (*env)->GetMethodID(env, c, "<init>", "(Z)V");
156 CHECK_NULL_RETURN(b_ctrID, NULL);
157 b_class = (*env)->NewGlobalRef(env, c);
158 CHECK_NULL_RETURN(b_class, NULL);
159 }
160
161 return( (*env)->NewObject(env, b_class, b_ctrID, (jboolean)(b!=0)) );
162 }
163
164 /*
165 * Retrieve the int file-descriptor from a public socket type object.
166 * Gets impl, then the FileDescriptor from the impl, and then the fd
167 * from that.
168 */
169 static int getFD(JNIEnv *env, jobject fileDesc) {
170 return (*env)->GetIntField(env, fileDesc, sf_fd_fdID);
171 }
172
173 /**
174 * Sets the status field of a SocketFlow to one of the
175 * canned enum values
176 */
177 static void setStatus (JNIEnv *env, jobject obj, int errval)
178 {
179 switch (errval) {
180 case 0: /* OK */
181 (*env)->SetObjectField(env, obj, sf_status, sfs_OK);
182 break;
183 case EPERM:
184 (*env)->SetObjectField(env, obj, sf_status, sfs_NOPERMISSION);
340 JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption
341 (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
342 {
343 JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
344 "unsupported socket option");
345 }
346
347 JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption
348 (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
349 {
350 JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
351 "unsupported socket option");
352 }
353
354 static jboolean flowSupported0() {
355 return JNI_FALSE;
356 }
357
358 #endif /* __solaris__ */
359
360
361 #ifdef __linux__
362 /*
363 * Class: sun_net_ExtendedOptionsImpl
364 * Method: setReusePortOption
365 * Signature: (Ljava/io/FileDescriptor;Ljava/lang/Object;)V
366 */
367 JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setReusePortOption
368 (JNIEnv *env, jclass UNUSED, jobject fileDesc, jboolean on)
369 {
370 int fd = getFD(env, fileDesc);
371 int optval;
372
373 if (fd < 0) {
374 NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed");
375 return;
376 } else {
377 int rv;
378 optval = (on ? 1 : 0);
379 rv = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
380 if (rv < 0) {
381 if (errno == ENOPROTOOPT) {
382 JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
383 "unsupported socket option");
384 } else {
385 NET_ERROR(env, JNU_JAVANETPKG "SocketException",
386 "set option SO_REUSEPORT failed");
387 }
388 return;
389 }
390 }
391 }
392 /*
393 * Class: sun_net_ExtendedOptionsImpl
394 * Method: getReusePortOption
395 * Signature: (Ljava/io/FileDescriptor;)Ljava/lang/Object;
396 */
397 JNIEXPORT jobject JNICALL Java_sun_net_ExtendedOptionsImpl_getReusePortOption
398 (JNIEnv *env, jclass UNUSED, jobject fileDesc)
399 {
400 int fd = getFD(env, fileDesc);
401
402 if (fd < 0) {
403 NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed");
404 return JNI_FALSE;
405 } else {
406 int on;
407 socklen_t sz = sizeof(on);
408
409 int rv = getsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, &sz);
410 if (rv < 0) {
411 if (errno == ENOPROTOOPT) {
412 JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
413 "unsupported socket option");
414 } else {
415 NET_ERROR(env, JNU_JAVANETPKG "SocketException",
416 "set option SO_REUSEPORT failed");
417 }
418 }
419 printf("getReusePortOption returns %d\n", on);
420 return createBoolean(env, on);
421 }
422 }
423
424 static jboolean reuseportsupported;
425 static jboolean reuseportsupported_set = JNI_FALSE;
426
427 static jboolean reuseportSupported0()
428 {
429 /* Do a simple dummy call, and try to figure out from that */
430 int one = 1;
431 int rv, s;
432 if (reuseportsupported_set) {
433 return reuseportsupported;
434 }
435 s = socket(PF_INET, SOCK_STREAM, 0);
436 if (s < 0) {
437 reuseportsupported = JNI_FALSE;
438 reuseportsupported_set = JNI_TRUE;
439 return JNI_FALSE;
440 }
441 rv = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void *)&one, sizeof(one));
442 if (rv != 0 && errno == ENOPROTOOPT) {
443 rv = JNI_FALSE;
444 } else {
445 rv = JNI_TRUE;
446 }
447 close(s);
448 reuseportsupported = rv;
449 reuseportsupported_set = JNI_TRUE;
450 return reuseportsupported;
451 }
452
453 #else /* __linux__ */
454
455 /* Non Linux. Functionality is not supported. So, throw UnsupportedOpExc */
456
457 JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setReusePortOption
458 (JNIEnv *env, jclass UNUSED, jobject fileDesc, jboolean on)
459 {
460 JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
461 "unsupported socket option");
462 }
463
464 JNIEXPORT jobject JNICALL Java_sun_net_ExtendedOptionsImpl_getReusePortOption
465 (JNIEnv *env, jclass UNUSED, jobject fileDesc)
466 {
467 JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
468 "unsupported socket option");
469 return JNI_FALSE;
470 }
471
472 static jboolean reuseportSupported0() {
473 return JNI_FALSE;
474 }
475 #endif /* __linux__ */
476
477 JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported
478 (JNIEnv *env, jclass UNUSED)
479 {
480 return flowSupported0();
481 }
482
483 JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_reuseportSupported
484 (JNIEnv *env, jclass UNUSED)
485 {
486 return reuseportSupported0();
487 }
|