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");
|