< prev index next >

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

Print this page




  26 
  27 #include "jvm.h"
  28 #include "net_util.h"
  29 
  30 #include "java_net_SocketOptions.h"
  31 #include "java_net_PlainSocketImpl.h"
  32 
  33 /************************************************************************
  34  * PlainSocketImpl
  35  */
  36 
  37 static jfieldID IO_fd_fdID;
  38 
  39 jfieldID psi_fdID;
  40 jfieldID psi_addressID;
  41 jfieldID psi_ipaddressID;
  42 jfieldID psi_portID;
  43 jfieldID psi_localportID;
  44 jfieldID psi_timeoutID;
  45 jfieldID psi_trafficClassID;
  46 jfieldID psi_serverSocketID;
  47 jfieldID psi_fdLockID;
  48 jfieldID psi_closePendingID;
  49 
  50 extern void setDefaultScopeID(JNIEnv *env, struct sockaddr *him);
  51 
  52 /*
  53  * file descriptor used for dup2
  54  */
  55 static int marker_fd = -1;
  56 
  57 
  58 #define SET_NONBLOCKING(fd) {           \
  59         int flags = fcntl(fd, F_GETFL); \
  60         flags |= O_NONBLOCK;            \
  61         fcntl(fd, F_SETFL, flags);      \
  62 }
  63 
  64 #define SET_BLOCKING(fd) {              \
  65         int flags = fcntl(fd, F_GETFL); \
  66         flags &= ~O_NONBLOCK;           \


 111  * Class:     java_net_PlainSocketImpl
 112  * Method:    initProto
 113  * Signature: ()V
 114  */
 115 JNIEXPORT void JNICALL
 116 Java_java_net_PlainSocketImpl_initProto(JNIEnv *env, jclass cls) {
 117     psi_fdID = (*env)->GetFieldID(env, cls , "fd",
 118                                   "Ljava/io/FileDescriptor;");
 119     CHECK_NULL(psi_fdID);
 120     psi_addressID = (*env)->GetFieldID(env, cls, "address",
 121                                           "Ljava/net/InetAddress;");
 122     CHECK_NULL(psi_addressID);
 123     psi_portID = (*env)->GetFieldID(env, cls, "port", "I");
 124     CHECK_NULL(psi_portID);
 125     psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I");
 126     CHECK_NULL(psi_localportID);
 127     psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I");
 128     CHECK_NULL(psi_timeoutID);
 129     psi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I");
 130     CHECK_NULL(psi_trafficClassID);
 131     psi_serverSocketID = (*env)->GetFieldID(env, cls, "serverSocket",
 132                         "Ljava/net/ServerSocket;");
 133     CHECK_NULL(psi_serverSocketID);
 134     psi_fdLockID = (*env)->GetFieldID(env, cls, "fdLock",
 135                                       "Ljava/lang/Object;");
 136     CHECK_NULL(psi_fdLockID);
 137     psi_closePendingID = (*env)->GetFieldID(env, cls, "closePending", "Z");
 138     CHECK_NULL(psi_closePendingID);
 139     IO_fd_fdID = NET_GetFileDescriptorID(env);
 140     CHECK_NULL(IO_fd_fdID);
 141 
 142     initInetAddressIDs(env);
 143     JNU_CHECK_EXCEPTION(env);
 144 
 145     /* Create the marker fd used for dup2 */
 146     marker_fd = getMarkerFD();
 147 }
 148 
 149 /* a global reference to the java.net.SocketException class. In
 150  * socketCreate, we ensure that this is initialized. This is to
 151  * prevent the problem where socketCreate runs out of file
 152  * descriptors, and is then unable to load the exception class.
 153  */
 154 static jclass socketExceptionCls;
 155 
 156 /*
 157  * Class:     java_net_PlainSocketImpl
 158  * Method:    socketCreate
 159  * Signature: (Z)V */
 160 JNIEXPORT void JNICALL
 161 Java_java_net_PlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
 162                                            jboolean stream) {
 163     jobject fdObj, ssObj;
 164     int fd;
 165     int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
 166     int domain = ipv6_available() ? AF_INET6 : AF_INET;
 167 
 168     if (socketExceptionCls == NULL) {
 169         jclass c = (*env)->FindClass(env, "java/net/SocketException");
 170         CHECK_NULL(c);
 171         socketExceptionCls = (jclass)(*env)->NewGlobalRef(env, c);
 172         CHECK_NULL(socketExceptionCls);
 173     }
 174     fdObj = (*env)->GetObjectField(env, this, psi_fdID);
 175 
 176     if (fdObj == NULL) {
 177         (*env)->ThrowNew(env, socketExceptionCls, "null fd object");
 178         return;
 179     }
 180 
 181     if ((fd = socket(domain, type, 0)) == -1) {
 182         /* note: if you run out of fds, you may not be able to load


 185          */
 186         NET_ThrowNew(env, errno, "can't create socket");
 187         return;
 188     }
 189 
 190     /* Disable IPV6_V6ONLY to ensure dual-socket support */
 191     if (domain == AF_INET6) {
 192         int arg = 0;
 193         if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
 194                        sizeof(int)) < 0) {
 195             NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
 196             close(fd);
 197             return;
 198         }
 199     }
 200 
 201     /*
 202      * If this is a server socket then enable SO_REUSEADDR
 203      * automatically and set to non blocking.
 204      */
 205     ssObj = (*env)->GetObjectField(env, this, psi_serverSocketID);
 206     if (ssObj != NULL) {
 207         int arg = 1;
 208         SET_NONBLOCKING(fd);
 209         if (NET_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
 210                        sizeof(arg)) < 0) {
 211             NET_ThrowNew(env, errno, "cannot set SO_REUSEADDR");
 212             close(fd);
 213             return;
 214         }
 215     }
 216 
 217     (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
 218 }
 219 
 220 /*
 221  * inetAddress is the address object passed to the socket connect
 222  * call.
 223  *
 224  * Class:     java_net_PlainSocketImpl
 225  * Method:    socketConnect
 226  * Signature: (Ljava/net/InetAddress;I)V




  26 
  27 #include "jvm.h"
  28 #include "net_util.h"
  29 
  30 #include "java_net_SocketOptions.h"
  31 #include "java_net_PlainSocketImpl.h"
  32 
  33 /************************************************************************
  34  * PlainSocketImpl
  35  */
  36 
  37 static jfieldID IO_fd_fdID;
  38 
  39 jfieldID psi_fdID;
  40 jfieldID psi_addressID;
  41 jfieldID psi_ipaddressID;
  42 jfieldID psi_portID;
  43 jfieldID psi_localportID;
  44 jfieldID psi_timeoutID;
  45 jfieldID psi_trafficClassID;

  46 jfieldID psi_fdLockID;
  47 jfieldID psi_closePendingID;
  48 
  49 extern void setDefaultScopeID(JNIEnv *env, struct sockaddr *him);
  50 
  51 /*
  52  * file descriptor used for dup2
  53  */
  54 static int marker_fd = -1;
  55 
  56 
  57 #define SET_NONBLOCKING(fd) {           \
  58         int flags = fcntl(fd, F_GETFL); \
  59         flags |= O_NONBLOCK;            \
  60         fcntl(fd, F_SETFL, flags);      \
  61 }
  62 
  63 #define SET_BLOCKING(fd) {              \
  64         int flags = fcntl(fd, F_GETFL); \
  65         flags &= ~O_NONBLOCK;           \


 110  * Class:     java_net_PlainSocketImpl
 111  * Method:    initProto
 112  * Signature: ()V
 113  */
 114 JNIEXPORT void JNICALL
 115 Java_java_net_PlainSocketImpl_initProto(JNIEnv *env, jclass cls) {
 116     psi_fdID = (*env)->GetFieldID(env, cls , "fd",
 117                                   "Ljava/io/FileDescriptor;");
 118     CHECK_NULL(psi_fdID);
 119     psi_addressID = (*env)->GetFieldID(env, cls, "address",
 120                                           "Ljava/net/InetAddress;");
 121     CHECK_NULL(psi_addressID);
 122     psi_portID = (*env)->GetFieldID(env, cls, "port", "I");
 123     CHECK_NULL(psi_portID);
 124     psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I");
 125     CHECK_NULL(psi_localportID);
 126     psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I");
 127     CHECK_NULL(psi_timeoutID);
 128     psi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I");
 129     CHECK_NULL(psi_trafficClassID);



 130     psi_fdLockID = (*env)->GetFieldID(env, cls, "fdLock",
 131                                       "Ljava/lang/Object;");
 132     CHECK_NULL(psi_fdLockID);
 133     psi_closePendingID = (*env)->GetFieldID(env, cls, "closePending", "Z");
 134     CHECK_NULL(psi_closePendingID);
 135     IO_fd_fdID = NET_GetFileDescriptorID(env);
 136     CHECK_NULL(IO_fd_fdID);
 137 
 138     initInetAddressIDs(env);
 139     JNU_CHECK_EXCEPTION(env);
 140 
 141     /* Create the marker fd used for dup2 */
 142     marker_fd = getMarkerFD();
 143 }
 144 
 145 /* a global reference to the java.net.SocketException class. In
 146  * socketCreate, we ensure that this is initialized. This is to
 147  * prevent the problem where socketCreate runs out of file
 148  * descriptors, and is then unable to load the exception class.
 149  */
 150 static jclass socketExceptionCls;
 151 
 152 /*
 153  * Class:     java_net_PlainSocketImpl
 154  * Method:    socketCreate
 155  * Signature: (ZZ)V */
 156 JNIEXPORT void JNICALL
 157 Java_java_net_PlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
 158                                            jboolean stream, jboolean server) {
 159     jobject fdObj, ssObj;
 160     int fd;
 161     int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
 162     int domain = ipv6_available() ? AF_INET6 : AF_INET;
 163 
 164     if (socketExceptionCls == NULL) {
 165         jclass c = (*env)->FindClass(env, "java/net/SocketException");
 166         CHECK_NULL(c);
 167         socketExceptionCls = (jclass)(*env)->NewGlobalRef(env, c);
 168         CHECK_NULL(socketExceptionCls);
 169     }
 170     fdObj = (*env)->GetObjectField(env, this, psi_fdID);
 171 
 172     if (fdObj == NULL) {
 173         (*env)->ThrowNew(env, socketExceptionCls, "null fd object");
 174         return;
 175     }
 176 
 177     if ((fd = socket(domain, type, 0)) == -1) {
 178         /* note: if you run out of fds, you may not be able to load


 181          */
 182         NET_ThrowNew(env, errno, "can't create socket");
 183         return;
 184     }
 185 
 186     /* Disable IPV6_V6ONLY to ensure dual-socket support */
 187     if (domain == AF_INET6) {
 188         int arg = 0;
 189         if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
 190                        sizeof(int)) < 0) {
 191             NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
 192             close(fd);
 193             return;
 194         }
 195     }
 196 
 197     /*
 198      * If this is a server socket then enable SO_REUSEADDR
 199      * automatically and set to non blocking.
 200      */
 201     if (server) {

 202         int arg = 1;
 203         SET_NONBLOCKING(fd);
 204         if (NET_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
 205                        sizeof(arg)) < 0) {
 206             NET_ThrowNew(env, errno, "cannot set SO_REUSEADDR");
 207             close(fd);
 208             return;
 209         }
 210     }
 211 
 212     (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
 213 }
 214 
 215 /*
 216  * inetAddress is the address object passed to the socket connect
 217  * call.
 218  *
 219  * Class:     java_net_PlainSocketImpl
 220  * Method:    socketConnect
 221  * Signature: (Ljava/net/InetAddress;I)V


< prev index next >