src/windows/native/java/net/DualStackPlainDatagramSocketImpl.c

Print this page




  38 static jboolean purgeOutstandingICMP(JNIEnv *env, jint fd)
  39 {
  40     jboolean got_icmp = JNI_FALSE;
  41     char buf[1];
  42     fd_set tbl;
  43     struct timeval t = { 0, 0 };
  44     SOCKETADDRESS rmtaddr;
  45     int addrlen = sizeof(rmtaddr);
  46 
  47     /*
  48      * Peek at the queue to see if there is an ICMP port unreachable. If there
  49      * is then receive it.
  50      */
  51     FD_ZERO(&tbl);
  52     FD_SET(fd, &tbl);
  53     while(1) {
  54         if (select(/*ignored*/fd+1, &tbl, 0, 0, &t) <= 0) {
  55             break;
  56         }
  57         if (recvfrom(fd, buf, 1, MSG_PEEK,
  58                          (struct sockaddr *)&rmtaddr, &addrlen) != JVM_IO_ERR) {
  59             break;
  60         }
  61         if (WSAGetLastError() != WSAECONNRESET) {
  62             /* some other error - we don't care here */
  63             break;
  64         }
  65 
  66         recvfrom(fd, buf, 1, 0,  (struct sockaddr *)&rmtaddr, &addrlen);
  67         got_icmp = JNI_TRUE;
  68     }
  69 
  70     return got_icmp;
  71 }
  72 
  73 /*
  74  * Class:     java_net_DualStackPlainDatagramSocketImpl
  75  * Method:    socketCreate
  76  * Signature: (Z)I
  77  */
  78 JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketCreate


 184  * Method:    socketClose
 185  * Signature: (I)V
 186  */
 187 JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketClose
 188   (JNIEnv *env, jclass clazz , jint fd) {
 189     NET_SocketClose(fd);
 190 }
 191 
 192 
 193 /*
 194  * Class:     java_net_DualStackPlainDatagramSocketImpl
 195  * Method:    socketLocalPort
 196  * Signature: (I)I
 197  */
 198 JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketLocalPort
 199   (JNIEnv *env, jclass clazz, jint fd) {
 200     SOCKETADDRESS sa;
 201     int len = sizeof(sa);
 202 
 203     if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) {
 204         NET_ThrowNew(env, WSAGetLastError(), "JVM_GetSockName");
 205         return -1;
 206     }
 207     return (int) ntohs((u_short)GET_PORT(&sa));
 208 }
 209 
 210 /*
 211  * Class:     java_net_DualStackPlainDatagramSocketImpl
 212  * Method:    socketLocalAddress
 213  * Signature: (I)Ljava/lang/Object;
 214  */
 215 JNIEXPORT jobject JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketLocalAddress
 216   (JNIEnv *env , jclass clazz, jint fd) {
 217     SOCKETADDRESS sa;
 218     int len = sizeof(sa);
 219     jobject iaObj;
 220     int port;
 221 
 222     if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) {
 223         NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
 224         return NULL;


 267         if (!fullPacket) {
 268             JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
 269             return -1;
 270         }
 271     } else {
 272         fullPacket = &(BUF[0]);
 273     }
 274 
 275     do {
 276         retry = FALSE;
 277 
 278         if (timeout) {
 279             if (prevTime == 0) {
 280                 prevTime = JVM_CurrentTimeMillis(env, 0);
 281             }
 282             rv = NET_Timeout(fd, timeout);
 283             if (rv <= 0) {
 284                 if (rv == 0) {
 285                     JNU_ThrowByName(env,JNU_JAVANETPKG "SocketTimeoutException",
 286                                     "Receive timed out");
 287                 } else if (rv == JVM_IO_ERR) {
 288                     JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 289                                     "Socket closed");
 290                 } else if (rv == JVM_IO_INTR) {
 291                     JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
 292                                     "operation interrupted");
 293                 }
 294                 if (packetBufferLen > MAX_BUFFER_LEN) {
 295                     free(fullPacket);
 296                 }
 297                 return -1;
 298             }
 299         }
 300 
 301         /* receive the packet */
 302         rv = recvfrom(fd, fullPacket, packetBufferLen, flags,
 303                     (struct sockaddr *)&sa, &sa_len);
 304 
 305         if (rv == SOCKET_ERROR && (WSAGetLastError() == WSAECONNRESET)) {
 306             /* An icmp port unreachable - we must receive this as Windows
 307              * does not reset the state of the socket until this has been
 308              * received.
 309              */
 310             purgeOutstandingICMP(env, fd);
 311 
 312             if (connected) {


 392     }
 393     return port;
 394 }
 395 
 396 /*
 397  * Class:     java_net_DualStackPlainDatagramSocketImpl
 398  * Method:    socketSend
 399  * Signature: (I[BIILjava/net/InetAddress;IZ)V
 400  */
 401 JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSend
 402   (JNIEnv *env, jclass clazz, jint fd, jbyteArray data, jint offset, jint length,
 403      jobject iaObj, jint port, jboolean connected) {
 404     SOCKETADDRESS sa;
 405     int sa_len = sizeof(sa);
 406     SOCKETADDRESS *sap = &sa;
 407     char BUF[MAX_BUFFER_LEN];
 408     char *fullPacket;
 409     int rv;
 410 
 411     if (connected) {
 412         sap = 0; /* arg to JVM_Sendto () null in this case */
 413         sa_len = 0;
 414     } else {
 415         if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
 416                                        &sa_len, JNI_TRUE) != 0) {
 417             return;
 418         }
 419     }
 420 
 421     if (length > MAX_BUFFER_LEN) {
 422         /* Note: the buffer needn't be greater than 65,536 (0xFFFF)
 423          * the max size of an IP packet. Anything bigger is truncated anyway.
 424          */
 425         if (length > MAX_PACKET_LEN) {
 426             length = MAX_PACKET_LEN;
 427         }
 428         fullPacket = (char *)malloc(length);
 429         if (!fullPacket) {
 430             JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
 431             return;
 432         }
 433     } else {
 434         fullPacket = &(BUF[0]);
 435     }
 436 
 437     (*env)->GetByteArrayRegion(env, data, offset, length,
 438                                (jbyte *)fullPacket);
 439     rv = sendto(fd, fullPacket, length, 0, (struct sockaddr *)sap, sa_len);
 440     if (rv == SOCKET_ERROR) {
 441         if (rv == JVM_IO_ERR) {
 442             NET_ThrowNew(env, WSAGetLastError(), "Datagram send failed");
 443         } else if (rv == JVM_IO_INTR) {
 444             JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
 445                             "operation interrupted");
 446         }
 447     }
 448 
 449     if (length > MAX_BUFFER_LEN) {
 450         free(fullPacket);
 451     }
 452 }
 453 
 454 /*
 455  * Class:     java_net_DualStackPlainDatagramSocketImpl
 456  * Method:    socketSetIntOption
 457  * Signature: (III)V
 458  */
 459 JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSetIntOption
 460   (JNIEnv *env, jclass clazz, jint fd , jint cmd, jint value) {
 461     int level, opt;
 462 
 463     if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
 464         JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
 465                                      "Invalid option");




  38 static jboolean purgeOutstandingICMP(JNIEnv *env, jint fd)
  39 {
  40     jboolean got_icmp = JNI_FALSE;
  41     char buf[1];
  42     fd_set tbl;
  43     struct timeval t = { 0, 0 };
  44     SOCKETADDRESS rmtaddr;
  45     int addrlen = sizeof(rmtaddr);
  46 
  47     /*
  48      * Peek at the queue to see if there is an ICMP port unreachable. If there
  49      * is then receive it.
  50      */
  51     FD_ZERO(&tbl);
  52     FD_SET(fd, &tbl);
  53     while(1) {
  54         if (select(/*ignored*/fd+1, &tbl, 0, 0, &t) <= 0) {
  55             break;
  56         }
  57         if (recvfrom(fd, buf, 1, MSG_PEEK,
  58                          (struct sockaddr *)&rmtaddr, &addrlen) != SOCKET_ERROR) {
  59             break;
  60         }
  61         if (WSAGetLastError() != WSAECONNRESET) {
  62             /* some other error - we don't care here */
  63             break;
  64         }
  65 
  66         recvfrom(fd, buf, 1, 0,  (struct sockaddr *)&rmtaddr, &addrlen);
  67         got_icmp = JNI_TRUE;
  68     }
  69 
  70     return got_icmp;
  71 }
  72 
  73 /*
  74  * Class:     java_net_DualStackPlainDatagramSocketImpl
  75  * Method:    socketCreate
  76  * Signature: (Z)I
  77  */
  78 JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketCreate


 184  * Method:    socketClose
 185  * Signature: (I)V
 186  */
 187 JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketClose
 188   (JNIEnv *env, jclass clazz , jint fd) {
 189     NET_SocketClose(fd);
 190 }
 191 
 192 
 193 /*
 194  * Class:     java_net_DualStackPlainDatagramSocketImpl
 195  * Method:    socketLocalPort
 196  * Signature: (I)I
 197  */
 198 JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketLocalPort
 199   (JNIEnv *env, jclass clazz, jint fd) {
 200     SOCKETADDRESS sa;
 201     int len = sizeof(sa);
 202 
 203     if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) {
 204         NET_ThrowNew(env, WSAGetLastError(), "getsockname");
 205         return -1;
 206     }
 207     return (int) ntohs((u_short)GET_PORT(&sa));
 208 }
 209 
 210 /*
 211  * Class:     java_net_DualStackPlainDatagramSocketImpl
 212  * Method:    socketLocalAddress
 213  * Signature: (I)Ljava/lang/Object;
 214  */
 215 JNIEXPORT jobject JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketLocalAddress
 216   (JNIEnv *env , jclass clazz, jint fd) {
 217     SOCKETADDRESS sa;
 218     int len = sizeof(sa);
 219     jobject iaObj;
 220     int port;
 221 
 222     if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) {
 223         NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
 224         return NULL;


 267         if (!fullPacket) {
 268             JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
 269             return -1;
 270         }
 271     } else {
 272         fullPacket = &(BUF[0]);
 273     }
 274 
 275     do {
 276         retry = FALSE;
 277 
 278         if (timeout) {
 279             if (prevTime == 0) {
 280                 prevTime = JVM_CurrentTimeMillis(env, 0);
 281             }
 282             rv = NET_Timeout(fd, timeout);
 283             if (rv <= 0) {
 284                 if (rv == 0) {
 285                     JNU_ThrowByName(env,JNU_JAVANETPKG "SocketTimeoutException",
 286                                     "Receive timed out");
 287                 } else if (rv == -1) {
 288                     JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
 289                                     "Socket closed");



 290                 }
 291                 if (packetBufferLen > MAX_BUFFER_LEN) {
 292                     free(fullPacket);
 293                 }
 294                 return -1;
 295             }
 296         }
 297 
 298         /* receive the packet */
 299         rv = recvfrom(fd, fullPacket, packetBufferLen, flags,
 300                     (struct sockaddr *)&sa, &sa_len);
 301 
 302         if (rv == SOCKET_ERROR && (WSAGetLastError() == WSAECONNRESET)) {
 303             /* An icmp port unreachable - we must receive this as Windows
 304              * does not reset the state of the socket until this has been
 305              * received.
 306              */
 307             purgeOutstandingICMP(env, fd);
 308 
 309             if (connected) {


 389     }
 390     return port;
 391 }
 392 
 393 /*
 394  * Class:     java_net_DualStackPlainDatagramSocketImpl
 395  * Method:    socketSend
 396  * Signature: (I[BIILjava/net/InetAddress;IZ)V
 397  */
 398 JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSend
 399   (JNIEnv *env, jclass clazz, jint fd, jbyteArray data, jint offset, jint length,
 400      jobject iaObj, jint port, jboolean connected) {
 401     SOCKETADDRESS sa;
 402     int sa_len = sizeof(sa);
 403     SOCKETADDRESS *sap = &sa;
 404     char BUF[MAX_BUFFER_LEN];
 405     char *fullPacket;
 406     int rv;
 407 
 408     if (connected) {
 409         sap = 0; /* arg to sendto () null in this case */
 410         sa_len = 0;
 411     } else {
 412         if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
 413                                        &sa_len, JNI_TRUE) != 0) {
 414             return;
 415         }
 416     }
 417 
 418     if (length > MAX_BUFFER_LEN) {
 419         /* Note: the buffer needn't be greater than 65,536 (0xFFFF)
 420          * the max size of an IP packet. Anything bigger is truncated anyway.
 421          */
 422         if (length > MAX_PACKET_LEN) {
 423             length = MAX_PACKET_LEN;
 424         }
 425         fullPacket = (char *)malloc(length);
 426         if (!fullPacket) {
 427             JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
 428             return;
 429         }
 430     } else {
 431         fullPacket = &(BUF[0]);
 432     }
 433 
 434     (*env)->GetByteArrayRegion(env, data, offset, length,
 435                                (jbyte *)fullPacket);
 436     rv = sendto(fd, fullPacket, length, 0, (struct sockaddr *)sap, sa_len);
 437     if (rv == SOCKET_ERROR) {
 438         if (rv == -1) {
 439             NET_ThrowNew(env, WSAGetLastError(), "Datagram send failed");



 440         }
 441     }
 442 
 443     if (length > MAX_BUFFER_LEN) {
 444         free(fullPacket);
 445     }
 446 }
 447 
 448 /*
 449  * Class:     java_net_DualStackPlainDatagramSocketImpl
 450  * Method:    socketSetIntOption
 451  * Signature: (III)V
 452  */
 453 JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSetIntOption
 454   (JNIEnv *env, jclass clazz, jint fd , jint cmd, jint value) {
 455     int level, opt;
 456 
 457     if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
 458         JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
 459                                      "Invalid option");