1 /* Copyright (C) 1999, 2000 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
17 #define ENOPROTOOPT 109
19 #else /* USE_WINSOCK */
21 #ifdef HAVE_SYS_SOCKET_H
22 #include <sys/socket.h>
24 #ifdef HAVE_NETINET_IN_H
25 #include <netinet/in.h>
27 #ifdef HAVE_ARPA_INET_H
28 #include <arpa/inet.h>
32 #endif /* USE_WINSOCK */
35 // Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2
39 // Avoid macro definitions of bind from system headers, e.g. on
40 // Solaris 7 with _XOPEN_SOURCE. FIXME
42 _Jv_bind (int fd, struct sockaddr *addr, int addrlen)
44 return ::bind (fd, addr, addrlen);
52 #include <java/io/IOException.h>
53 #include <java/io/FileDescriptor.h>
54 #include <java/io/InterruptedIOException.h>
55 #include <java/net/BindException.h>
56 #include <java/net/SocketException.h>
57 #include <java/net/PlainDatagramSocketImpl.h>
58 #include <java/net/InetAddress.h>
59 #include <java/net/DatagramPacket.h>
60 #include <java/lang/InternalError.h>
61 #include <java/lang/Object.h>
62 #include <java/lang/Boolean.h>
63 #include <java/lang/Integer.h>
65 // FIXME: remove these
66 #define BooleanClass java::lang::Boolean::class$
67 #define IntegerClass java::lang::Integer::class$
69 #ifdef DISABLE_JAVA_NET
72 java::net::PlainDatagramSocketImpl::create ()
74 throw new SocketException (
75 JvNewStringLatin1 ("DatagramSocketImpl.create: unimplemented"));
79 java::net::PlainDatagramSocketImpl::bind (jint, java::net::InetAddress *)
81 throw new BindException (
82 JvNewStringLatin1 ("DatagramSocketImpl.bind: unimplemented"));
86 java::net::PlainDatagramSocketImpl::peek (java::net::InetAddress *)
88 throw new java::io::IOException (
89 JvNewStringLatin1 ("DatagramSocketImpl.peek: unimplemented"));
93 java::net::PlainDatagramSocketImpl::send (java::net::DatagramPacket *)
95 throw new java::io::IOException (
96 JvNewStringLatin1 ("DatagramSocketImpl.send: unimplemented"));
100 java::net::PlainDatagramSocketImpl::receive (java::net::DatagramPacket *)
102 throw new java::io::IOException (
103 JvNewStringLatin1 ("DatagramSocketImpl.receive: unimplemented"));
107 java::net::PlainDatagramSocketImpl::setTimeToLive (jint)
109 throw new java::io::IOException (
110 JvNewStringLatin1 ("DatagramSocketImpl.setTimeToLive: unimplemented"));
114 java::net::PlainDatagramSocketImpl::getTimeToLive ()
116 throw new java::io::IOException (
117 JvNewStringLatin1 ("DatagramSocketImpl.getTimeToLive: unimplemented"));
121 java::net::PlainDatagramSocketImpl::mcastGrp (java::net::InetAddress *,
124 throw new java::io::IOException (
125 JvNewStringLatin1 ("DatagramSocketImpl.mcastGrp: unimplemented"));
129 java::net::PlainDatagramSocketImpl::setOption (jint, java::lang::Object *)
131 throw new SocketException (
132 JvNewStringLatin1 ("DatagramSocketImpl.setOption: unimplemented"));
136 java::net::PlainDatagramSocketImpl::getOption (jint)
138 throw new SocketException (
139 JvNewStringLatin1 ("DatagramSocketImpl.getOption: unimplemented"));
142 #else /* DISABLE_JAVA_NET */
144 #ifndef HAVE_SOCKLEN_T
145 typedef int socklen_t;
150 struct sockaddr_in address;
152 struct sockaddr_in6 address6;
158 #if HAVE_STRUCT_IP_MREQ
161 #if HAVE_STRUCT_IPV6_MREQ
162 struct ipv6_mreq mreq6;
170 struct in6_addr addr6;
175 // FIXME: routines here and/or in natPlainSocketImpl.cc could throw
176 // NoRouteToHostException; also consider UnknownHostException, ConnectException.
179 java::net::PlainDatagramSocketImpl::create ()
181 int sock = ::socket (AF_INET, SOCK_DGRAM, 0);
184 char* strerr = strerror (errno);
185 throw new java::net::SocketException (JvNewStringUTF (strerr));
188 fd = new java::io::FileDescriptor (sock);
192 java::net::PlainDatagramSocketImpl::bind (jint lport,
193 java::net::InetAddress *host)
195 // FIXME: prob. need to do a setsockopt with SO_BROADCAST to allow multicast.
197 struct sockaddr *ptr = (struct sockaddr *) &u.address;
198 // FIXME: Use getaddrinfo() to get actual protocol instead of assuming ipv4.
199 jbyteArray haddress = host->addr;
200 jbyte *bytes = elements (haddress);
201 int len = haddress->length;
205 u.address.sin_family = AF_INET;
207 memcpy (&u.address.sin_addr, bytes, len);
209 u.address.sin_addr.s_addr = htonl (INADDR_ANY);
210 len = sizeof (struct sockaddr_in);
211 u.address.sin_port = htons (lport);
216 u.address6.sin6_family = AF_INET6;
217 memcpy (&u.address6.sin6_addr, bytes, len);
218 len = sizeof (struct sockaddr_in6);
219 u.address6.sin6_port = htons (lport);
223 throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
225 if (_Jv_bind (fnum, ptr, len) == 0)
227 socklen_t addrlen = sizeof(u);
230 else if (::getsockname (fnum, (sockaddr*) &u, &addrlen) == 0)
231 localPort = ntohs (u.address.sin_port);
237 char* strerr = strerror (errno);
238 throw new java::net::BindException (JvNewStringUTF (strerr));
242 java::net::PlainDatagramSocketImpl::peek (java::net::InetAddress *i)
244 // FIXME: Deal with Multicast and if the socket is connected.
246 socklen_t addrlen = sizeof(u);
248 ::recvfrom (fnum, (char *) NULL, 0, MSG_PEEK, (sockaddr*) &u,
252 // FIXME: Deal with Multicast addressing and if the socket is connected.
255 if (u.address.sin_family == AF_INET)
257 raddr = JvNewByteArray (4);
258 memcpy (elements (raddr), &u.address.sin_addr, 4);
259 rport = ntohs (u.address.sin_port);
262 else if (u.address.sin_family == AF_INET6)
264 raddr = JvNewByteArray (16);
265 memcpy (elements (raddr), &u.address6.sin6_addr, 16);
266 rport = ntohs (u.address6.sin6_port);
270 throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
275 char* strerr = strerror (errno);
276 throw new java::io::IOException (JvNewStringUTF (strerr));
280 java::net::PlainDatagramSocketImpl::send (java::net::DatagramPacket *p)
282 // FIXME: Deal with Multicast and if the socket is connected.
283 jint rport = p->getPort();
285 jbyteArray haddress = p->getAddress()->addr;
286 jbyte *bytes = elements (haddress);
287 int len = haddress->length;
288 struct sockaddr *ptr = (struct sockaddr *) &u.address;
289 jbyte *dbytes = elements (p->getData());
292 u.address.sin_family = AF_INET;
293 memcpy (&u.address.sin_addr, bytes, len);
294 len = sizeof (struct sockaddr_in);
295 u.address.sin_port = htons (rport);
300 u.address6.sin6_family = AF_INET6;
301 memcpy (&u.address6.sin6_addr, bytes, len);
302 len = sizeof (struct sockaddr_in6);
303 u.address6.sin6_port = htons (rport);
307 throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
309 if (::sendto (fnum, (char *) dbytes, p->getLength(), 0, ptr, len) >= 0)
312 char* strerr = strerror (errno);
313 throw new java::io::IOException (JvNewStringUTF (strerr));
317 java::net::PlainDatagramSocketImpl::receive (java::net::DatagramPacket *p)
319 // FIXME: Deal with Multicast and if the socket is connected.
321 socklen_t addrlen = sizeof(u);
322 jbyte *dbytes = elements (p->getData());
325 // Do timeouts via select since SO_RCVTIMEO is not always available.
332 tv.tv_sec = timeout / 1000;
333 tv.tv_usec = (timeout % 1000) * 1000;
335 if ((retval = _Jv_select (fnum + 1, &rset, NULL, NULL, &tv)) < 0)
337 else if (retval == 0)
338 throw new java::io::InterruptedIOException ();
342 ::recvfrom (fnum, (char *) dbytes, p->getLength(), 0, (sockaddr*) &u,
346 // FIXME: Deal with Multicast addressing and if the socket is connected.
349 if (u.address.sin_family == AF_INET)
351 raddr = JvNewByteArray (4);
352 memcpy (elements (raddr), &u.address.sin_addr, 4);
353 rport = ntohs (u.address.sin_port);
356 else if (u.address.sin_family == AF_INET6)
358 raddr = JvNewByteArray (16);
359 memcpy (elements (raddr), &u.address6.sin6_addr, 16);
360 rport = ntohs (u.address6.sin6_port);
364 throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
366 p->setAddress (new InetAddress (raddr, NULL));
368 p->setLength ((jint) retlen);
371 char* strerr = strerror (errno);
372 throw new java::io::IOException (JvNewStringUTF (strerr));
376 java::net::PlainDatagramSocketImpl::setTimeToLive (jint ttl)
378 // Assumes IPPROTO_IP rather than IPPROTO_IPV6 since socket created is IPv4.
379 char val = (char) ttl;
380 socklen_t val_len = sizeof(val);
381 if (::setsockopt (fnum, IPPROTO_IP, IP_MULTICAST_TTL, &val, val_len) == 0)
384 char* strerr = strerror (errno);
385 throw new java::io::IOException (JvNewStringUTF (strerr));
389 java::net::PlainDatagramSocketImpl::getTimeToLive ()
391 // Assumes IPPROTO_IP rather than IPPROTO_IPV6 since socket created is IPv4.
393 socklen_t val_len = sizeof(val);
394 if (::getsockopt (fnum, IPPROTO_IP, IP_MULTICAST_TTL, &val, &val_len) == 0)
395 return ((int) val) & 0xFF;
397 char* strerr = strerror (errno);
398 throw new java::io::IOException (JvNewStringUTF (strerr));
402 java::net::PlainDatagramSocketImpl::mcastGrp (java::net::InetAddress *inetaddr,
406 jbyteArray haddress = inetaddr->addr;
407 jbyte *bytes = elements (haddress);
408 int len = haddress->length;
413 #if HAVE_STRUCT_IP_MREQ
417 opname = join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
418 memcpy (&u.mreq.imr_multiaddr, bytes, len);
419 // FIXME: If a non-default interface is set, use it; see Stevens p. 501.
420 // Maybe not, see note in last paragraph at bottom of Stevens p. 497.
421 u.mreq.imr_interface.s_addr = htonl (INADDR_ANY);
422 len = sizeof (struct ip_mreq);
423 ptr = (const char *) &u.mreq;
426 #if HAVE_STRUCT_IPV6_MREQ
429 level = IPPROTO_IPV6;
431 /* Prefer new RFC 2553 names. */
432 #ifndef IPV6_JOIN_GROUP
433 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
435 #ifndef IPV6_LEAVE_GROUP
436 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
439 opname = join ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP;
440 memcpy (&u.mreq6.ipv6mr_multiaddr, bytes, len);
441 // FIXME: If a non-default interface is set, use it; see Stevens p. 501.
442 // Maybe not, see note in last paragraph at bottom of Stevens p. 497.
443 u.mreq6.ipv6mr_interface = 0;
444 len = sizeof (struct ipv6_mreq);
445 ptr = (const char *) &u.mreq6;
449 throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
451 if (::setsockopt (fnum, level, opname, ptr, len) == 0)
454 char* strerr = strerror (errno);
455 throw new java::io::IOException (JvNewStringUTF (strerr));
459 java::net::PlainDatagramSocketImpl::setOption (jint optID,
460 java::lang::Object *value)
463 socklen_t val_len = sizeof (val);
465 if (_Jv_IsInstanceOf (value, &BooleanClass))
467 java::lang::Boolean *boolobj =
468 static_cast<java::lang::Boolean *> (value);
469 val = boolobj->booleanValue() ? 1 : 0;
471 else if (_Jv_IsInstanceOf (value, &IntegerClass))
473 java::lang::Integer *intobj =
474 static_cast<java::lang::Integer *> (value);
475 val = (int) intobj->intValue();
477 // Else assume value to be an InetAddress for use with IP_MULTICAST_IF.
481 case _Jv_TCP_NODELAY_ :
482 throw new java::net::SocketException (
483 JvNewStringUTF ("TCP_NODELAY not valid for UDP"));
485 case _Jv_SO_LINGER_ :
486 throw new java::net::SocketException (
487 JvNewStringUTF ("SO_LINGER not valid for UDP"));
489 case _Jv_SO_SNDBUF_ :
490 case _Jv_SO_RCVBUF_ :
491 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
493 optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
494 if (::setsockopt (fnum, SOL_SOCKET, opt, (char *) &val, val_len) != 0)
497 throw new java::lang::InternalError (
498 JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
501 case _Jv_SO_REUSEADDR_ :
502 #if defined(SO_REUSEADDR)
503 if (::setsockopt (fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
507 throw new java::lang::InternalError (
508 JvNewStringUTF ("SO_REUSEADDR not supported"));
511 case _Jv_SO_BINDADDR_ :
512 throw new java::net::SocketException (
513 JvNewStringUTF ("SO_BINDADDR: read only option"));
515 case _Jv_IP_MULTICAST_IF_ :
523 haddress = ((java::net::InetAddress *) value)->addr;
524 bytes = elements (haddress);
525 len = haddress->length;
529 opname = IP_MULTICAST_IF;
530 memcpy (&u.addr, bytes, len);
531 len = sizeof (struct in_addr);
532 ptr = (const char *) &u.addr;
534 // Tru64 UNIX V5.0 has struct sockaddr_in6, but no IPV6_MULTICAST_IF
535 #if defined (HAVE_INET6) && defined (IPV6_MULTICAST_IF)
538 level = IPPROTO_IPV6;
539 opname = IPV6_MULTICAST_IF;
540 memcpy (&u.addr6, bytes, len);
541 len = sizeof (struct in6_addr);
542 ptr = (const char *) &u.addr6;
547 new java::net::SocketException (JvNewStringUTF ("invalid length"));
549 if (::setsockopt (fnum, level, opname, ptr, len) != 0)
552 case _Jv_SO_TIMEOUT_ :
560 char* strerr = strerror (errno);
561 throw new java::net::SocketException (JvNewStringUTF (strerr));
565 java::net::PlainDatagramSocketImpl::getOption (jint optID)
568 socklen_t val_len = sizeof(val);
570 socklen_t addrlen = sizeof(u);
574 case _Jv_TCP_NODELAY_ :
575 throw new java::net::SocketException (
576 JvNewStringUTF ("TCP_NODELAY not valid for UDP"));
579 case _Jv_SO_LINGER_ :
580 throw new java::net::SocketException (
581 JvNewStringUTF ("SO_LINGER not valid for UDP"));
583 case _Jv_SO_RCVBUF_ :
584 case _Jv_SO_SNDBUF_ :
585 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
587 optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
588 if (::getsockopt (fnum, SOL_SOCKET, opt, (char *) &val, &val_len) != 0)
591 return new java::lang::Integer (val);
593 throw new java::lang::InternalError (
594 JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
597 case _Jv_SO_BINDADDR_:
598 // cache the local address
599 if (localAddress == NULL)
602 if (::getsockname (fnum, (sockaddr*) &u, &addrlen) != 0)
604 if (u.address.sin_family == AF_INET)
606 laddr = JvNewByteArray (4);
607 memcpy (elements (laddr), &u.address.sin_addr, 4);
610 else if (u.address.sin_family == AF_INET6)
612 laddr = JvNewByteArray (16);
613 memcpy (elements (laddr), &u.address6.sin6_addr, 16);
617 throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
618 localAddress = new java::net::InetAddress (laddr, NULL);
622 case _Jv_SO_REUSEADDR_ :
623 #if defined(SO_REUSEADDR)
624 if (::getsockopt (fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
627 return new java::lang::Boolean (val != 0);
629 throw new java::lang::InternalError (
630 JvNewStringUTF ("SO_REUSEADDR not supported"));
633 case _Jv_IP_MULTICAST_IF_ :
634 #ifdef HAVE_INET_NTOA
635 struct in_addr inaddr;
636 socklen_t inaddr_len;
639 inaddr_len = sizeof(inaddr);
640 if (::getsockopt (fnum, IPPROTO_IP, IP_MULTICAST_IF, (char *) &inaddr,
644 bytes = inet_ntoa (inaddr);
646 return java::net::InetAddress::getByName (JvNewStringLatin1 (bytes));
648 throw new java::net::SocketException (
649 JvNewStringUTF ("IP_MULTICAST_IF: not available - no inet_ntoa()"));
652 case _Jv_SO_TIMEOUT_ :
653 return new java::lang::Integer (timeout);
660 char* strerr = strerror (errno);
661 throw new java::net::SocketException (JvNewStringUTF (strerr));
664 #endif /* DISABLE_JAVA_NET */