src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c
changeset 59329 289000934908
parent 50275 69204b98dc3d
equal deleted inserted replaced
59328:f280911d3427 59329:289000934908
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 #include "jni.h"
       
    27 #include "jni_util.h"
       
    28 #include "jvm.h"
       
    29 #include "jlong.h"
       
    30 
       
    31 #include <netdb.h>
    26 #include <netdb.h>
    32 #include <sys/types.h>
    27 #include <sys/types.h>
    33 #include <sys/socket.h>
    28 #include <sys/socket.h>
    34 #include <stdlib.h>
    29 #include <stdlib.h>
    35 #include <string.h>
    30 #include <string.h>
    37 
    32 
    38 #if defined(__linux__) || defined(_ALLBSD_SOURCE)
    33 #if defined(__linux__) || defined(_ALLBSD_SOURCE)
    39 #include <netinet/in.h>
    34 #include <netinet/in.h>
    40 #endif
    35 #endif
    41 
    36 
       
    37 #include "jni.h"
       
    38 #include "jni_util.h"
       
    39 #include "jlong.h"
    42 #include "net_util.h"
    40 #include "net_util.h"
    43 #include "net_util_md.h"
       
    44 #include "nio.h"
    41 #include "nio.h"
    45 #include "nio_util.h"
    42 #include "nio_util.h"
    46 
    43 
    47 #include "sun_nio_ch_DatagramChannelImpl.h"
    44 #include "sun_nio_ch_DatagramChannelImpl.h"
    48 
    45 
    49 static jfieldID dci_senderID;   /* sender in sun.nio.ch.DatagramChannelImpl */
       
    50 static jfieldID dci_senderAddrID; /* sender InetAddress in sun.nio.ch.DatagramChannelImpl */
       
    51 static jfieldID dci_senderPortID; /* sender port in sun.nio.ch.DatagramChannelImpl */
       
    52 static jclass isa_class;        /* java.net.InetSocketAddress */
       
    53 static jmethodID isa_ctorID;    /*   .InetSocketAddress(InetAddress, int) */
       
    54 
       
    55 JNIEXPORT void JNICALL
    46 JNIEXPORT void JNICALL
    56 Java_sun_nio_ch_DatagramChannelImpl_initIDs(JNIEnv *env, jclass clazz)
    47 Java_sun_nio_ch_DatagramChannelImpl_disconnect0(JNIEnv *env, jclass clazz,
    57 {
       
    58     clazz = (*env)->FindClass(env, "java/net/InetSocketAddress");
       
    59     CHECK_NULL(clazz);
       
    60     isa_class = (*env)->NewGlobalRef(env, clazz);
       
    61     if (isa_class == NULL) {
       
    62         JNU_ThrowOutOfMemoryError(env, NULL);
       
    63         return;
       
    64     }
       
    65     isa_ctorID = (*env)->GetMethodID(env, clazz, "<init>",
       
    66                                      "(Ljava/net/InetAddress;I)V");
       
    67     CHECK_NULL(isa_ctorID);
       
    68 
       
    69     clazz = (*env)->FindClass(env, "sun/nio/ch/DatagramChannelImpl");
       
    70     CHECK_NULL(clazz);
       
    71     dci_senderID = (*env)->GetFieldID(env, clazz, "sender",
       
    72                                       "Ljava/net/SocketAddress;");
       
    73     CHECK_NULL(dci_senderID);
       
    74     dci_senderAddrID = (*env)->GetFieldID(env, clazz,
       
    75                                           "cachedSenderInetAddress",
       
    76                                           "Ljava/net/InetAddress;");
       
    77     CHECK_NULL(dci_senderAddrID);
       
    78     dci_senderPortID = (*env)->GetFieldID(env, clazz,
       
    79                                           "cachedSenderPort", "I");
       
    80     CHECK_NULL(dci_senderPortID);
       
    81 }
       
    82 
       
    83 JNIEXPORT void JNICALL
       
    84 Java_sun_nio_ch_DatagramChannelImpl_disconnect0(JNIEnv *env, jobject this,
       
    85                                                 jobject fdo, jboolean isIPv6)
    48                                                 jobject fdo, jboolean isIPv6)
    86 {
    49 {
    87     jint fd = fdval(env, fdo);
    50     jint fd = fdval(env, fdo);
    88     int rv;
    51     int rv;
    89 
    52 
   120     if (rv < 0)
    83     if (rv < 0)
   121         handleSocketError(env, errno);
    84         handleSocketError(env, errno);
   122 }
    85 }
   123 
    86 
   124 JNIEXPORT jint JNICALL
    87 JNIEXPORT jint JNICALL
   125 Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this,
    88 Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jclass clazz,
   126                                              jobject fdo, jlong address,
    89                                              jobject fdo, jlong bufAddress,
   127                                              jint len, jboolean connected)
    90                                              jint len, jlong senderAddress,
       
    91                                              jboolean connected)
   128 {
    92 {
   129     jint fd = fdval(env, fdo);
    93     jint fd = fdval(env, fdo);
   130     void *buf = (void *)jlong_to_ptr(address);
    94     void *buf = (void *)jlong_to_ptr(bufAddress);
   131     SOCKETADDRESS sa;
    95     SOCKETADDRESS *sa = (SOCKETADDRESS *)jlong_to_ptr(senderAddress);
   132     socklen_t sa_len = sizeof(SOCKETADDRESS);
    96     socklen_t sa_len = sizeof(SOCKETADDRESS);
   133     jboolean retry = JNI_FALSE;
    97     jboolean retry = JNI_FALSE;
   134     jint n = 0;
    98     jint n;
   135     jobject senderAddr;
       
   136 
    99 
   137     if (len > MAX_PACKET_LEN) {
   100     if (len > MAX_PACKET_LEN) {
   138         len = MAX_PACKET_LEN;
   101         len = MAX_PACKET_LEN;
   139     }
   102     }
   140 
   103 
   141     do {
   104     do {
   142         retry = JNI_FALSE;
   105         retry = JNI_FALSE;
   143         n = recvfrom(fd, buf, len, 0, &sa.sa, &sa_len);
   106         n = recvfrom(fd, buf, len, 0, (struct sockaddr *)sa, &sa_len);
   144         if (n < 0) {
   107         if (n < 0) {
   145             if (errno == EAGAIN || errno == EWOULDBLOCK) {
   108             if (errno == EAGAIN || errno == EWOULDBLOCK) {
   146                 return IOS_UNAVAILABLE;
   109                 return IOS_UNAVAILABLE;
   147             }
   110             }
   148             if (errno == EINTR) {
   111             if (errno == EINTR) {
   150             }
   113             }
   151             if (errno == ECONNREFUSED) {
   114             if (errno == ECONNREFUSED) {
   152                 if (connected == JNI_FALSE) {
   115                 if (connected == JNI_FALSE) {
   153                     retry = JNI_TRUE;
   116                     retry = JNI_TRUE;
   154                 } else {
   117                 } else {
   155                     JNU_ThrowByName(env, JNU_JAVANETPKG
   118                     JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", 0);
   156                                     "PortUnreachableException", 0);
       
   157                     return IOS_THROWN;
   119                     return IOS_THROWN;
   158                 }
   120                 }
   159             } else {
   121             } else {
   160                 return handleSocketError(env, errno);
   122                 return handleSocketError(env, errno);
   161             }
   123             }
   162         }
   124         }
   163     } while (retry == JNI_TRUE);
   125     } while (retry == JNI_TRUE);
   164 
   126 
   165     /*
       
   166      * If the source address and port match the cached address
       
   167      * and port in DatagramChannelImpl then we don't need to
       
   168      * create InetAddress and InetSocketAddress objects.
       
   169      */
       
   170     senderAddr = (*env)->GetObjectField(env, this, dci_senderAddrID);
       
   171     if (senderAddr != NULL) {
       
   172         if (!NET_SockaddrEqualsInetAddress(env, &sa, senderAddr)) {
       
   173             senderAddr = NULL;
       
   174         } else {
       
   175             jint port = (*env)->GetIntField(env, this, dci_senderPortID);
       
   176             if (port != NET_GetPortFromSockaddr(&sa)) {
       
   177                 senderAddr = NULL;
       
   178             }
       
   179         }
       
   180     }
       
   181     if (senderAddr == NULL) {
       
   182         jobject isa = NULL;
       
   183         int port = 0;
       
   184         jobject ia = NET_SockaddrToInetAddress(env, &sa, &port);
       
   185         if (ia != NULL) {
       
   186             isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
       
   187         }
       
   188         CHECK_NULL_RETURN(isa, IOS_THROWN);
       
   189 
       
   190         (*env)->SetObjectField(env, this, dci_senderAddrID, ia);
       
   191         (*env)->SetIntField(env, this, dci_senderPortID,
       
   192                             NET_GetPortFromSockaddr(&sa));
       
   193         (*env)->SetObjectField(env, this, dci_senderID, isa);
       
   194     }
       
   195     return n;
   127     return n;
   196 }
   128 }
   197 
   129 
   198 JNIEXPORT jint JNICALL
   130 JNIEXPORT jint JNICALL
   199 Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this,
   131 Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jclass clazz,
   200                                           jboolean preferIPv6, jobject fdo, jlong address,
   132                                           jboolean preferIPv6, jobject fdo, jlong address,
   201                                           jint len, jobject destAddress, jint destPort)
   133                                           jint len, jobject destAddress, jint destPort)
   202 {
   134 {
   203     jint fd = fdval(env, fdo);
   135     jint fd = fdval(env, fdo);
   204     void *buf = (void *)jlong_to_ptr(address);
   136     void *buf = (void *)jlong_to_ptr(address);