35 */ |
35 */ |
36 |
36 |
37 static jfieldID IO_fd_fdID; |
37 static jfieldID IO_fd_fdID; |
38 |
38 |
39 jfieldID psi_fdID; |
39 jfieldID psi_fdID; |
40 jfieldID psi_fd1ID; |
|
41 jfieldID psi_addressID; |
40 jfieldID psi_addressID; |
42 jfieldID psi_portID; |
41 jfieldID psi_portID; |
43 jfieldID psi_localportID; |
42 jfieldID psi_localportID; |
44 jfieldID psi_timeoutID; |
43 jfieldID psi_timeoutID; |
45 jfieldID psi_trafficClassID; |
44 jfieldID psi_trafficClassID; |
46 jfieldID psi_serverSocketID; |
45 jfieldID psi_serverSocketID; |
47 jfieldID psi_lastfdID; |
|
48 |
46 |
49 /* |
47 /* |
50 * the level of the TCP protocol for setsockopt and getsockopt |
48 * the level of the TCP protocol for setsockopt and getsockopt |
51 * we only want to look this up once, from the static initializer |
49 * we only want to look this up once, from the static initializer |
52 * of TwoStacksPlainSocketImpl |
50 * of TwoStacksPlainSocketImpl |
53 */ |
51 */ |
54 static int tcp_level = -1; |
52 static int tcp_level = -1; |
55 |
53 |
56 static int getFD(JNIEnv *env, jobject this) { |
54 static int getFD(JNIEnv *env, jobject this) { |
57 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); |
55 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); |
58 |
|
59 if (fdObj == NULL) { |
|
60 return -1; |
|
61 } |
|
62 return (*env)->GetIntField(env, fdObj, IO_fd_fdID); |
|
63 } |
|
64 |
|
65 static int getFD1(JNIEnv *env, jobject this) { |
|
66 jobject fdObj = (*env)->GetObjectField(env, this, psi_fd1ID); |
|
67 |
56 |
68 if (fdObj == NULL) { |
57 if (fdObj == NULL) { |
69 return -1; |
58 return -1; |
70 } |
59 } |
71 return (*env)->GetIntField(env, fdObj, IO_fd_fdID); |
60 return (*env)->GetIntField(env, fdObj, IO_fd_fdID); |
88 struct protoent *proto = getprotobyname("TCP"); |
77 struct protoent *proto = getprotobyname("TCP"); |
89 tcp_level = (proto == 0 ? IPPROTO_TCP: proto->p_proto); |
78 tcp_level = (proto == 0 ? IPPROTO_TCP: proto->p_proto); |
90 |
79 |
91 psi_fdID = (*env)->GetFieldID(env, cls , "fd", "Ljava/io/FileDescriptor;"); |
80 psi_fdID = (*env)->GetFieldID(env, cls , "fd", "Ljava/io/FileDescriptor;"); |
92 CHECK_NULL(psi_fdID); |
81 CHECK_NULL(psi_fdID); |
93 psi_fd1ID =(*env)->GetFieldID(env, cls , "fd1", "Ljava/io/FileDescriptor;"); |
|
94 CHECK_NULL(psi_fd1ID); |
|
95 psi_addressID = (*env)->GetFieldID(env, cls, "address", |
82 psi_addressID = (*env)->GetFieldID(env, cls, "address", |
96 "Ljava/net/InetAddress;"); |
83 "Ljava/net/InetAddress;"); |
97 CHECK_NULL(psi_addressID); |
84 CHECK_NULL(psi_addressID); |
98 psi_portID = (*env)->GetFieldID(env, cls, "port", "I"); |
85 psi_portID = (*env)->GetFieldID(env, cls, "port", "I"); |
99 CHECK_NULL(psi_portID); |
86 CHECK_NULL(psi_portID); |
100 psi_lastfdID = (*env)->GetFieldID(env, cls, "lastfd", "I"); |
|
101 CHECK_NULL(psi_lastfdID); |
|
102 psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I"); |
87 psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I"); |
103 CHECK_NULL(psi_localportID); |
88 CHECK_NULL(psi_localportID); |
104 psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I"); |
89 psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I"); |
105 CHECK_NULL(psi_timeoutID); |
90 CHECK_NULL(psi_timeoutID); |
106 psi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I"); |
91 psi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I"); |
136 return; |
121 return; |
137 } else { |
122 } else { |
138 /* Set socket attribute so it is not passed to any child process */ |
123 /* Set socket attribute so it is not passed to any child process */ |
139 SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE); |
124 SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE); |
140 (*env)->SetIntField(env, fdObj, IO_fd_fdID, (int)fd); |
125 (*env)->SetIntField(env, fdObj, IO_fd_fdID, (int)fd); |
141 } |
|
142 if (ipv6_available()) { |
|
143 fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); |
|
144 |
|
145 if (IS_NULL(fd1Obj)) { |
|
146 (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); |
|
147 NET_SocketClose(fd); |
|
148 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
|
149 "null fd1 object"); |
|
150 return; |
|
151 } |
|
152 fd1 = socket(AF_INET6, (stream ? SOCK_STREAM: SOCK_DGRAM), 0); |
|
153 if (fd1 == -1) { |
|
154 (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); |
|
155 NET_SocketClose(fd); |
|
156 NET_ThrowCurrent(env, "create"); |
|
157 return; |
|
158 } else { |
|
159 /* Set socket attribute so it is not passed to any child process */ |
|
160 SetHandleInformation((HANDLE)(UINT_PTR)fd1, HANDLE_FLAG_INHERIT, FALSE); |
|
161 (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1); |
|
162 } |
|
163 } else { |
|
164 (*env)->SetObjectField(env, this, psi_fd1ID, NULL); |
|
165 } |
126 } |
166 } |
127 } |
167 |
128 |
168 /* |
129 /* |
169 * inetAddress is the address object passed to the socket connect |
130 * inetAddress is the address object passed to the socket connect |
180 { |
141 { |
181 jint localport = (*env)->GetIntField(env, this, psi_localportID); |
142 jint localport = (*env)->GetIntField(env, this, psi_localportID); |
182 |
143 |
183 /* family and localport are int fields of iaObj */ |
144 /* family and localport are int fields of iaObj */ |
184 int family; |
145 int family; |
185 jint fd = -1, fd1 = -1; |
146 jint fd = -1; |
186 jint len; |
147 jint len; |
187 int ipv6_supported = ipv6_available(); |
148 |
188 |
|
189 /* fd initially points to the IPv4 socket and fd1 to the IPv6 socket |
|
190 * If we want to connect to IPv6 then we swap the two sockets/objects |
|
191 * This way, fd is always the connected socket, and fd1 always gets closed. |
|
192 */ |
|
193 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); |
149 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); |
194 jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); |
|
195 |
150 |
196 SOCKETADDRESS sa; |
151 SOCKETADDRESS sa; |
197 |
152 |
198 /* The result of the connection */ |
153 /* The result of the connection */ |
199 int connect_res; |
154 int connect_res; |
216 JNI_FALSE) != 0) { |
167 JNI_FALSE) != 0) { |
217 return; |
168 return; |
218 } |
169 } |
219 |
170 |
220 family = sa.sa.sa_family; |
171 family = sa.sa.sa_family; |
221 if (family == AF_INET6) { |
172 if (family != AF_INET) { |
222 if (!ipv6_supported) { |
173 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
223 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
174 "Protocol family not supported"); |
224 "Protocol family not supported"); |
175 } |
225 return; |
176 if (fd == -1) { |
226 } else { |
177 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
227 if (fd1 == -1) { |
178 "Destination unreachable"); |
228 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
179 return; |
229 "Destination unreachable"); |
180 } |
230 return; |
|
231 } |
|
232 /* close the v4 socket, and set fd to be the v6 socket */ |
|
233 (*env)->SetObjectField(env, this, psi_fdID, fd1Obj); |
|
234 (*env)->SetObjectField(env, this, psi_fd1ID, NULL); |
|
235 NET_SocketClose(fd); |
|
236 fd = fd1; fdObj = fd1Obj; |
|
237 } |
|
238 } else { |
|
239 if (fd1 != -1) { |
|
240 (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1); |
|
241 NET_SocketClose(fd1); |
|
242 } |
|
243 if (fd == -1) { |
|
244 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
|
245 "Destination unreachable"); |
|
246 return; |
|
247 } |
|
248 } |
|
249 (*env)->SetObjectField(env, this, psi_fd1ID, NULL); |
|
250 |
181 |
251 if (timeout <= 0) { |
182 if (timeout <= 0) { |
252 connect_res = connect(fd, &sa.sa, sizeof(SOCKETADDRESS)); |
183 connect_res = connect(fd, &sa.sa, sizeof(SOCKETADDRESS)); |
253 if (connect_res == SOCKET_ERROR) { |
184 if (connect_res == SOCKET_ERROR) { |
254 connect_res = WSAGetLastError(); |
185 connect_res = WSAGetLastError(); |
386 Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this, |
317 Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this, |
387 jobject iaObj, jint localport, |
318 jobject iaObj, jint localport, |
388 jboolean exclBind) { |
319 jboolean exclBind) { |
389 |
320 |
390 /* fdObj is the FileDescriptor field on this */ |
321 /* fdObj is the FileDescriptor field on this */ |
391 jobject fdObj, fd1Obj; |
322 jobject fdObj; |
392 /* fd is an int field on fdObj */ |
323 /* fd is an int field on fdObj */ |
393 int fd, fd1 = -1, len = 0; |
324 int fd, len = 0; |
394 int ipv6_supported = ipv6_available(); |
|
395 |
325 |
396 /* family is an int field of iaObj */ |
326 /* family is an int field of iaObj */ |
397 int family; |
327 int family; |
398 int rv; |
328 int rv; |
399 |
329 |
400 SOCKETADDRESS sa; |
330 SOCKETADDRESS sa; |
401 |
331 |
402 fdObj = (*env)->GetObjectField(env, this, psi_fdID); |
332 fdObj = (*env)->GetObjectField(env, this, psi_fdID); |
403 fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); |
|
404 |
333 |
405 family = getInetAddress_family(env, iaObj); |
334 family = getInetAddress_family(env, iaObj); |
406 |
335 |
407 if (family == java_net_InetAddress_IPv6 && !ipv6_supported) { |
336 if (family != java_net_InetAddress_IPv4) { |
408 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
337 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
409 "Protocol family not supported"); |
338 "Protocol family not supported"); |
410 return; |
339 return; |
411 } |
340 } |
412 |
341 |
413 if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { |
342 if (IS_NULL(fdObj)) { |
414 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
343 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
415 "Socket closed"); |
344 "Socket closed"); |
416 return; |
345 return; |
417 } else { |
346 } else { |
418 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); |
347 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); |
419 if (ipv6_supported) { |
|
420 fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); |
|
421 } |
|
422 } |
348 } |
423 if (IS_NULL(iaObj)) { |
349 if (IS_NULL(iaObj)) { |
424 JNU_ThrowNullPointerException(env, "inet address argument"); |
350 JNU_ThrowNullPointerException(env, "inet address argument"); |
425 return; |
351 return; |
426 } |
352 } |
427 |
353 |
428 if (NET_InetAddressToSockaddr(env, iaObj, localport, &sa, &len, |
354 if (NET_InetAddressToSockaddr(env, iaObj, localport, &sa, &len, |
429 JNI_FALSE) != 0) { |
355 JNI_FALSE) != 0) { |
430 return; |
356 return; |
431 } |
357 } |
432 if (ipv6_supported) { |
358 rv = NET_WinBind(fd, &sa, len, exclBind); |
433 struct ipv6bind v6bind; |
|
434 v6bind.addr = &sa.sa; |
|
435 v6bind.ipv4_fd = fd; |
|
436 v6bind.ipv6_fd = fd1; |
|
437 rv = NET_BindV6(&v6bind, exclBind); |
|
438 if (rv != -1) { |
|
439 /* check if the fds have changed */ |
|
440 if (v6bind.ipv4_fd != fd) { |
|
441 fd = v6bind.ipv4_fd; |
|
442 if (fd == -1) { |
|
443 /* socket is closed. */ |
|
444 (*env)->SetObjectField(env, this, psi_fdID, NULL); |
|
445 } else { |
|
446 /* socket was re-created */ |
|
447 (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd); |
|
448 } |
|
449 } |
|
450 if (v6bind.ipv6_fd != fd1) { |
|
451 fd1 = v6bind.ipv6_fd; |
|
452 if (fd1 == -1) { |
|
453 /* socket is closed. */ |
|
454 (*env)->SetObjectField(env, this, psi_fd1ID, NULL); |
|
455 } else { |
|
456 /* socket was re-created */ |
|
457 (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1); |
|
458 } |
|
459 } |
|
460 } else { |
|
461 /* NET_BindV6() closes both sockets upon a failure */ |
|
462 (*env)->SetObjectField(env, this, psi_fdID, NULL); |
|
463 (*env)->SetObjectField(env, this, psi_fd1ID, NULL); |
|
464 } |
|
465 } else { |
|
466 rv = NET_WinBind(fd, &sa, len, exclBind); |
|
467 } |
|
468 |
359 |
469 if (rv == -1) { |
360 if (rv == -1) { |
470 NET_ThrowCurrent(env, "NET_Bind"); |
361 NET_ThrowCurrent(env, "NET_Bind"); |
471 return; |
362 return; |
472 } |
363 } |
503 Java_java_net_TwoStacksPlainSocketImpl_socketListen |
394 Java_java_net_TwoStacksPlainSocketImpl_socketListen |
504 (JNIEnv *env, jobject this, jint count) |
395 (JNIEnv *env, jobject this, jint count) |
505 { |
396 { |
506 /* this FileDescriptor fd field */ |
397 /* this FileDescriptor fd field */ |
507 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); |
398 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); |
508 jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); |
|
509 jobject address; |
399 jobject address; |
510 /* fdObj's int fd field */ |
400 /* fdObj's int fd field */ |
511 int fd = INVALID_SOCKET, fd1 = INVALID_SOCKET; |
401 int fd = INVALID_SOCKET; |
512 SOCKETADDRESS addr; |
402 SOCKETADDRESS addr; |
513 int addrlen; |
403 int addrlen; |
514 |
404 |
515 if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { |
405 if (IS_NULL(fdObj)) { |
516 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
406 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
517 "socket closed"); |
407 "socket closed"); |
518 return; |
408 return; |
519 } |
409 } |
520 |
410 |
521 if (!IS_NULL(fdObj)) { |
411 if (!IS_NULL(fdObj)) { |
522 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); |
412 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); |
523 } |
413 } |
524 /* Listen on V4 if address type is v4 or if v6 and address is ::0. |
|
525 * Listen on V6 if address type is v6 or if v4 and address is 0.0.0.0. |
|
526 * In cases, where we listen on one space only, we close the other socket. |
|
527 */ |
|
528 address = (*env)->GetObjectField(env, this, psi_addressID); |
414 address = (*env)->GetObjectField(env, this, psi_addressID); |
529 if (IS_NULL(address)) { |
415 if (IS_NULL(address)) { |
530 JNU_ThrowNullPointerException(env, "socket address"); |
416 JNU_ThrowNullPointerException(env, "socket address"); |
531 return; |
417 return; |
532 } |
418 } |
533 if (NET_InetAddressToSockaddr(env, address, 0, &addr, &addrlen, |
419 if (NET_InetAddressToSockaddr(env, address, 0, &addr, &addrlen, |
534 JNI_FALSE) != 0) { |
420 JNI_FALSE) != 0) { |
535 return; |
421 return; |
536 } |
422 } |
537 |
423 |
538 if (addr.sa.sa_family == AF_INET || IN6ADDR_ISANY(&addr.sa6)) { |
424 if (addr.sa.sa_family == AF_INET) { |
539 /* listen on v4 */ |
425 /* listen on v4 */ |
540 if (listen(fd, count) == -1) { |
426 if (listen(fd, count) == -1) { |
541 NET_ThrowCurrent(env, "listen failed"); |
427 NET_ThrowCurrent(env, "listen failed"); |
542 } |
428 } |
543 } else { |
429 } else { |
544 NET_SocketClose (fd); |
430 NET_SocketClose(fd); |
545 (*env)->SetObjectField(env, this, psi_fdID, NULL); |
431 (*env)->SetObjectField(env, this, psi_fdID, NULL); |
546 } |
|
547 if (ipv6_available() && !IS_NULL(fd1Obj)) { |
|
548 fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); |
|
549 if (addr.sa.sa_family == AF_INET6 || addr.sa4.sin_addr.s_addr == INADDR_ANY) { |
|
550 /* listen on v6 */ |
|
551 if (listen(fd1, count) == -1) { |
|
552 NET_ThrowCurrent(env, "listen failed"); |
|
553 } |
|
554 } else { |
|
555 NET_SocketClose (fd1); |
|
556 (*env)->SetObjectField(env, this, psi_fd1ID, NULL); |
|
557 } |
|
558 } |
432 } |
559 } |
433 } |
560 |
434 |
561 /* |
435 /* |
562 * Class: java_net_TwoStacksPlainSocketImpl |
436 * Class: java_net_TwoStacksPlainSocketImpl |
569 { |
443 { |
570 /* fields on this */ |
444 /* fields on this */ |
571 jint port; |
445 jint port; |
572 jint timeout = (*env)->GetIntField(env, this, psi_timeoutID); |
446 jint timeout = (*env)->GetIntField(env, this, psi_timeoutID); |
573 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); |
447 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); |
574 jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); |
|
575 |
448 |
576 /* the FileDescriptor field on socket */ |
449 /* the FileDescriptor field on socket */ |
577 jobject socketFdObj; |
450 jobject socketFdObj; |
578 |
451 |
579 /* cache the Inet4/6Address classes */ |
452 /* cache the Inet4 class */ |
580 static jclass inet4Cls; |
453 static jclass inet4Cls; |
581 static jclass inet6Cls; |
|
582 |
454 |
583 /* the InetAddress field on socket */ |
455 /* the InetAddress field on socket */ |
584 jobject socketAddressObj; |
456 jobject socketAddressObj; |
585 |
457 |
586 /* the fd int field on fdObj */ |
458 /* the fd int field on fdObj */ |
587 jint fd=-1, fd1=-1; |
459 jint fd=-1; |
588 |
460 |
589 SOCKETADDRESS sa; |
461 SOCKETADDRESS sa; |
590 jint len; |
462 jint len; |
591 |
463 int ret; |
592 if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { |
464 |
|
465 if (IS_NULL(fdObj)) { |
593 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
466 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
594 "Socket closed"); |
467 "Socket closed"); |
595 return; |
468 return; |
596 } |
469 } |
597 if (!IS_NULL(fdObj)) { |
470 |
598 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); |
471 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); |
599 } |
472 |
600 if (!IS_NULL(fd1Obj)) { |
|
601 fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); |
|
602 } |
|
603 if (IS_NULL(socket)) { |
473 if (IS_NULL(socket)) { |
604 JNU_ThrowNullPointerException(env, "socket is null"); |
474 JNU_ThrowNullPointerException(env, "socket is null"); |
605 return; |
475 return; |
606 } else { |
476 } else { |
607 socketFdObj = (*env)->GetObjectField(env, socket, psi_fdID); |
477 socketFdObj = (*env)->GetObjectField(env, socket, psi_fdID); |
609 } |
479 } |
610 if ((IS_NULL(socketAddressObj)) || (IS_NULL(socketFdObj))) { |
480 if ((IS_NULL(socketAddressObj)) || (IS_NULL(socketFdObj))) { |
611 JNU_ThrowNullPointerException(env, "socket address or fd obj"); |
481 JNU_ThrowNullPointerException(env, "socket address or fd obj"); |
612 return; |
482 return; |
613 } |
483 } |
614 if (fd != -1 && fd1 != -1) { |
484 |
615 fd_set rfds; |
485 len = sizeof(struct sockaddr_in); |
616 struct timeval t, *tP=&t; |
486 if (timeout) { |
617 int lastfd, res, fd2; |
487 ret = NET_Timeout(fd, timeout); |
618 FD_ZERO(&rfds); |
488 if (ret == 0) { |
619 FD_SET(fd,&rfds); |
|
620 FD_SET(fd1,&rfds); |
|
621 if (timeout) { |
|
622 t.tv_sec = timeout/1000; |
|
623 t.tv_usec = (timeout%1000)*1000; |
|
624 } else { |
|
625 tP = NULL; |
|
626 } |
|
627 res = select (fd, &rfds, NULL, NULL, tP); |
|
628 if (res == 0) { |
|
629 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", |
489 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", |
630 "Accept timed out"); |
490 "Accept timed out"); |
631 return; |
491 return; |
632 } else if (res == 1) { |
492 } else if (ret == -1) { |
633 fd2 = FD_ISSET(fd, &rfds)? fd: fd1; |
493 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); |
634 } else if (res == 2) { |
494 /* REMIND: SOCKET CLOSED PROBLEM */ |
635 /* avoid starvation */ |
495 /* NET_ThrowCurrent(env, "Accept failed"); */ |
636 lastfd = (*env)->GetIntField(env, this, psi_lastfdID); |
|
637 if (lastfd != -1) { |
|
638 fd2 = lastfd==fd? fd1: fd; |
|
639 } else { |
|
640 fd2 = fd; |
|
641 } |
|
642 (*env)->SetIntField(env, this, psi_lastfdID, fd2); |
|
643 } else { |
|
644 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
|
645 "select failed"); |
|
646 return; |
496 return; |
647 } |
497 } else if (ret == -2) { |
648 if (fd2 == fd) { /* v4 */ |
498 JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", |
649 len = sizeof(struct sockaddr_in); |
499 "operation interrupted"); |
650 } else { |
500 return; |
651 len = sizeof(struct sockaddr_in6); |
501 } |
652 } |
502 } |
653 fd = fd2; |
503 |
654 } else { |
|
655 int ret; |
|
656 if (fd1 != -1) { |
|
657 fd = fd1; |
|
658 len = sizeof(struct sockaddr_in6); |
|
659 } else { |
|
660 len = sizeof(struct sockaddr_in); |
|
661 } |
|
662 if (timeout) { |
|
663 ret = NET_Timeout(fd, timeout); |
|
664 if (ret == 0) { |
|
665 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", |
|
666 "Accept timed out"); |
|
667 return; |
|
668 } else if (ret == -1) { |
|
669 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); |
|
670 /* REMIND: SOCKET CLOSED PROBLEM */ |
|
671 /* NET_ThrowCurrent(env, "Accept failed"); */ |
|
672 return; |
|
673 } else if (ret == -2) { |
|
674 JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", |
|
675 "operation interrupted"); |
|
676 return; |
|
677 } |
|
678 } |
|
679 } |
|
680 fd = accept(fd, &sa.sa, &len); |
504 fd = accept(fd, &sa.sa, &len); |
681 if (fd < 0) { |
505 if (fd < 0) { |
682 /* REMIND: SOCKET CLOSED PROBLEM */ |
506 /* REMIND: SOCKET CLOSED PROBLEM */ |
683 if (fd == -2) { |
507 if (fd == -2) { |
684 JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", |
508 JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", |
690 return; |
514 return; |
691 } |
515 } |
692 SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, 0); |
516 SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, 0); |
693 (*env)->SetIntField(env, socketFdObj, IO_fd_fdID, fd); |
517 (*env)->SetIntField(env, socketFdObj, IO_fd_fdID, fd); |
694 |
518 |
695 if (sa.sa.sa_family == AF_INET) { |
519 if (sa.sa.sa_family != AF_INET) { |
696 if (inet4Cls == NULL) { |
520 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
697 jclass c = (*env)->FindClass(env, "java/net/Inet4Address"); |
521 "Protocol family not supported"); |
698 if (c != NULL) { |
522 return; |
699 inet4Cls = (*env)->NewGlobalRef(env, c); |
523 } |
700 (*env)->DeleteLocalRef(env, c); |
524 |
701 } |
525 if (inet4Cls == NULL) { |
702 } |
526 jclass c = (*env)->FindClass(env, "java/net/Inet4Address"); |
703 |
527 if (c != NULL) { |
|
528 inet4Cls = (*env)->NewGlobalRef(env, c); |
|
529 (*env)->DeleteLocalRef(env, c); |
|
530 } |
|
531 } |
|
532 |
|
533 /* |
|
534 * fill up the remote peer port and address in the new socket structure |
|
535 */ |
|
536 if (inet4Cls != NULL) { |
|
537 socketAddressObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID); |
|
538 } else { |
|
539 socketAddressObj = NULL; |
|
540 } |
|
541 if (socketAddressObj == NULL) { |
704 /* |
542 /* |
705 * fill up the remote peer port and address in the new socket structure |
543 * FindClass or NewObject failed so close connection and |
|
544 * exit (there will be a pending exception). |
706 */ |
545 */ |
707 if (inet4Cls != NULL) { |
546 NET_SocketClose(fd); |
708 socketAddressObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID); |
547 return; |
709 } else { |
548 } |
710 socketAddressObj = NULL; |
549 |
711 } |
550 setInetAddress_addr(env, socketAddressObj, ntohl(sa.sa4.sin_addr.s_addr)); |
712 if (socketAddressObj == NULL) { |
551 setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv4); |
713 /* |
552 (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj); |
714 * FindClass or NewObject failed so close connection and |
|
715 * exist (there will be a pending exception). |
|
716 */ |
|
717 NET_SocketClose(fd); |
|
718 return; |
|
719 } |
|
720 |
|
721 setInetAddress_addr(env, socketAddressObj, ntohl(sa.sa4.sin_addr.s_addr)); |
|
722 setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv4); |
|
723 (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj); |
|
724 } else { |
|
725 /* AF_INET6 -> Inet6Address */ |
|
726 if (inet6Cls == 0) { |
|
727 jclass c = (*env)->FindClass(env, "java/net/Inet6Address"); |
|
728 if (c != NULL) { |
|
729 inet6Cls = (*env)->NewGlobalRef(env, c); |
|
730 (*env)->DeleteLocalRef(env, c); |
|
731 } |
|
732 } |
|
733 |
|
734 if (inet6Cls != NULL) { |
|
735 socketAddressObj = (*env)->NewObject(env, inet6Cls, ia6_ctrID); |
|
736 } else { |
|
737 socketAddressObj = NULL; |
|
738 } |
|
739 if (socketAddressObj == NULL) { |
|
740 /* |
|
741 * FindClass or NewObject failed so close connection and |
|
742 * exist (there will be a pending exception). |
|
743 */ |
|
744 NET_SocketClose(fd); |
|
745 return; |
|
746 } |
|
747 setInet6Address_ipaddress(env, socketAddressObj, (char *)&sa.sa6.sin6_addr); |
|
748 setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv6); |
|
749 setInet6Address_scopeid(env, socketAddressObj, sa.sa6.sin6_scope_id); |
|
750 |
|
751 } |
|
752 /* fields common to AF_INET and AF_INET6 */ |
|
753 |
|
754 port = ntohs ((u_short)GET_PORT(&sa)); |
553 port = ntohs ((u_short)GET_PORT(&sa)); |
755 (*env)->SetIntField(env, socket, psi_portID, (int)port); |
554 (*env)->SetIntField(env, socket, psi_portID, (int)port); |
756 port = (*env)->GetIntField(env, this, psi_localportID); |
555 port = (*env)->GetIntField(env, this, psi_localportID); |
757 (*env)->SetIntField(env, socket, psi_localportID, port); |
556 (*env)->SetIntField(env, socket, psi_localportID, port); |
758 (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj); |
557 (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj); |
793 JNIEXPORT void JNICALL |
592 JNIEXPORT void JNICALL |
794 Java_java_net_TwoStacksPlainSocketImpl_socketClose0(JNIEnv *env, jobject this, |
593 Java_java_net_TwoStacksPlainSocketImpl_socketClose0(JNIEnv *env, jobject this, |
795 jboolean useDeferredClose) { |
594 jboolean useDeferredClose) { |
796 |
595 |
797 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); |
596 jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); |
798 jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); |
597 jint fd=-1; |
799 jint fd=-1, fd1=-1; |
598 |
800 |
599 if (IS_NULL(fdObj)) { |
801 if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { |
|
802 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
600 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", |
803 "socket already closed"); |
601 "socket already closed"); |
804 return; |
602 return; |
805 } |
603 } |
806 if (!IS_NULL(fdObj)) { |
604 if (!IS_NULL(fdObj)) { |
807 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); |
605 fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); |
808 } |
|
809 if (!IS_NULL(fd1Obj)) { |
|
810 fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); |
|
811 } |
606 } |
812 if (fd != -1) { |
607 if (fd != -1) { |
813 (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); |
608 (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); |
814 NET_SocketClose(fd); |
609 NET_SocketClose(fd); |
815 } |
|
816 if (fd1 != -1) { |
|
817 (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1); |
|
818 NET_SocketClose(fd1); |
|
819 } |
610 } |
820 } |
611 } |
821 |
612 |
822 /* |
613 /* |
823 * Socket options for plainsocketImpl |
614 * Socket options for plainsocketImpl |
996 */ |
774 */ |
997 JNIEXPORT jint JNICALL |
775 JNIEXPORT jint JNICALL |
998 Java_java_net_TwoStacksPlainSocketImpl_socketGetOption |
776 Java_java_net_TwoStacksPlainSocketImpl_socketGetOption |
999 (JNIEnv *env, jobject this, jint opt, jobject iaContainerObj) |
777 (JNIEnv *env, jobject this, jint opt, jobject iaContainerObj) |
1000 { |
778 { |
1001 int fd, fd1; |
779 int fd; |
1002 int level = 0, optname = 0, optlen = 0; |
780 int level = 0, optname = 0, optlen = 0; |
1003 union { |
781 union { |
1004 int i; |
782 int i; |
1005 struct linger ling; |
783 struct linger ling; |
1006 } optval; |
784 } optval; |
1007 |
785 |
1008 /* |
786 /* |
1009 * Get SOCKET and check it hasn't been closed |
787 * Get SOCKET and check it hasn't been closed |
1010 */ |
788 */ |
1011 fd = getFD(env, this); |
789 fd = getFD(env, this); |
1012 fd1 = getFD1(env, this); |
|
1013 memset((char *)&optval, 0, sizeof(optval)); |
790 memset((char *)&optval, 0, sizeof(optval)); |
1014 |
791 |
1015 if (fd < 0 && fd1 < 0) { |
792 if (fd < 0) { |
1016 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); |
793 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); |
1017 return -1; |
794 return -1; |
1018 } |
795 } |
1019 if (fd < 0) { |
|
1020 fd = fd1; |
|
1021 } |
|
1022 |
|
1023 /* For IPv6, we assume both sockets have the same setting always */ |
|
1024 |
796 |
1025 /* |
797 /* |
1026 * SO_BINDADDR isn't a socket option |
798 * SO_BINDADDR isn't a socket option |
1027 */ |
799 */ |
1028 if (opt == java_net_SocketOptions_SO_BINDADDR) { |
800 if (opt == java_net_SocketOptions_SO_BINDADDR) { |