1 /* Copyright (C) 2003, 2004, 2005 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
12 #ifdef HAVE_SYS_IOCTL_H
13 #define BSD_COMP /* Get FIONREAD on Solaris2. */
14 #include <sys/ioctl.h>
17 // Pick up FIONREAD on Solaris 2.5.
18 #ifdef HAVE_SYS_FILIO_H
19 #include <sys/filio.h>
22 #include <netinet/in.h>
23 #include <netinet/tcp.h>
28 // Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2
33 #include <gcj/javaprims.h>
34 #include <gnu/java/net/PlainSocketImpl.h>
35 #include <gnu/java/net/PlainSocketImpl$SocketInputStream.h>
36 #include <gnu/java/net/PlainSocketImpl$SocketOutputStream.h>
37 #include <java/io/IOException.h>
38 #include <java/io/InterruptedIOException.h>
39 #include <java/net/BindException.h>
40 #include <java/net/ConnectException.h>
41 #include <java/net/InetAddress.h>
42 #include <java/net/InetSocketAddress.h>
43 #include <java/net/SocketException.h>
44 #include <java/net/SocketTimeoutException.h>
45 #include <java/lang/InternalError.h>
46 #include <java/lang/Object.h>
47 #include <java/lang/Boolean.h>
48 #include <java/lang/Class.h>
49 #include <java/lang/Integer.h>
50 #include <java/lang/Thread.h>
51 #include <java/lang/NullPointerException.h>
52 #include <java/lang/ArrayIndexOutOfBoundsException.h>
53 #include <java/lang/IllegalArgumentException.h>
57 struct sockaddr_in address;
59 struct sockaddr_in6 address6;
64 gnu::java::net::PlainSocketImpl::create (jboolean stream)
66 int sock = _Jv_socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0);
70 char* strerr = strerror (errno);
71 throw new ::java::io::IOException (JvNewStringUTF (strerr));
74 _Jv_platform_close_on_exec (sock);
76 // We use native_fd in place of fd here. From leaving fd null we avoid
77 // the double close problem in FileDescriptor.finalize.
82 gnu::java::net::PlainSocketImpl::bind (::java::net::InetAddress *host, jint lport)
85 struct sockaddr *ptr = (struct sockaddr *) &u.address;
86 jbyteArray haddress = host->addr;
87 jbyte *bytes = elements (haddress);
88 int len = haddress->length;
93 u.address.sin_family = AF_INET;
96 memcpy (&u.address.sin_addr, bytes, len);
98 u.address.sin_addr.s_addr = htonl (INADDR_ANY);
100 len = sizeof (struct sockaddr_in);
101 u.address.sin_port = htons (lport);
106 u.address6.sin6_family = AF_INET6;
107 memcpy (&u.address6.sin6_addr, bytes, len);
108 len = sizeof (struct sockaddr_in6);
109 u.address6.sin6_port = htons (lport);
113 throw new ::java::net::SocketException (JvNewStringUTF ("invalid length"));
115 // Enable SO_REUSEADDR, so that servers can reuse ports left in TIME_WAIT.
116 ::setsockopt(native_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &i, sizeof(i));
118 if (_Jv_bind (native_fd, ptr, len) == 0)
120 socklen_t addrlen = sizeof(u);
124 else if (::getsockname (native_fd, (sockaddr*) &u, &addrlen) == 0)
125 localport = ntohs (u.address.sin_port);
133 char* strerr = strerror (errno);
134 throw new ::java::net::BindException (JvNewStringUTF (strerr));
138 gnu::java::net::PlainSocketImpl::connect (::java::net::SocketAddress *addr,
141 ::java::net::InetSocketAddress *tmp = (::java::net::InetSocketAddress*) addr;
142 ::java::net::InetAddress *host = tmp->getAddress();
143 jint rport = tmp->getPort();
146 socklen_t addrlen = sizeof(u);
147 jbyteArray haddress = host->addr;
148 jbyte *bytes = elements (haddress);
149 int len = haddress->length;
150 struct sockaddr *ptr = (struct sockaddr *) &u.address;
153 u.address.sin_family = AF_INET;
154 memcpy (&u.address.sin_addr, bytes, len);
155 len = sizeof (struct sockaddr_in);
156 u.address.sin_port = htons (rport);
161 u.address6.sin6_family = AF_INET6;
162 memcpy (&u.address6.sin6_addr, bytes, len);
163 len = sizeof (struct sockaddr_in6);
164 u.address6.sin6_port = htons (rport);
168 throw new ::java::net::SocketException (JvNewStringUTF ("invalid length"));
172 int flags = ::fcntl (native_fd, F_GETFL);
173 ::fcntl (native_fd, F_SETFL, flags | O_NONBLOCK);
175 if ((_Jv_connect (native_fd, ptr, len) != 0) && (errno != EINPROGRESS))
181 FD_SET(native_fd, &fset);
182 tv.tv_sec = timeout / 1000;
183 tv.tv_usec = (timeout % 1000) * 1000;
186 if ((retval = _Jv_select (native_fd + 1, &fset, &fset, NULL, &tv)) < 0)
188 else if (retval == 0)
189 throw new ::java::net::SocketTimeoutException
190 (JvNewStringUTF ("Connect timed out"));
191 // Set the socket back into a blocking state.
192 ::fcntl (native_fd, F_SETFL, flags);
196 if (_Jv_connect (native_fd, ptr, len) != 0)
203 // A bind may not have been done on this socket; if so, set localport now.
206 if (::getsockname (native_fd, (sockaddr*) &u, &addrlen) == 0)
207 localport = ntohs (u.address.sin_port);
215 char* strerr = strerror (errno);
216 throw new ::java::net::ConnectException (JvNewStringUTF (strerr));
220 gnu::java::net::PlainSocketImpl::listen (jint backlog)
222 if (::listen (native_fd, backlog) != 0)
224 char* strerr = strerror (errno);
225 throw new ::java::io::IOException (JvNewStringUTF (strerr));
230 gnu::java::net::PlainSocketImpl::accept (gnu::java::net::PlainSocketImpl *s)
233 socklen_t addrlen = sizeof(u);
236 // Do timeouts via select since SO_RCVTIMEO is not always available.
237 if (timeout > 0 && native_fd >= 0 && native_fd < FD_SETSIZE)
242 FD_SET(native_fd, &fset);
243 tv.tv_sec = timeout / 1000;
244 tv.tv_usec = (timeout % 1000) * 1000;
246 if ((retval = _Jv_select (native_fd + 1, &fset, &fset, NULL, &tv)) < 0)
248 else if (retval == 0)
249 throw new ::java::net::SocketTimeoutException (
250 JvNewStringUTF("Accept timed out"));
253 new_socket = _Jv_accept (native_fd, (sockaddr*) &u, &addrlen);
258 _Jv_platform_close_on_exec (new_socket);
262 if (u.address.sin_family == AF_INET)
264 raddr = JvNewByteArray (4);
265 memcpy (elements (raddr), &u.address.sin_addr, 4);
266 rport = ntohs (u.address.sin_port);
269 else if (u.address.sin_family == AF_INET6)
271 raddr = JvNewByteArray (16);
272 memcpy (elements (raddr), &u.address6.sin6_addr, 16);
273 rport = ntohs (u.address6.sin6_port);
277 throw new ::java::net::SocketException (JvNewStringUTF ("invalid family"));
279 s->native_fd = new_socket;
280 s->localport = localport;
281 s->address = new ::java::net::InetAddress (raddr, NULL);
286 char* strerr = strerror (errno);
287 throw new ::java::io::IOException (JvNewStringUTF (strerr));
290 // Close(shutdown) the socket.
292 gnu::java::net::PlainSocketImpl::close()
294 // Avoid races from asynchronous finalization.
295 JvSynchronize sync (this);
297 // should we use shutdown here? how would that effect so_linger?
298 int res = _Jv_close (native_fd);
302 // These three errors are not errors according to tests performed
303 // on the reference implementation.
304 if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF)
305 throw new ::java::io::IOException (JvNewStringUTF (strerror (errno)));
307 // Safe place to reset the file pointer.
313 write_helper (jint native_fd, jbyte *bytes, jint len);
315 // Write a byte to the socket.
317 gnu::java::net::PlainSocketImpl$SocketOutputStream::write(jint b)
319 jbyte data = (jbyte) b;
320 write_helper (this$0->native_fd, &data, 1);
323 // Write some bytes to the socket.
325 gnu::java::net::PlainSocketImpl$SocketOutputStream::write(jbyteArray b, jint offset, jint len)
328 throw new ::java::lang::NullPointerException;
329 if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
330 throw new ::java::lang::ArrayIndexOutOfBoundsException;
332 write_helper (this$0->native_fd, elements (b) + offset * sizeof (jbyte), len);
336 write_helper(jint native_fd, jbyte *bytes, jint len)
342 int r = _Jv_write (native_fd, bytes, len);
346 if (::java::lang::Thread::interrupted())
348 ::java::io::InterruptedIOException *iioe
349 = new ::java::io::InterruptedIOException
350 (JvNewStringLatin1 (strerror (errno)));
351 iioe->bytesTransferred = written;
354 // Some errors should not cause exceptions.
355 if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF)
356 throw new ::java::io::IOException (JvNewStringUTF (strerror (errno)));
367 gnu::java::net::PlainSocketImpl::sendUrgentData (jint)
369 throw new ::java::net::SocketException (JvNewStringLatin1 (
370 "PlainSocketImpl: sending of urgent data not supported by this socket"));
374 read_helper (jint native_fd, jint timeout, jbyte *bytes, jint count);
376 // Read a single byte from the socket.
378 gnu::java::net::PlainSocketImpl$SocketInputStream::read(void)
382 if (read_helper (this$0->native_fd, this$0->timeout, &data, 1) == 1)
388 // Read count bytes into the buffer, starting at offset.
390 gnu::java::net::PlainSocketImpl$SocketInputStream::read(jbyteArray buffer, jint offset,
394 throw new ::java::lang::NullPointerException;
396 jsize bsize = JvGetArrayLength (buffer);
398 if (offset < 0 || count < 0 || offset + count > bsize)
399 throw new ::java::lang::ArrayIndexOutOfBoundsException;
401 return read_helper (this$0->native_fd, this$0->timeout,
402 elements (buffer) + offset * sizeof (jbyte), count);
406 read_helper (jint native_fd, jint timeout, jbyte *bytes, jint count)
408 // If zero bytes were requested, short circuit so that recv
409 // doesn't signal EOF.
413 // Do timeouts via select.
414 if (timeout > 0 && native_fd >= 0 && native_fd < FD_SETSIZE)
416 // Create the file descriptor set.
419 FD_SET (native_fd, &read_fds);
420 // Create the timeout struct based on our internal timeout value.
421 struct timeval timeout_value;
422 timeout_value.tv_sec = timeout / 1000;
423 timeout_value.tv_usec =(timeout % 1000) * 1000;
424 // Select on the fds.
426 _Jv_select (native_fd + 1, &read_fds, NULL, NULL, &timeout_value);
427 // We're only interested in the 0 return.
428 // error returns still require us to try to read
429 // the socket to see what happened.
432 ::java::net::SocketTimeoutException *timeoutException =
433 new ::java::net::SocketTimeoutException
434 (JvNewStringUTF ("Read timed out"));
435 throw timeoutException;
440 int r = ::recv (native_fd, (char *) bytes, count, 0);
445 if (::java::lang::Thread::interrupted())
447 ::java::io::InterruptedIOException *iioe =
448 new ::java::io::InterruptedIOException
449 (JvNewStringUTF ("Read interrupted"));
450 iioe->bytesTransferred = r == -1 ? 0 : r;
455 // Some errors cause us to return end of stream...
456 if (errno == ENOTCONN)
459 // Other errors need to be signalled.
460 throw new ::java::io::IOException (JvNewStringUTF (strerror (errno)));
466 // How many bytes are available?
468 gnu::java::net::PlainSocketImpl::available(void)
470 #if defined(FIONREAD) || defined(HAVE_SELECT)
473 bool num_set = false;
475 #if defined(FIONREAD)
476 r = ::ioctl (native_fd, FIONREAD, &num);
478 if (r == -1 && errno == ENOTTY)
480 // If the ioctl doesn't work, we don't care.
486 #elif defined(HAVE_SELECT)
497 throw new ::java::io::IOException(JvNewStringUTF(strerror(errno)));
500 // If we didn't get anything we can use select.
502 #if defined(HAVE_SELECT)
504 if (! num_set && native_fd >= 0 && native_fd < FD_SETSIZE)
508 FD_SET (native_fd, &rd);
512 r = _Jv_select (native_fd + 1, &rd, NULL, NULL, &tv);
515 num = r == 0 ? 0 : 1;
517 #endif /* HAVE_SELECT */
521 throw new ::java::io::IOException (JvNewStringUTF ("unimplemented"));
526 gnu::java::net::PlainSocketImpl::setOption (jint optID, ::java::lang::Object *value)
529 socklen_t val_len = sizeof (val);
532 throw new ::java::net::SocketException (JvNewStringUTF ("Socket closed"));
534 if (_Jv_IsInstanceOf (value, &::java::lang::Boolean::class$))
536 ::java::lang::Boolean *boolobj =
537 static_cast< ::java::lang::Boolean *> (value);
538 if (boolobj->booleanValue())
542 if (optID == _Jv_SO_LINGER_)
548 else if (_Jv_IsInstanceOf (value, &::java::lang::Integer::class$))
550 ::java::lang::Integer *intobj =
551 static_cast< ::java::lang::Integer *> (value);
552 val = (int) intobj->intValue();
556 throw new ::java::lang::IllegalArgumentException (
557 JvNewStringLatin1 ("`value' must be Boolean or Integer"));
562 case _Jv_TCP_NODELAY_ :
564 if (::setsockopt (native_fd, IPPROTO_TCP, TCP_NODELAY, (char *) &val,
568 throw new ::java::lang::InternalError
569 (JvNewStringUTF ("TCP_NODELAY not supported"));
570 #endif /* TCP_NODELAY */
573 case _Jv_SO_KEEPALIVE_ :
574 if (::setsockopt (native_fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &val,
579 case _Jv_SO_BROADCAST_ :
580 throw new ::java::net::SocketException
581 (JvNewStringUTF ("SO_BROADCAST not valid for TCP"));
584 case _Jv_SO_OOBINLINE_ :
585 if (::setsockopt (native_fd, SOL_SOCKET, SO_OOBINLINE, (char *) &val,
590 case _Jv_SO_LINGER_ :
593 l_val.l_onoff = (val != -1);
594 l_val.l_linger = val;
596 if (::setsockopt (native_fd, SOL_SOCKET, SO_LINGER, (char *) &l_val,
600 throw new ::java::lang::InternalError (
601 JvNewStringUTF ("SO_LINGER not supported"));
602 #endif /* SO_LINGER */
605 case _Jv_SO_SNDBUF_ :
606 case _Jv_SO_RCVBUF_ :
607 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
609 optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
610 if (::setsockopt (native_fd, SOL_SOCKET, opt, (char *) &val, val_len) != 0)
613 throw new ::java::lang::InternalError (
614 JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
618 case _Jv_SO_BINDADDR_ :
619 throw new ::java::net::SocketException (
620 JvNewStringUTF ("SO_BINDADDR: read only option"));
623 case _Jv_IP_MULTICAST_IF_ :
624 throw new ::java::net::SocketException (
625 JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"));
628 case _Jv_IP_MULTICAST_IF2_ :
629 throw new ::java::net::SocketException (
630 JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP"));
633 case _Jv_IP_MULTICAST_LOOP_ :
634 throw new ::java::net::SocketException (
635 JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP"));
639 if (::setsockopt (native_fd, SOL_SOCKET, IP_TOS, (char *) &val,
644 case _Jv_SO_REUSEADDR_ :
645 #if defined(SO_REUSEADDR)
646 if (::setsockopt (native_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
651 throw new ::java::lang::InternalError (
652 JvNewStringUTF ("SO_REUSEADDR not supported"));
655 case _Jv_SO_TIMEOUT_ :
664 char* strerr = strerror (errno);
665 throw new ::java::net::SocketException (JvNewStringUTF (strerr));
668 ::java::lang::Object *
669 gnu::java::net::PlainSocketImpl::getOption (jint optID)
672 socklen_t val_len = sizeof(val);
674 socklen_t addrlen = sizeof(u);
676 socklen_t l_val_len = sizeof(l_val);
681 case _Jv_TCP_NODELAY_ :
682 if (::getsockopt (native_fd, IPPROTO_TCP, TCP_NODELAY, (char *) &val,
686 return new ::java::lang::Boolean (val != 0);
688 throw new ::java::lang::InternalError
689 (JvNewStringUTF ("TCP_NODELAY not supported"));
693 case _Jv_SO_LINGER_ :
695 if (::getsockopt (native_fd, SOL_SOCKET, SO_LINGER, (char *) &l_val,
700 return new ::java::lang::Integer (l_val.l_linger);
702 return new ::java::lang::Boolean ((jboolean)false);
704 throw new ::java::lang::InternalError
705 (JvNewStringUTF ("SO_LINGER not supported"));
709 case _Jv_SO_KEEPALIVE_ :
710 if (::getsockopt (native_fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &val,
714 return new ::java::lang::Boolean (val != 0);
716 case _Jv_SO_BROADCAST_ :
717 if (::getsockopt (native_fd, SOL_SOCKET, SO_BROADCAST, (char *) &val,
720 return new ::java::lang::Boolean ((jboolean)val);
722 case _Jv_SO_OOBINLINE_ :
723 if (::getsockopt (native_fd, SOL_SOCKET, SO_OOBINLINE, (char *) &val,
726 return new ::java::lang::Boolean ((jboolean)val);
728 case _Jv_SO_RCVBUF_ :
729 case _Jv_SO_SNDBUF_ :
730 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
732 optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
733 if (::getsockopt (native_fd, SOL_SOCKET, opt, (char *) &val, &val_len) != 0)
736 return new ::java::lang::Integer (val);
738 throw new ::java::lang::InternalError
739 (JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
742 case _Jv_SO_BINDADDR_:
743 // cache the local address
744 if (localAddress == NULL)
748 if (::getsockname (native_fd, (sockaddr*) &u, &addrlen) != 0)
751 if (u.address.sin_family == AF_INET)
753 laddr = JvNewByteArray (4);
754 memcpy (elements (laddr), &u.address.sin_addr, 4);
757 else if (u.address.sin_family == AF_INET6)
759 laddr = JvNewByteArray (16);
760 memcpy (elements (laddr), &u.address6.sin6_addr, 16);
764 throw new ::java::net::SocketException
765 (JvNewStringUTF ("invalid family"));
766 localAddress = new ::java::net::InetAddress (laddr, NULL);
771 case _Jv_IP_MULTICAST_IF_ :
772 throw new ::java::net::SocketException
773 (JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"));
776 case _Jv_IP_MULTICAST_IF2_ :
777 throw new ::java::net::SocketException
778 (JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP"));
781 case _Jv_IP_MULTICAST_LOOP_ :
782 throw new ::java::net::SocketException
783 (JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP"));
787 if (::getsockopt (native_fd, SOL_SOCKET, IP_TOS, (char *) &val,
790 return new ::java::lang::Integer (val);
793 case _Jv_SO_REUSEADDR_ :
794 #if defined(SO_REUSEADDR)
795 if (::getsockopt (native_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
799 throw new ::java::lang::InternalError (
800 JvNewStringUTF ("SO_REUSEADDR not supported"));
804 case _Jv_SO_TIMEOUT_ :
805 return new ::java::lang::Integer (timeout);
813 char* strerr = strerror (errno);
814 throw new ::java::net::SocketException (JvNewStringUTF (strerr));
818 gnu::java::net::PlainSocketImpl::shutdownInput (void)
820 if (::shutdown (native_fd, 0))
821 throw new ::java::net::SocketException (JvNewStringUTF (strerror (errno)));
825 gnu::java::net::PlainSocketImpl::shutdownOutput (void)
827 if (::shutdown (native_fd, 1))
828 throw new ::java::net::SocketException (JvNewStringUTF (strerror (errno)));