Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/src/solaris/native/java/net/Inet4AddressImpl.c
+++ new/src/solaris/native/java/net/Inet4AddressImpl.c
1 1 /*
2 2 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation. Oracle designates this
8 8 * particular file as subject to the "Classpath" exception as provided
9 9 * by Oracle in the LICENSE file that accompanied this code.
10 10 *
11 11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 14 * version 2 for more details (a copy is included in the LICENSE file that
15 15 * accompanied this code).
16 16 *
17 17 * You should have received a copy of the GNU General Public License version
18 18 * 2 along with this work; if not, write to the Free Software Foundation,
19 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 20 *
21 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 22 * or visit www.oracle.com if you need additional information or have any
23 23 * questions.
24 24 */
25 25
26 26 #include <errno.h>
27 27 #include <sys/time.h>
28 28 #include <sys/types.h>
29 29 #include <sys/socket.h>
30 30 #include <netinet/in_systm.h>
31 31 #include <netinet/in.h>
32 32 #include <netinet/ip.h>
33 33 #include <netinet/ip_icmp.h>
34 34 #include <netdb.h>
35 35 #include <string.h>
36 36 #include <stdlib.h>
37 37 #include <ctype.h>
38 38
39 39 #include "jvm.h"
40 40 #include "jni_util.h"
41 41 #include "net_util.h"
42 42
43 43 #include "java_net_Inet4AddressImpl.h"
44 44
45 45 /* the initial size of our hostent buffers */
46 46 #define HENT_BUF_SIZE 1024
47 47 #define BIG_HENT_BUF_SIZE 10240 /* a jumbo-sized one */
48 48
49 49 /************************************************************************
50 50 * Inet4AddressImpl
51 51 */
52 52
↓ open down ↓ |
52 lines elided |
↑ open up ↑ |
53 53 /*
54 54 * Class: java_net_Inet4AddressImpl
55 55 * Method: getLocalHostName
56 56 * Signature: ()Ljava/lang/String;
57 57 */
58 58 JNIEXPORT jstring JNICALL
59 59 Java_java_net_Inet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
60 60 char hostname[MAXHOSTNAMELEN+1];
61 61
62 62 hostname[0] = '\0';
63 - if (JVM_GetHostName(hostname, MAXHOSTNAMELEN)) {
63 + if (JVM_GetHostName(hostname, sizeof(hostname))) {
64 64 /* Something went wrong, maybe networking is not setup? */
65 65 strcpy(hostname, "localhost");
66 66 } else {
67 67 #ifdef __linux__
68 68 /* On Linux gethostname() says "host.domain.sun.com". On
69 69 * Solaris gethostname() says "host", so extra work is needed.
70 70 */
71 71 #else
72 72 /* Solaris doesn't want to give us a fully qualified domain name.
73 73 * We do a reverse lookup to try and get one. This works
74 74 * if DNS occurs before NIS in /etc/resolv.conf, but fails
75 75 * if NIS comes first (it still gets only a partial name).
76 76 * We use thread-safe system calls.
77 77 */
78 78 #endif /* __linux__ */
79 79 struct hostent res, res2, *hp;
80 80 // these buffers must be pointer-aligned so they are declared
81 81 // with pointer type
82 82 char *buf[HENT_BUF_SIZE/(sizeof (char *))];
83 83 char *buf2[HENT_BUF_SIZE/(sizeof (char *))];
84 84 int h_error=0;
85 85
86 86 #ifdef __GLIBC__
87 87 gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &hp, &h_error);
88 88 #else
89 89 hp = gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &h_error);
90 90 #endif
91 91 if (hp) {
92 92 #ifdef __GLIBC__
93 93 gethostbyaddr_r(hp->h_addr, hp->h_length, AF_INET,
94 94 &res2, (char*)buf2, sizeof(buf2), &hp, &h_error);
95 95 #else
96 96 hp = gethostbyaddr_r(hp->h_addr, hp->h_length, AF_INET,
97 97 &res2, (char*)buf2, sizeof(buf2), &h_error);
98 98 #endif
99 99 if (hp) {
100 100 /*
101 101 * If gethostbyaddr_r() found a fully qualified host name,
102 102 * returns that name. Otherwise, returns the hostname
103 103 * found by gethostname().
104 104 */
105 105 char *p = hp->h_name;
106 106 if ((strlen(hp->h_name) > strlen(hostname))
107 107 && (strncmp(hostname, hp->h_name, strlen(hostname)) == 0)
108 108 && (*(p + strlen(hostname)) == '.'))
109 109 strcpy(hostname, hp->h_name);
110 110 }
111 111 }
112 112 }
113 113 return (*env)->NewStringUTF(env, hostname);
114 114 }
115 115
116 116 static jclass ni_iacls;
117 117 static jclass ni_ia4cls;
118 118 static jmethodID ni_ia4ctrID;
119 119 static jfieldID ni_iaaddressID;
120 120 static jfieldID ni_iahostID;
121 121 static jfieldID ni_iafamilyID;
122 122 static int initialized = 0;
123 123
124 124 /*
125 125 * Find an internet address for a given hostname. Note that this
126 126 * code only works for addresses of type INET. The translation
127 127 * of %d.%d.%d.%d to an address (int) occurs in java now, so the
128 128 * String "host" shouldn't *ever* be a %d.%d.%d.%d string
129 129 *
130 130 * Class: java_net_Inet4AddressImpl
131 131 * Method: lookupAllHostAddr
132 132 * Signature: (Ljava/lang/String;)[[B
133 133 */
134 134
135 135 JNIEXPORT jobjectArray JNICALL
136 136 Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
137 137 jstring host) {
138 138 const char *hostname;
139 139 jobjectArray ret = 0;
140 140 struct hostent res, *hp = 0;
141 141 // this buffer must be pointer-aligned so is declared
142 142 // with pointer type
143 143 char *buf[HENT_BUF_SIZE/(sizeof (char *))];
144 144
145 145 /* temporary buffer, on the off chance we need to expand */
146 146 char *tmp = NULL;
147 147 int h_error=0;
148 148
149 149 if (!initialized) {
150 150 ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
151 151 ni_iacls = (*env)->NewGlobalRef(env, ni_iacls);
152 152 ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address");
153 153 ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls);
154 154 ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
155 155 ni_iaaddressID = (*env)->GetFieldID(env, ni_iacls, "address", "I");
156 156 ni_iafamilyID = (*env)->GetFieldID(env, ni_iacls, "family", "I");
157 157 ni_iahostID = (*env)->GetFieldID(env, ni_iacls, "hostName", "Ljava/lang/String;");
158 158 initialized = 1;
159 159 }
160 160
161 161 if (IS_NULL(host)) {
162 162 JNU_ThrowNullPointerException(env, "host is null");
163 163 return 0;
164 164 }
165 165 hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
166 166 CHECK_NULL_RETURN(hostname, NULL);
167 167
168 168 #ifdef __solaris__
169 169 /*
170 170 * Workaround for Solaris bug 4160367 - if a hostname contains a
171 171 * white space then 0.0.0.0 is returned
172 172 */
173 173 if (isspace((unsigned char)hostname[0])) {
174 174 JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
175 175 (char *)hostname);
176 176 JNU_ReleaseStringPlatformChars(env, host, hostname);
177 177 return NULL;
178 178 }
179 179 #endif
180 180
181 181 /* Try once, with our static buffer. */
182 182 #ifdef __GLIBC__
183 183 gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &hp, &h_error);
184 184 #else
185 185 hp = gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &h_error);
186 186 #endif
187 187
188 188 /* With the re-entrant system calls, it's possible that the buffer
189 189 * we pass to it is not large enough to hold an exceptionally
190 190 * large DNS entry. This is signaled by errno->ERANGE. We try once
191 191 * more, with a very big size.
192 192 */
193 193 if (hp == NULL && errno == ERANGE) {
194 194 if ((tmp = (char*)malloc(BIG_HENT_BUF_SIZE))) {
195 195 #ifdef __GLIBC__
196 196 gethostbyname_r(hostname, &res, tmp, BIG_HENT_BUF_SIZE,
197 197 &hp, &h_error);
198 198 #else
199 199 hp = gethostbyname_r(hostname, &res, tmp, BIG_HENT_BUF_SIZE,
200 200 &h_error);
201 201 #endif
202 202 }
203 203 }
204 204 if (hp != NULL) {
205 205 struct in_addr **addrp = (struct in_addr **) hp->h_addr_list;
206 206 int i = 0;
207 207
208 208 while (*addrp != (struct in_addr *) 0) {
209 209 i++;
210 210 addrp++;
211 211 }
212 212
213 213 ret = (*env)->NewObjectArray(env, i, ni_iacls, NULL);
214 214 if (IS_NULL(ret)) {
215 215 /* we may have memory to free at the end of this */
216 216 goto cleanupAndReturn;
217 217 }
218 218 addrp = (struct in_addr **) hp->h_addr_list;
219 219 i = 0;
220 220 while (*addrp) {
221 221 jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
222 222 if (IS_NULL(iaObj)) {
223 223 ret = NULL;
224 224 goto cleanupAndReturn;
225 225 }
226 226 (*env)->SetIntField(env, iaObj, ni_iaaddressID,
227 227 ntohl((*addrp)->s_addr));
228 228 (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
229 229 (*env)->SetObjectArrayElement(env, ret, i, iaObj);
230 230 addrp++;
231 231 i++;
232 232 }
233 233 } else {
234 234 JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
235 235 (char *)hostname);
236 236 ret = NULL;
237 237 }
238 238
239 239 cleanupAndReturn:
240 240 JNU_ReleaseStringPlatformChars(env, host, hostname);
241 241 if (tmp != NULL) {
242 242 free(tmp);
243 243 }
244 244 return ret;
245 245 }
246 246
247 247 /*
248 248 * Class: java_net_Inet4AddressImpl
249 249 * Method: getHostByAddr
250 250 * Signature: (I)Ljava/lang/String;
251 251 */
252 252 JNIEXPORT jstring JNICALL
253 253 Java_java_net_Inet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
254 254 jbyteArray addrArray) {
255 255 jstring ret = NULL;
256 256 jint addr;
257 257 struct hostent hent, *hp = 0;
258 258 // this buffer must be pointer-aligned so is declared
259 259 // with pointer type
260 260 char *buf[HENT_BUF_SIZE/(sizeof (char *))];
261 261 int h_error = 0;
262 262 char *tmp = NULL;
263 263
264 264 /*
265 265 * We are careful here to use the reentrant version of
266 266 * gethostbyname because at the Java level this routine is not
267 267 * protected by any synchronization.
268 268 *
269 269 * Still keeping the reentrant platform dependent calls temporarily
270 270 * We should probably conform to one interface later.
271 271 *
272 272 */
273 273 jbyte caddr[4];
274 274 (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
275 275 addr = ((caddr[0]<<24) & 0xff000000);
276 276 addr |= ((caddr[1] <<16) & 0xff0000);
277 277 addr |= ((caddr[2] <<8) & 0xff00);
278 278 addr |= (caddr[3] & 0xff);
279 279 addr = htonl(addr);
280 280 #ifdef __GLIBC__
281 281 gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET, &hent,
282 282 (char*)buf, sizeof(buf), &hp, &h_error);
283 283 #else
284 284 hp = gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET, &hent,
285 285 (char*)buf, sizeof(buf), &h_error);
286 286 #endif
287 287 /* With the re-entrant system calls, it's possible that the buffer
288 288 * we pass to it is not large enough to hold an exceptionally
289 289 * large DNS entry. This is signaled by errno->ERANGE. We try once
290 290 * more, with a very big size.
291 291 */
292 292 if (hp == NULL && errno == ERANGE) {
293 293 if ((tmp = (char*)malloc(BIG_HENT_BUF_SIZE))) {
294 294 #ifdef __GLIBC__
295 295 gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET,
296 296 &hent, tmp, BIG_HENT_BUF_SIZE, &hp, &h_error);
297 297 #else
298 298 hp = gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET,
299 299 &hent, tmp, BIG_HENT_BUF_SIZE, &h_error);
300 300 #endif
301 301 } else {
302 302 JNU_ThrowOutOfMemoryError(env, "getHostByAddr");
303 303 }
304 304 }
305 305 if (hp == NULL) {
306 306 JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);
307 307 } else {
308 308 ret = (*env)->NewStringUTF(env, hp->h_name);
309 309 }
310 310 if (tmp) {
311 311 free(tmp);
312 312 }
313 313 return ret;
314 314 }
315 315
316 316 #define SET_NONBLOCKING(fd) { \
317 317 int flags = fcntl(fd, F_GETFL); \
318 318 flags |= O_NONBLOCK; \
319 319 fcntl(fd, F_SETFL, flags); \
320 320 }
321 321
322 322 /**
323 323 * ping implementation.
324 324 * Send a ICMP_ECHO_REQUEST packet every second until either the timeout
325 325 * expires or a answer is received.
326 326 * Returns true is an ECHO_REPLY is received, otherwise, false.
327 327 */
328 328 static jboolean
329 329 ping4(JNIEnv *env, jint fd, struct sockaddr_in* him, jint timeout,
330 330 struct sockaddr_in* netif, jint ttl) {
331 331 jint size;
332 332 jint n, hlen1, icmplen;
333 333 socklen_t len;
334 334 char sendbuf[1500];
335 335 char recvbuf[1500];
336 336 struct icmp *icmp;
337 337 struct ip *ip;
338 338 struct sockaddr_in sa_recv;
339 339 jchar pid;
340 340 jint tmout2, seq = 1;
341 341 struct timeval tv;
342 342 size_t plen;
343 343
344 344 /* icmp_id is a 16 bit data type, therefore down cast the pid */
345 345 pid = (jchar)getpid();
346 346 size = 60*1024;
347 347 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
348 348 /*
349 349 * sets the ttl (max number of hops)
350 350 */
351 351 if (ttl > 0) {
352 352 setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
353 353 }
354 354 /*
355 355 * a specific interface was specified, so let's bind the socket
356 356 * to that interface to ensure the requests are sent only through it.
357 357 */
358 358 if (netif != NULL) {
359 359 if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in)) < 0) {
360 360 NET_ThrowNew(env, errno, "Can't bind socket");
361 361 close(fd);
362 362 return JNI_FALSE;
363 363 }
364 364 }
365 365 /*
366 366 * Make the socket non blocking so we can use select
367 367 */
368 368 SET_NONBLOCKING(fd);
369 369 do {
370 370 /*
371 371 * create the ICMP request
372 372 */
373 373 icmp = (struct icmp *) sendbuf;
374 374 icmp->icmp_type = ICMP_ECHO;
375 375 icmp->icmp_code = 0;
376 376 icmp->icmp_id = htons(pid);
377 377 icmp->icmp_seq = htons(seq);
378 378 seq++;
379 379 gettimeofday(&tv, NULL);
380 380 memcpy(icmp->icmp_data, &tv, sizeof(tv));
381 381 plen = ICMP_ADVLENMIN + sizeof(tv);
382 382 icmp->icmp_cksum = 0;
383 383 icmp->icmp_cksum = in_cksum((u_short *)icmp, plen);
384 384 /*
385 385 * send it
386 386 */
387 387 n = sendto(fd, sendbuf, plen, 0, (struct sockaddr *)him,
388 388 sizeof(struct sockaddr));
389 389 if (n < 0 && errno != EINPROGRESS ) {
390 390 #ifdef __linux__
391 391 if (errno != EINVAL)
392 392 /*
393 393 * On some Linuxes, when bound to the loopback interface, sendto
394 394 * will fail and errno will be set to EINVAL. When that happens,
395 395 * don't throw an exception, just return false.
396 396 */
397 397 #endif /*__linux__ */
398 398 NET_ThrowNew(env, errno, "Can't send ICMP packet");
399 399 close(fd);
400 400 return JNI_FALSE;
401 401 }
402 402
403 403 tmout2 = timeout > 1000 ? 1000 : timeout;
404 404 do {
405 405 tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2);
406 406 if (tmout2 >= 0) {
407 407 len = sizeof(sa_recv);
408 408 n = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr *)&sa_recv, &len);
409 409 ip = (struct ip*) recvbuf;
410 410 hlen1 = (ip->ip_hl) << 2;
411 411 icmp = (struct icmp *) (recvbuf + hlen1);
412 412 icmplen = n - hlen1;
413 413 /*
414 414 * We did receive something, but is it what we were expecting?
415 415 * I.E.: A ICMP_ECHOREPLY packet with the proper PID.
416 416 */
417 417 if (icmplen >= 8 && icmp->icmp_type == ICMP_ECHOREPLY &&
418 418 (ntohs(icmp->icmp_id) == pid) &&
419 419 (him->sin_addr.s_addr == sa_recv.sin_addr.s_addr)) {
420 420 close(fd);
421 421 return JNI_TRUE;
422 422 }
423 423 }
424 424 } while (tmout2 > 0);
425 425 timeout -= 1000;
426 426 } while (timeout >0);
427 427 close(fd);
428 428 return JNI_FALSE;
429 429 }
430 430
431 431 /*
432 432 * Class: java_net_Inet4AddressImpl
433 433 * Method: isReachable0
434 434 * Signature: ([bI[bI)Z
435 435 */
436 436 JNIEXPORT jboolean JNICALL
437 437 Java_java_net_Inet4AddressImpl_isReachable0(JNIEnv *env, jobject this,
438 438 jbyteArray addrArray,
439 439 jint timeout,
440 440 jbyteArray ifArray,
441 441 jint ttl) {
442 442 jint addr;
443 443 jbyte caddr[4];
444 444 jint fd;
445 445 struct sockaddr_in him;
446 446 struct sockaddr_in* netif = NULL;
447 447 struct sockaddr_in inf;
448 448 int len = 0;
449 449 int connect_rv = -1;
450 450 int sz;
451 451
452 452 memset((char *) caddr, 0, sizeof(caddr));
453 453 memset((char *) &him, 0, sizeof(him));
454 454 sz = (*env)->GetArrayLength(env, addrArray);
455 455 if (sz != 4) {
456 456 return JNI_FALSE;
457 457 }
458 458 (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
459 459 addr = ((caddr[0]<<24) & 0xff000000);
460 460 addr |= ((caddr[1] <<16) & 0xff0000);
461 461 addr |= ((caddr[2] <<8) & 0xff00);
462 462 addr |= (caddr[3] & 0xff);
463 463 addr = htonl(addr);
464 464 him.sin_addr.s_addr = addr;
465 465 him.sin_family = AF_INET;
466 466 len = sizeof(him);
467 467 /*
468 468 * If a network interface was specified, let's create the address
469 469 * for it.
470 470 */
471 471 if (!(IS_NULL(ifArray))) {
472 472 memset((char *) caddr, 0, sizeof(caddr));
473 473 (*env)->GetByteArrayRegion(env, ifArray, 0, 4, caddr);
474 474 addr = ((caddr[0]<<24) & 0xff000000);
475 475 addr |= ((caddr[1] <<16) & 0xff0000);
476 476 addr |= ((caddr[2] <<8) & 0xff00);
477 477 addr |= (caddr[3] & 0xff);
478 478 addr = htonl(addr);
479 479 inf.sin_addr.s_addr = addr;
480 480 inf.sin_family = AF_INET;
481 481 inf.sin_port = 0;
482 482 netif = &inf;
483 483 }
484 484
485 485 /*
486 486 * Let's try to create a RAW socket to send ICMP packets
487 487 * This usually requires "root" privileges, so it's likely to fail.
488 488 */
489 489 fd = JVM_Socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
490 490 if (fd != -1) {
491 491 /*
492 492 * It didn't fail, so we can use ICMP_ECHO requests.
493 493 */
494 494 return ping4(env, fd, &him, timeout, netif, ttl);
495 495 }
496 496
497 497 /*
498 498 * Can't create a raw socket, so let's try a TCP socket
499 499 */
500 500 fd = JVM_Socket(AF_INET, SOCK_STREAM, 0);
501 501 if (fd == JVM_IO_ERR) {
502 502 /* note: if you run out of fds, you may not be able to load
503 503 * the exception class, and get a NoClassDefFoundError
504 504 * instead.
505 505 */
506 506 NET_ThrowNew(env, errno, "Can't create socket");
507 507 return JNI_FALSE;
508 508 }
509 509 if (ttl > 0) {
510 510 setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
511 511 }
512 512
513 513 /*
514 514 * A network interface was specified, so let's bind to it.
515 515 */
516 516 if (netif != NULL) {
517 517 if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in)) < 0) {
518 518 NET_ThrowNew(env, errno, "Can't bind socket");
519 519 close(fd);
520 520 return JNI_FALSE;
521 521 }
522 522 }
523 523
524 524 /*
525 525 * Make the socket non blocking so we can use select/poll.
526 526 */
527 527 SET_NONBLOCKING(fd);
528 528
529 529 /* no need to use NET_Connect as non-blocking */
530 530 him.sin_port = htons(7); /* Echo */
531 531 connect_rv = JVM_Connect(fd, (struct sockaddr *)&him, len);
532 532
533 533 /**
534 534 * connection established or refused immediately, either way it means
535 535 * we were able to reach the host!
536 536 */
537 537 if (connect_rv == 0 || errno == ECONNREFUSED) {
538 538 close(fd);
539 539 return JNI_TRUE;
540 540 } else {
541 541 int optlen;
542 542
543 543 switch (errno) {
544 544 case ENETUNREACH: /* Network Unreachable */
545 545 case EAFNOSUPPORT: /* Address Family not supported */
546 546 case EADDRNOTAVAIL: /* address is not available on the remote machine */
547 547 #ifdef __linux__
548 548 case EINVAL:
549 549 /*
550 550 * On some Linuxes, when bound to the loopback interface, connect
551 551 * will fail and errno will be set to EINVAL. When that happens,
552 552 * don't throw an exception, just return false.
553 553 */
554 554 #endif /* __linux__ */
555 555 close(fd);
556 556 return JNI_FALSE;
557 557 }
558 558
559 559 if (errno != EINPROGRESS) {
560 560 NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
561 561 "connect failed");
562 562 close(fd);
563 563 return JNI_FALSE;
564 564 }
565 565
566 566 timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);
567 567 if (timeout >= 0) {
568 568 /* has connection been established? */
569 569 optlen = sizeof(connect_rv);
570 570 if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
571 571 &optlen) <0) {
572 572 connect_rv = errno;
573 573 }
574 574 if (connect_rv == 0 || connect_rv == ECONNREFUSED) {
575 575 close(fd);
576 576 return JNI_TRUE;
577 577 }
578 578 }
579 579 close(fd);
580 580 return JNI_FALSE;
581 581 }
582 582 }
↓ open down ↓ |
509 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX