src/java.base/windows/native/libnio/ch/DatagramChannelImpl.c
changeset 59329 289000934908
parent 47216 71c04702a3d5
equal deleted inserted replaced
59328:f280911d3427 59329:289000934908
     1 /*
     1 /*
     2  * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    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 <winsock2.h>
       
    27 
    26 #include "jni.h"
    28 #include "jni.h"
    27 #include "jni_util.h"
    29 #include "jni_util.h"
    28 #include "jvm.h"
       
    29 #include "jlong.h"
    30 #include "jlong.h"
    30 #include <io.h>
    31 #include "net_util.h"
    31 #include "sun_nio_ch_DatagramChannelImpl.h"
       
    32 #include "nio.h"
    32 #include "nio.h"
    33 #include "nio_util.h"
    33 #include "nio_util.h"
    34 #include "net_util.h"
       
    35 #include <winsock2.h>
       
    36 
    34 
    37 static jfieldID dci_senderID;   /* sender in sun.nio.ch.DatagramChannelImpl */
    35 #include "sun_nio_ch_DatagramChannelImpl.h"
    38 static jfieldID dci_senderAddrID; /* sender InetAddress in sun.nio.ch.DatagramChannelImpl */
       
    39 static jfieldID dci_senderPortID; /* sender port in sun.nio.ch.DatagramChannelImpl */
       
    40 static jclass isa_class;        /* java.net.InetSocketAddress */
       
    41 static jmethodID isa_ctorID;    /* java.net.InetSocketAddress(InetAddress, int) */
       
    42 
       
    43 
       
    44 JNIEXPORT void JNICALL
       
    45 Java_sun_nio_ch_DatagramChannelImpl_initIDs(JNIEnv *env, jclass clazz)
       
    46 {
       
    47     clazz = (*env)->FindClass(env, "java/net/InetSocketAddress");
       
    48     CHECK_NULL(clazz);
       
    49     isa_class = (*env)->NewGlobalRef(env, clazz);
       
    50     if (isa_class == NULL) {
       
    51         JNU_ThrowOutOfMemoryError(env, NULL);
       
    52         return;
       
    53     }
       
    54     isa_ctorID = (*env)->GetMethodID(env, clazz, "<init>",
       
    55                                      "(Ljava/net/InetAddress;I)V");
       
    56     CHECK_NULL(isa_ctorID);
       
    57 
       
    58     clazz = (*env)->FindClass(env, "sun/nio/ch/DatagramChannelImpl");
       
    59     CHECK_NULL(clazz);
       
    60     dci_senderID = (*env)->GetFieldID(env, clazz, "sender",
       
    61                                       "Ljava/net/SocketAddress;");
       
    62     CHECK_NULL(dci_senderID);
       
    63     dci_senderAddrID = (*env)->GetFieldID(env, clazz,
       
    64                                           "cachedSenderInetAddress",
       
    65                                           "Ljava/net/InetAddress;");
       
    66     CHECK_NULL(dci_senderAddrID);
       
    67     dci_senderPortID = (*env)->GetFieldID(env, clazz,
       
    68                                           "cachedSenderPort", "I");
       
    69     CHECK_NULL(dci_senderPortID);
       
    70 }
       
    71 
    36 
    72 /*
    37 /*
    73  * This function "purges" all outstanding ICMP port unreachable packets
    38  * This function "purges" all outstanding ICMP port unreachable packets
    74  * outstanding on a socket and returns JNI_TRUE if any ICMP messages
    39  * outstanding on a socket and returns JNI_TRUE if any ICMP messages
    75  * have been purged. The rational for purging is to emulate normal BSD
    40  * have been purged. The rational for purging is to emulate normal BSD
   110 
    75 
   111     return got_icmp;
    76     return got_icmp;
   112 }
    77 }
   113 
    78 
   114 JNIEXPORT void JNICALL
    79 JNIEXPORT void JNICALL
   115 Java_sun_nio_ch_DatagramChannelImpl_disconnect0(JNIEnv *env, jobject this,
    80 Java_sun_nio_ch_DatagramChannelImpl_disconnect0(JNIEnv *env, jclass clazz,
   116                                                 jobject fdo, jboolean isIPv6)
    81                                                 jobject fdo, jboolean isIPv6)
   117 {
    82 {
   118     jint fd = fdval(env, fdo);
    83     jint fd = fdval(env, fdo);
   119     int rv = 0;
    84     int rv = 0;
   120     SOCKETADDRESS sa;
    85     SOCKETADDRESS sa;
   133                  NULL, 0, &bytesReturned, NULL, NULL);
    98                  NULL, 0, &bytesReturned, NULL, NULL);
   134     }
    99     }
   135 }
   100 }
   136 
   101 
   137 JNIEXPORT jint JNICALL
   102 JNIEXPORT jint JNICALL
   138 Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jobject this,
   103 Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jclass clazz,
   139                                             jobject fdo, jlong address,
   104                                              jobject fdo, jlong bufAddress,
   140                                             jint len, jboolean connected)
   105                                              jint len, jlong senderAddress,
       
   106                                              jboolean connected)
   141 {
   107 {
   142     jint fd = fdval(env, fdo);
   108     jint fd = fdval(env, fdo);
   143     void *buf = (void *)jlong_to_ptr(address);
   109     void *buf = (void *)jlong_to_ptr(bufAddress);
   144     SOCKETADDRESS sa;
   110     SOCKETADDRESS *sa = (SOCKETADDRESS *)jlong_to_ptr(senderAddress);
   145     int sa_len = sizeof(sa);
   111     int sa_len = sizeof(SOCKETADDRESS);
   146     BOOL retry = FALSE;
   112     BOOL retry = FALSE;
   147     jint n;
   113     jint n;
   148     jobject senderAddr;
       
   149 
   114 
   150     do {
   115     do {
   151         retry = FALSE;
   116         retry = FALSE;
   152         n = recvfrom((SOCKET)fd,
   117         n = recvfrom((SOCKET)fd,
   153                      (char *)buf,
   118                      (char *)buf,
   154                      len,
   119                      len,
   155                      0,
   120                      0,
   156                      &sa.sa,
   121                      (struct sockaddr *)sa,
   157                      &sa_len);
   122                      &sa_len);
   158 
   123 
   159         if (n == SOCKET_ERROR) {
   124         if (n == SOCKET_ERROR) {
   160             int theErr = (jint)WSAGetLastError();
   125             int theErr = (jint)WSAGetLastError();
   161             if (theErr == WSAEMSGSIZE) {
   126             if (theErr == WSAEMSGSIZE) {
   162                 /* Spec says the rest of the data will be discarded... */
   127                 /* Spec says the rest of the data will be discarded... */
   163                 n = len;
   128                 n = len;
   164             } else if (theErr == WSAECONNRESET) {
   129             } else if (theErr == WSAECONNRESET) {
   165                 purgeOutstandingICMP(env, this, fd);
   130                 purgeOutstandingICMP(env, clazz, fd);
   166                 if (connected == JNI_FALSE) {
   131                 if (connected == JNI_FALSE) {
   167                     retry = TRUE;
   132                     retry = TRUE;
   168                 } else {
   133                 } else {
   169                     JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", 0);
   134                     JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", 0);
   170                     return IOS_THROWN;
   135                     return IOS_THROWN;
   173                 return IOS_UNAVAILABLE;
   138                 return IOS_UNAVAILABLE;
   174             } else return handleSocketError(env, theErr);
   139             } else return handleSocketError(env, theErr);
   175         }
   140         }
   176     } while (retry);
   141     } while (retry);
   177 
   142 
   178     /*
       
   179      * If the source address and port match the cached address
       
   180      * and port in DatagramChannelImpl then we don't need to
       
   181      * create InetAddress and InetSocketAddress objects.
       
   182      */
       
   183     senderAddr = (*env)->GetObjectField(env, this, dci_senderAddrID);
       
   184     if (senderAddr != NULL) {
       
   185         if (!NET_SockaddrEqualsInetAddress(env, &sa, senderAddr)) {
       
   186             senderAddr = NULL;
       
   187         } else {
       
   188             jint port = (*env)->GetIntField(env, this, dci_senderPortID);
       
   189             if (port != NET_GetPortFromSockaddr(&sa)) {
       
   190                 senderAddr = NULL;
       
   191             }
       
   192         }
       
   193     }
       
   194     if (senderAddr == NULL) {
       
   195         jobject isa = NULL;
       
   196         int port;
       
   197         jobject ia = NET_SockaddrToInetAddress(env, &sa, &port);
       
   198         if (ia != NULL) {
       
   199             isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
       
   200         }
       
   201         CHECK_NULL_RETURN(isa, IOS_THROWN);
       
   202 
       
   203         // update cachedSenderInetAddress/cachedSenderPort
       
   204         (*env)->SetObjectField(env, this, dci_senderAddrID, ia);
       
   205         (*env)->SetIntField(env, this, dci_senderPortID,
       
   206                             NET_GetPortFromSockaddr(&sa));
       
   207         (*env)->SetObjectField(env, this, dci_senderID, isa);
       
   208     }
       
   209     return n;
   143     return n;
   210 }
   144 }
   211 
   145 
   212 JNIEXPORT jint JNICALL
   146 JNIEXPORT jint JNICALL
   213 Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this,
   147 Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jclass clazz,
   214                                           jboolean preferIPv6, jobject fdo,
   148                                           jboolean preferIPv6, jobject fdo,
   215                                           jlong address, jint len,
   149                                           jlong address, jint len,
   216                                           jobject destAddress, jint destPort)
   150                                           jobject destAddress, jint destPort)
   217 {
   151 {
   218     jint fd = fdval(env, fdo);
   152     jint fd = fdval(env, fdo);