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,302 ****
* 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"
- 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() ;
/*
! * Class: sun_net_ExtendedOptionsImpl
* Method: init
* Signature: ()V
*/
! JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_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");
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);
}
! /**
! * Sets the status field of a SocketFlow to one of the
! * canned enum values
! */
! static void setStatus (JNIEnv *env, jobject obj, 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;
}
}
! #ifdef __solaris__
/*
! * Class: sun_net_ExtendedOptionsImpl
! * Method: setFlowOption
! * Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V
*/
! JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption
! (JNIEnv *env, jclass UNUSED, jobject fileDesc, 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;
- jlong bandwidth;
int rv;
!
! jint priority = (*env)->GetIntField(env, flow, sf_priority);
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) {
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");
} else {
! NET_ERROR(env, JNU_JAVANETPKG "SocketException",
"set option SO_FLOW_SLA failed");
}
! return;
! }
! setStatus(env, flow, props.sfp_status);
}
}
/*
! * Class: sun_net_ExtendedOptionsImpl
! * Method: getFlowOption
! * Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V
*/
! JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption
! (JNIEnv *env, jclass UNUSED, jobject fileDesc, 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");
} else {
! NET_ERROR(env, JNU_JAVANETPKG "SocketException",
! "set option SO_FLOW_SLA failed");
}
! return;
}
/* first check status to see if flow exists */
! status = props.sfp_status;
! setStatus(env, flow, status);
! if (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);
}
}
! }
}
! static jboolean flowsupported;
! static jboolean flowsupported_set = JNI_FALSE;
!
! static jboolean flowSupported0()
{
/* 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;
--- 21,166 ----
* 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 "SolarisSocketOptions.h"
static jfieldID sf_priority;
static jfieldID sf_bandwidth;
! static int initialized = 0;
/*
! * Class: jdk_net_SolarisSocketOptions
* Method: init
* Signature: ()V
*/
! JNIEXPORT void JNICALL Java_jdk_net_SolarisSocketOptions_init
! (JNIEnv *env, jclass unused)
{
! if (!initialized) {
! jclass c = (*env)->FindClass(env, "jdk/net/SocketFlow");
CHECK_NULL(c);
sf_priority = (*env)->GetFieldID(env, c, "priority", "I");
CHECK_NULL(sf_priority);
sf_bandwidth = (*env)->GetFieldID(env, c, "bandwidth", "J");
CHECK_NULL(sf_bandwidth);
! initialized = 1;
! }
}
! /** Return the Status value. */
! static jint toStatus(int errval)
{
switch (errval) {
! 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;
}
}
! 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: jdk_net_SolarisSocketOptions
! * Method: setFlowOption0
! * Signature: (IIJ)I
*/
! JNIEXPORT jint JNICALL Java_jdk_net_SolarisSocketOptions_setFlowOption
! (JNIEnv *env, jobject unused, jint fd, jint priority, jlong bandwidth)
{
int rv;
! 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;
}
! 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) {
! JNU_ThrowByName(env, "java/net/SocketException", "Permission denied");
} else {
! throwByNameWithLastError(env, "java/net/SocketException",
"set option SO_FLOW_SLA failed");
}
! return 0;
}
+ return toStatus(props.sfp_status);
}
/*
! * Class: jdk_net_SolarisSocketOptions
! * Method: getFlowOption0
! * Signature: (ILjdk/net/SocketFlow;)I
*/
! JNIEXPORT jint JNICALL Java_jdk_net_SolarisSocketOptions_getFlowOption
! (JNIEnv *env, jobject unused, jint fd, jobject flow)
{
sock_flow_props_t props;
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) {
! JNU_ThrowByName(env, "java/net/SocketException", "Permission denied");
} else {
! throwByNameWithLastError(env, "java/net/SocketException",
! "get option SO_FLOW_SLA failed");
}
! return -1;
}
/* first check status to see if flow exists */
! 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);
}
! 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;
!
s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s < 0) {
return JNI_FALSE;
}
memset(&props, 0, sizeof(props));
props.sfp_version = SOCK_FLOW_PROP_VERSION1;
props.sfp_mask |= SFP_PRIORITY;
*** 306,344 ****
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();
}
--- 170,176 ----
rv = JNI_FALSE;
} else {
rv = JNI_TRUE;
}
close(s);
! return rv;
}