Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / libjava / gnu / java / net / natPlainDatagramSocketImplPosix.cc
blob708f5421cea352811ddfaa0e317373ccab00bf13
1 /* Copyright (C) 2003 Free Software Foundation
3 This file is part of libgcj.
5 This software is copyrighted work licensed under the terms of the
6 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
7 details. */
9 #include <config.h>
10 #include <platform.h>
12 #ifdef HAVE_NETINET_IN_H
13 #include <netinet/in.h>
14 #endif
15 #ifdef HAVE_ARPA_INET_H
16 #include <arpa/inet.h>
17 #endif
18 #include <errno.h>
19 #include <string.h>
21 #if HAVE_BSTRING_H
22 // Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2
23 #include <bstring.h>
24 #endif
26 #include <gcj/cni.h>
27 #include <gnu/java/net/PlainDatagramSocketImpl.h>
28 #include <java/io/IOException.h>
29 #include <java/io/InterruptedIOException.h>
30 #include <java/net/BindException.h>
31 #include <java/net/SocketException.h>
32 #include <java/net/SocketTimeoutException.h>
33 #include <java/net/InetAddress.h>
34 #include <java/net/NetworkInterface.h>
35 #include <java/net/DatagramPacket.h>
36 #include <java/net/PortUnreachableException.h>
37 #include <java/lang/InternalError.h>
38 #include <java/lang/Object.h>
39 #include <java/lang/Boolean.h>
40 #include <java/lang/Integer.h>
42 union SockAddr
44 struct sockaddr_in address;
45 #ifdef HAVE_INET6
46 struct sockaddr_in6 address6;
47 #endif
50 union McastReq
52 #if HAVE_STRUCT_IP_MREQ
53 struct ip_mreq mreq;
54 #endif
55 #if HAVE_STRUCT_IPV6_MREQ
56 struct ipv6_mreq mreq6;
57 #endif
60 union InAddr
62 struct in_addr addr;
63 #ifdef HAVE_INET6
64 struct in6_addr addr6;
65 #endif
69 // FIXME: routines here and/or in natPlainSocketImpl.cc could throw
70 // NoRouteToHostException; also consider UnknownHostException, ConnectException.
72 void
73 gnu::java::net::PlainDatagramSocketImpl::create ()
75 int sock = _Jv_socket (AF_INET, SOCK_DGRAM, 0);
77 if (sock < 0)
79 char* strerr = strerror (errno);
80 throw new ::java::net::SocketException (JvNewStringUTF (strerr));
83 _Jv_platform_close_on_exec (sock);
85 // We use native_fd in place of fd here. From leaving fd null we avoid
86 // the double close problem in FileDescriptor.finalize.
87 native_fd = sock;
90 void
91 gnu::java::net::PlainDatagramSocketImpl::bind (jint lport,
92 ::java::net::InetAddress *host)
94 union SockAddr u;
95 struct sockaddr *ptr = (struct sockaddr *) &u.address;
96 // FIXME: Use getaddrinfo() to get actual protocol instead of assuming ipv4.
97 jbyteArray haddress = host->addr;
98 jbyte *bytes = elements (haddress);
99 int len = haddress->length;
101 if (len == 4)
103 u.address.sin_family = AF_INET;
105 if (host != NULL)
106 memcpy (&u.address.sin_addr, bytes, len);
107 else
108 u.address.sin_addr.s_addr = htonl (INADDR_ANY);
110 len = sizeof (struct sockaddr_in);
111 u.address.sin_port = htons (lport);
113 #ifdef HAVE_INET6
114 else if (len == 16)
116 u.address6.sin6_family = AF_INET6;
117 memcpy (&u.address6.sin6_addr, bytes, len);
118 len = sizeof (struct sockaddr_in6);
119 u.address6.sin6_port = htons (lport);
121 #endif
122 else
123 throw new ::java::net::SocketException (JvNewStringUTF ("invalid length"));
125 if (_Jv_bind (native_fd, ptr, len) == 0)
127 socklen_t addrlen = sizeof(u);
129 if (lport != 0)
130 localPort = lport;
131 else if (::getsockname (native_fd, (sockaddr*) &u, &addrlen) == 0)
132 localPort = ntohs (u.address.sin_port);
133 else
134 goto error;
136 /* Allow broadcast by default. */
137 int broadcast = 1;
138 if (::setsockopt (native_fd, SOL_SOCKET, SO_BROADCAST, (char *) &broadcast,
139 sizeof (broadcast)) != 0)
140 goto error;
142 return;
145 error:
146 char* strerr = strerror (errno);
147 throw new ::java::net::BindException (JvNewStringUTF (strerr));
150 void
151 gnu::java::net::PlainDatagramSocketImpl::connect (::java::net::InetAddress *, jint)
153 throw new ::java::lang::InternalError (JvNewStringLatin1 (
154 "PlainDatagramSocketImpl::connect: not implemented yet"));
157 void
158 gnu::java::net::PlainDatagramSocketImpl::disconnect ()
160 throw new ::java::lang::InternalError (JvNewStringLatin1 (
161 "PlainDatagramSocketImpl::disconnect: not implemented yet"));
164 jint
165 gnu::java::net::PlainDatagramSocketImpl::peek (::java::net::InetAddress *i)
167 // FIXME: Deal with Multicast and if the socket is connected.
168 union SockAddr u;
169 socklen_t addrlen = sizeof(u);
170 ssize_t retlen =
171 ::recvfrom (native_fd, (char *) NULL, 0, MSG_PEEK, (sockaddr*) &u,
172 &addrlen);
173 if (retlen < 0)
174 goto error;
175 // FIXME: Deal with Multicast addressing and if the socket is connected.
176 jbyteArray raddr;
177 jint rport;
178 if (u.address.sin_family == AF_INET)
180 raddr = JvNewByteArray (4);
181 memcpy (elements (raddr), &u.address.sin_addr, 4);
182 rport = ntohs (u.address.sin_port);
184 #ifdef HAVE_INET6
185 else if (u.address.sin_family == AF_INET6)
187 raddr = JvNewByteArray (16);
188 memcpy (elements (raddr), &u.address6.sin6_addr, 16);
189 rport = ntohs (u.address6.sin6_port);
191 #endif
192 else
193 throw new ::java::net::SocketException (JvNewStringUTF ("invalid family"));
195 i->addr = raddr;
196 return rport;
197 error:
198 char* strerr = strerror (errno);
200 if (errno == ECONNREFUSED)
201 throw new ::java::net::PortUnreachableException (JvNewStringUTF (strerr));
203 throw new ::java::io::IOException (JvNewStringUTF (strerr));
206 jint
207 gnu::java::net::PlainDatagramSocketImpl::peekData (::java::net::DatagramPacket *p)
209 // FIXME: Deal with Multicast and if the socket is connected.
210 union SockAddr u;
211 socklen_t addrlen = sizeof(u);
212 jbyte *dbytes = elements (p->getData()) + p->getOffset();
213 jint maxlen = p->maxlen - p->getOffset();
214 ssize_t retlen = 0;
216 // Do timeouts via select since SO_RCVTIMEO is not always available.
217 if (timeout > 0 && native_fd >= 0 && native_fd < FD_SETSIZE)
219 fd_set rset;
220 struct timeval tv;
221 FD_ZERO(&rset);
222 FD_SET(native_fd, &rset);
223 tv.tv_sec = timeout / 1000;
224 tv.tv_usec = (timeout % 1000) * 1000;
225 int retval;
226 if ((retval = _Jv_select (native_fd + 1, &rset, NULL, NULL, &tv)) < 0)
227 goto error;
228 else if (retval == 0)
229 throw new ::java::net::SocketTimeoutException
230 (JvNewStringUTF ("PeekData timed out") );
233 retlen =
234 ::recvfrom (native_fd, (char *) dbytes, maxlen, MSG_PEEK, (sockaddr*) &u,
235 &addrlen);
236 if (retlen < 0)
237 goto error;
238 // FIXME: Deal with Multicast addressing and if the socket is connected.
239 jbyteArray raddr;
240 jint rport;
241 if (u.address.sin_family == AF_INET)
243 raddr = JvNewByteArray (4);
244 memcpy (elements (raddr), &u.address.sin_addr, 4);
245 rport = ntohs (u.address.sin_port);
247 #ifdef HAVE_INET6
248 else if (u.address.sin_family == AF_INET6)
250 raddr = JvNewByteArray (16);
251 memcpy (elements (raddr), &u.address6.sin6_addr, 16);
252 rport = ntohs (u.address6.sin6_port);
254 #endif
255 else
256 throw new ::java::net::SocketException (JvNewStringUTF ("invalid family"));
258 p->setAddress (new ::java::net::InetAddress (raddr, NULL));
259 p->setPort (rport);
260 p->length = (int) retlen;
261 return rport;
263 error:
264 char* strerr = strerror (errno);
266 if (errno == ECONNREFUSED)
267 throw new ::java::net::PortUnreachableException (JvNewStringUTF (strerr));
269 throw new ::java::io::IOException (JvNewStringUTF (strerr));
272 // Close(shutdown) the socket.
273 void
274 gnu::java::net::PlainDatagramSocketImpl::close ()
276 // Avoid races from asynchronous finalization.
277 JvSynchronize sync (this);
279 // The method isn't declared to throw anything, so we disregard
280 // the return value.
281 _Jv_close (native_fd);
282 native_fd = -1;
283 timeout = 0;
286 void
287 gnu::java::net::PlainDatagramSocketImpl::send (::java::net::DatagramPacket *p)
289 JvSynchronize lock (SEND_LOCK);
291 // FIXME: Deal with Multicast and if the socket is connected.
292 jint rport = p->getPort();
293 union SockAddr u;
294 jbyteArray haddress = p->getAddress()->addr;
295 jbyte *bytes = elements (haddress);
296 int len = haddress->length;
297 struct sockaddr *ptr = (struct sockaddr *) &u.address;
298 jbyte *dbytes = elements (p->getData()) + p->getOffset();
299 if (len == 4)
301 u.address.sin_family = AF_INET;
302 memcpy (&u.address.sin_addr, bytes, len);
303 len = sizeof (struct sockaddr_in);
304 u.address.sin_port = htons (rport);
306 #ifdef HAVE_INET6
307 else if (len == 16)
309 u.address6.sin6_family = AF_INET6;
310 memcpy (&u.address6.sin6_addr, bytes, len);
311 len = sizeof (struct sockaddr_in6);
312 u.address6.sin6_port = htons (rport);
314 #endif
315 else
316 throw new ::java::net::SocketException (JvNewStringUTF ("invalid length"));
318 if (::sendto (native_fd, (char *) dbytes, p->getLength(), 0, ptr, len) >= 0)
319 return;
321 char* strerr = strerror (errno);
323 if (errno == ECONNREFUSED)
324 throw new ::java::net::PortUnreachableException (JvNewStringUTF (strerr));
326 throw new ::java::io::IOException (JvNewStringUTF (strerr));
329 void
330 gnu::java::net::PlainDatagramSocketImpl::receive (::java::net::DatagramPacket *p)
332 JvSynchronize lock (RECEIVE_LOCK);
334 // FIXME: Deal with Multicast and if the socket is connected.
335 union SockAddr u;
336 socklen_t addrlen = sizeof(u);
337 jbyte *dbytes = elements (p->getData()) + p->getOffset();
338 jint maxlen = p->maxlen - p->getOffset();
339 ssize_t retlen = 0;
341 // Do timeouts via select since SO_RCVTIMEO is not always available.
342 if (timeout > 0 && native_fd >= 0 && native_fd < FD_SETSIZE)
344 fd_set rset;
345 struct timeval tv;
346 FD_ZERO(&rset);
347 FD_SET(native_fd, &rset);
348 tv.tv_sec = timeout / 1000;
349 tv.tv_usec = (timeout % 1000) * 1000;
350 int retval;
351 if ((retval = _Jv_select (native_fd + 1, &rset, NULL, NULL, &tv)) < 0)
352 goto error;
353 else if (retval == 0)
354 throw new ::java::net::SocketTimeoutException
355 (JvNewStringUTF ("Receive timed out") );
358 retlen =
359 ::recvfrom (native_fd, (char *) dbytes, maxlen, 0, (sockaddr*) &u,
360 &addrlen);
361 if (retlen < 0)
362 goto error;
363 // FIXME: Deal with Multicast addressing and if the socket is connected.
364 jbyteArray raddr;
365 jint rport;
366 if (u.address.sin_family == AF_INET)
368 raddr = JvNewByteArray (4);
369 memcpy (elements (raddr), &u.address.sin_addr, 4);
370 rport = ntohs (u.address.sin_port);
372 #ifdef HAVE_INET6
373 else if (u.address.sin_family == AF_INET6)
375 raddr = JvNewByteArray (16);
376 memcpy (elements (raddr), &u.address6.sin6_addr, 16);
377 rport = ntohs (u.address6.sin6_port);
379 #endif
380 else
381 throw new ::java::net::SocketException (JvNewStringUTF ("invalid family"));
383 p->setAddress (new ::java::net::InetAddress (raddr, NULL));
384 p->setPort (rport);
385 p->length = (jint) retlen;
386 return;
388 error:
389 char* strerr = strerror (errno);
391 if (errno == ECONNREFUSED)
392 throw new ::java::net::PortUnreachableException (JvNewStringUTF (strerr));
394 throw new ::java::io::IOException (JvNewStringUTF (strerr));
397 void
398 gnu::java::net::PlainDatagramSocketImpl::setTimeToLive (jint ttl)
400 // Assumes IPPROTO_IP rather than IPPROTO_IPV6 since socket created is IPv4.
401 char val = (char) ttl;
402 socklen_t val_len = sizeof(val);
404 if (::setsockopt (native_fd, IPPROTO_IP, IP_MULTICAST_TTL, &val, val_len) == 0)
405 return;
407 char* strerr = strerror (errno);
408 throw new ::java::io::IOException (JvNewStringUTF (strerr));
411 jint
412 gnu::java::net::PlainDatagramSocketImpl::getTimeToLive ()
414 // Assumes IPPROTO_IP rather than IPPROTO_IPV6 since socket created is IPv4.
415 char val;
416 socklen_t val_len = sizeof(val);
418 if (::getsockopt (native_fd, IPPROTO_IP, IP_MULTICAST_TTL, &val, &val_len) == 0)
419 return ((int) val) & 0xFF;
421 char* strerr = strerror (errno);
422 throw new ::java::io::IOException (JvNewStringUTF (strerr));
425 void
426 gnu::java::net::PlainDatagramSocketImpl::mcastGrp (::java::net::InetAddress *inetaddr,
427 ::java::net::NetworkInterface *,
428 jboolean join)
430 // FIXME: implement use of NetworkInterface
432 jbyteArray haddress = inetaddr->addr;
433 #if HAVE_STRUCT_IP_MREQ || HAVE_STRUCT_IPV6_MREQ
434 union McastReq u;
435 jbyte *bytes = elements (haddress);
436 #endif
438 int len = haddress->length;
439 int level, opname;
440 const char *ptr;
441 if (0)
443 #if HAVE_STRUCT_IP_MREQ
444 else if (len == 4)
446 level = IPPROTO_IP;
447 opname = join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
448 memcpy (&u.mreq.imr_multiaddr, bytes, len);
449 // FIXME: If a non-default interface is set, use it; see Stevens p. 501.
450 // Maybe not, see note in last paragraph at bottom of Stevens p. 497.
451 u.mreq.imr_interface.s_addr = htonl (INADDR_ANY);
452 len = sizeof (struct ip_mreq);
453 ptr = (const char *) &u.mreq;
455 #endif
456 #if HAVE_STRUCT_IPV6_MREQ
457 else if (len == 16)
459 level = IPPROTO_IPV6;
461 /* Prefer new RFC 2553 names. */
462 #ifndef IPV6_JOIN_GROUP
463 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
464 #endif
465 #ifndef IPV6_LEAVE_GROUP
466 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
467 #endif
469 opname = join ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP;
470 memcpy (&u.mreq6.ipv6mr_multiaddr, bytes, len);
471 // FIXME: If a non-default interface is set, use it; see Stevens p. 501.
472 // Maybe not, see note in last paragraph at bottom of Stevens p. 497.
473 u.mreq6.ipv6mr_interface = 0;
474 len = sizeof (struct ipv6_mreq);
475 ptr = (const char *) &u.mreq6;
477 #endif
478 else
479 throw new ::java::net::SocketException (JvNewStringUTF ("invalid length"));
481 if (::setsockopt (native_fd, level, opname, ptr, len) == 0)
482 return;
484 char* strerr = strerror (errno);
485 throw new ::java::io::IOException (JvNewStringUTF (strerr));
488 void
489 gnu::java::net::PlainDatagramSocketImpl::setOption (jint optID,
490 ::java::lang::Object *value)
492 int val;
493 socklen_t val_len = sizeof (val);
495 if (native_fd < 0)
496 throw new ::java::net::SocketException (JvNewStringUTF ("Socket closed"));
498 if (_Jv_IsInstanceOf (value, &::java::lang::Boolean::class$))
500 ::java::lang::Boolean *boolobj =
501 static_cast< ::java::lang::Boolean *> (value);
502 val = boolobj->booleanValue() ? 1 : 0;
504 else if (_Jv_IsInstanceOf (value, &::java::lang::Integer::class$))
506 ::java::lang::Integer *intobj =
507 static_cast< ::java::lang::Integer *> (value);
508 val = (int) intobj->intValue();
510 // Else assume value to be an InetAddress for use with IP_MULTICAST_IF.
512 switch (optID)
514 case _Jv_TCP_NODELAY_ :
515 throw new ::java::net::SocketException (
516 JvNewStringUTF ("TCP_NODELAY not valid for UDP"));
517 return;
518 case _Jv_SO_LINGER_ :
519 throw new ::java::net::SocketException (
520 JvNewStringUTF ("SO_LINGER not valid for UDP"));
521 return;
522 case _Jv_SO_KEEPALIVE_ :
523 throw new ::java::net::SocketException (
524 JvNewStringUTF ("SO_KEEPALIVE not valid for UDP"));
525 return;
527 case _Jv_SO_BROADCAST_ :
528 if (::setsockopt (native_fd, SOL_SOCKET, SO_BROADCAST, (char *) &val,
529 val_len) != 0)
530 goto error;
531 return;
533 case _Jv_SO_OOBINLINE_ :
534 throw new ::java::net::SocketException (
535 JvNewStringUTF ("SO_OOBINLINE: not valid for UDP"));
536 return;
538 case _Jv_SO_SNDBUF_ :
539 case _Jv_SO_RCVBUF_ :
540 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
541 int opt;
542 optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
543 if (::setsockopt (native_fd, SOL_SOCKET, opt, (char *) &val, val_len) != 0)
544 goto error;
545 #else
546 throw new ::java::lang::InternalError (
547 JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
548 #endif
549 return;
550 case _Jv_SO_REUSEADDR_ :
551 #if defined(SO_REUSEADDR)
552 if (::setsockopt (native_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
553 val_len) != 0)
554 goto error;
555 #else
556 throw new ::java::lang::InternalError (
557 JvNewStringUTF ("SO_REUSEADDR not supported"));
558 #endif
559 return;
560 case _Jv_SO_BINDADDR_ :
561 throw new ::java::net::SocketException (
562 JvNewStringUTF ("SO_BINDADDR: read only option"));
563 return;
564 case _Jv_IP_MULTICAST_IF_ :
565 union InAddr u;
566 jbyteArray haddress;
567 jbyte *bytes;
568 int len;
569 int level, opname;
570 const char *ptr;
572 haddress = ((::java::net::InetAddress *) value)->addr;
573 bytes = elements (haddress);
574 len = haddress->length;
575 if (len == 4)
577 level = IPPROTO_IP;
578 opname = IP_MULTICAST_IF;
579 memcpy (&u.addr, bytes, len);
580 len = sizeof (struct in_addr);
581 ptr = (const char *) &u.addr;
583 // Tru64 UNIX V5.0 has struct sockaddr_in6, but no IPV6_MULTICAST_IF
584 #if defined (HAVE_INET6) && defined (IPV6_MULTICAST_IF)
585 else if (len == 16)
587 level = IPPROTO_IPV6;
588 opname = IPV6_MULTICAST_IF;
589 memcpy (&u.addr6, bytes, len);
590 len = sizeof (struct in6_addr);
591 ptr = (const char *) &u.addr6;
593 #endif
594 else
595 throw
596 new ::java::net::SocketException (JvNewStringUTF ("invalid length"));
598 if (::setsockopt (native_fd, level, opname, ptr, len) != 0)
599 goto error;
600 return;
602 case _Jv_IP_MULTICAST_IF2_ :
603 throw new ::java::net::SocketException (
604 JvNewStringUTF ("IP_MULTICAST_IF2: not yet implemented"));
605 return;
607 case _Jv_IP_MULTICAST_LOOP_ :
608 haddress = ((::java::net::InetAddress *) value)->addr;
609 len = haddress->length;
610 if (len == 4)
612 level = IPPROTO_IP;
613 opname = IP_MULTICAST_LOOP;
615 #if defined (HAVE_INET6) && defined (IPV6_MULTICAST_LOOP)
616 else if (len == 16)
618 level = IPPROTO_IPV6;
619 opname = IPV6_MULTICAST_LOOP;
621 #endif
622 else
623 throw
624 new ::java::net::SocketException (JvNewStringUTF ("invalid address length"));
625 if (::setsockopt (native_fd, level, opname, (char *) &val,
626 val_len) != 0)
627 goto error;
628 return;
630 case _Jv_IP_TOS_ :
631 if (::setsockopt (native_fd, SOL_SOCKET, IP_TOS, (char *) &val,
632 val_len) != 0)
633 goto error;
634 return;
636 case _Jv_SO_TIMEOUT_ :
637 timeout = val;
638 return;
639 default :
640 errno = ENOPROTOOPT;
643 error:
644 char* strerr = strerror (errno);
645 throw new ::java::net::SocketException (JvNewStringUTF (strerr));
648 ::java::lang::Object *
649 gnu::java::net::PlainDatagramSocketImpl::getOption (jint optID)
651 int val;
652 socklen_t val_len = sizeof(val);
653 union SockAddr u;
654 socklen_t addrlen = sizeof(u);
655 int level, opname;
657 switch (optID)
659 case _Jv_TCP_NODELAY_ :
660 throw new ::java::net::SocketException (
661 JvNewStringUTF ("TCP_NODELAY not valid for UDP"));
662 break;
663 case _Jv_SO_LINGER_ :
664 throw new ::java::net::SocketException (
665 JvNewStringUTF ("SO_LINGER not valid for UDP"));
666 break;
667 case _Jv_SO_KEEPALIVE_ :
668 throw new ::java::net::SocketException (
669 JvNewStringUTF ("SO_KEEPALIVE not valid for UDP"));
670 break;
672 case _Jv_SO_BROADCAST_ :
673 if (::getsockopt (native_fd, SOL_SOCKET, SO_BROADCAST, (char *) &val,
674 &val_len) != 0)
675 goto error;
676 return new ::java::lang::Boolean (val != 0);
678 case _Jv_SO_OOBINLINE_ :
679 throw new ::java::net::SocketException (
680 JvNewStringUTF ("SO_OOBINLINE not valid for UDP"));
681 break;
683 case _Jv_SO_RCVBUF_ :
684 case _Jv_SO_SNDBUF_ :
685 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
686 int opt;
687 optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
688 if (::getsockopt (native_fd, SOL_SOCKET, opt, (char *) &val, &val_len) != 0)
689 goto error;
690 else
691 return new ::java::lang::Integer (val);
692 #else
693 throw new ::java::lang::InternalError (
694 JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
695 #endif
696 break;
697 case _Jv_SO_BINDADDR_:
698 // cache the local address
699 if (localAddress == NULL)
701 jbyteArray laddr;
702 if (::getsockname (native_fd, (sockaddr*) &u, &addrlen) != 0)
703 goto error;
704 if (u.address.sin_family == AF_INET)
706 laddr = JvNewByteArray (4);
707 memcpy (elements (laddr), &u.address.sin_addr, 4);
709 #ifdef HAVE_INET6
710 else if (u.address.sin_family == AF_INET6)
712 laddr = JvNewByteArray (16);
713 memcpy (elements (laddr), &u.address6.sin6_addr, 16);
715 #endif
716 else
717 throw new ::java::net::SocketException (
718 JvNewStringUTF ("invalid family"));
719 localAddress = new ::java::net::InetAddress (laddr, NULL);
721 return localAddress;
722 break;
723 case _Jv_SO_REUSEADDR_ :
724 #if defined(SO_REUSEADDR)
725 if (::getsockopt (native_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
726 &val_len) != 0)
727 goto error;
728 return new ::java::lang::Boolean (val != 0);
729 #else
730 throw new ::java::lang::InternalError (
731 JvNewStringUTF ("SO_REUSEADDR not supported"));
732 #endif
733 break;
734 case _Jv_IP_MULTICAST_IF_ :
735 #ifdef HAVE_INET_NTOA
736 struct in_addr inaddr;
737 socklen_t inaddr_len;
738 char *bytes;
740 inaddr_len = sizeof(inaddr);
741 if (::getsockopt (native_fd, IPPROTO_IP, IP_MULTICAST_IF, (char *) &inaddr,
742 &inaddr_len) != 0)
743 goto error;
745 bytes = inet_ntoa (inaddr);
747 return ::java::net::InetAddress::getByName (JvNewStringLatin1 (bytes));
748 #else
749 throw new ::java::net::SocketException (
750 JvNewStringUTF ("IP_MULTICAST_IF: not available - no inet_ntoa()"));
751 #endif
752 break;
753 case _Jv_SO_TIMEOUT_ :
754 return new ::java::lang::Integer (timeout);
755 break;
757 case _Jv_IP_MULTICAST_IF2_ :
758 throw new ::java::net::SocketException (
759 JvNewStringUTF ("IP_MULTICAST_IF2: not yet implemented"));
760 break;
762 case _Jv_IP_MULTICAST_LOOP_ :
763 // cache the local address
764 if (localAddress == NULL)
766 jbyteArray laddr;
767 if (::getsockname (native_fd, (sockaddr*) &u, &addrlen) != 0)
768 goto error;
769 if (u.address.sin_family == AF_INET)
771 laddr = JvNewByteArray (4);
772 memcpy (elements (laddr), &u.address.sin_addr, 4);
774 #ifdef HAVE_INET6
775 else if (u.address.sin_family == AF_INET6)
777 laddr = JvNewByteArray (16);
778 memcpy (elements (laddr), &u.address6.sin6_addr, 16);
780 #endif
781 else
782 throw new ::java::net::SocketException (
783 JvNewStringUTF ("invalid family"));
784 localAddress = new ::java::net::InetAddress (laddr, NULL);
787 if (localAddress->addr->length == 4)
789 level = IPPROTO_IP;
790 opname = IP_MULTICAST_LOOP;
792 #if defined (HAVE_INET6) && defined (IPV6_MULTICAST_LOOP)
793 else if (localAddress->addr->length == 16)
795 level = IPPROTO_IPV6;
796 opname = IPV6_MULTICAST_LOOP;
798 #endif
799 else
800 throw
801 new ::java::net::SocketException (JvNewStringUTF ("invalid address length"));
802 if (::getsockopt (native_fd, level, opname, (char *) &val,
803 &val_len) != 0)
804 goto error;
805 return new ::java::lang::Boolean (val != 0);
807 case _Jv_IP_TOS_ :
808 if (::getsockopt (native_fd, SOL_SOCKET, IP_TOS, (char *) &val,
809 &val_len) != 0)
810 goto error;
811 return new ::java::lang::Integer (val);
813 default :
814 errno = ENOPROTOOPT;
817 error:
818 char* strerr = strerror (errno);
819 throw new ::java::net::SocketException (JvNewStringUTF (strerr));