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();
145 // Set the SocketImpl's address and port fields before we try to
146 // connect. Note that the fact that these are set doesn't imply
147 // that we're actually connected to anything. We need to record
148 // this data before we attempt the connect, since non-blocking
149 // SocketChannels will use this and almost certainly throw timeout
155 socklen_t addrlen
= sizeof(u
);
156 jbyteArray haddress
= host
->addr
;
157 jbyte
*bytes
= elements (haddress
);
158 int len
= haddress
->length
;
159 struct sockaddr
*ptr
= (struct sockaddr
*) &u
.address
;
162 u
.address
.sin_family
= AF_INET
;
163 memcpy (&u
.address
.sin_addr
, bytes
, len
);
164 len
= sizeof (struct sockaddr_in
);
165 u
.address
.sin_port
= htons (rport
);
170 u
.address6
.sin6_family
= AF_INET6
;
171 memcpy (&u
.address6
.sin6_addr
, bytes
, len
);
172 len
= sizeof (struct sockaddr_in6
);
173 u
.address6
.sin6_port
= htons (rport
);
177 throw new ::java::net::SocketException (JvNewStringUTF ("invalid length"));
181 int flags
= ::fcntl (native_fd
, F_GETFL
);
182 ::fcntl (native_fd
, F_SETFL
, flags
| O_NONBLOCK
);
184 if ((_Jv_connect (native_fd
, ptr
, len
) != 0) && (errno
!= EINPROGRESS
))
190 FD_SET(native_fd
, &fset
);
191 tv
.tv_sec
= timeout
/ 1000;
192 tv
.tv_usec
= (timeout
% 1000) * 1000;
195 if ((retval
= _Jv_select (native_fd
+ 1, &fset
, &fset
, NULL
, &tv
)) < 0)
197 else if (retval
== 0)
198 throw new ::java::net::SocketTimeoutException
199 (JvNewStringUTF ("Connect timed out"));
200 // Set the socket back into a blocking state.
201 ::fcntl (native_fd
, F_SETFL
, flags
);
205 if (_Jv_connect (native_fd
, ptr
, len
) != 0)
209 // A bind may not have been done on this socket; if so, set localport now.
212 if (::getsockname (native_fd
, (sockaddr
*) &u
, &addrlen
) == 0)
213 localport
= ntohs (u
.address
.sin_port
);
221 char* strerr
= strerror (errno
);
222 throw new ::java::net::ConnectException (JvNewStringUTF (strerr
));
226 gnu::java::net::PlainSocketImpl::listen (jint backlog
)
228 if (::listen (native_fd
, backlog
) != 0)
230 char* strerr
= strerror (errno
);
231 throw new ::java::io::IOException (JvNewStringUTF (strerr
));
236 throw_on_sock_closed (gnu::java::net::PlainSocketImpl
*soc_impl
)
238 // Avoid races from asynchronous close().
239 JvSynchronize
sync (soc_impl
);
240 if (soc_impl
->native_fd
== -1)
242 using namespace java::net
;
243 // Socket was closed.
244 SocketException
*se
=
245 new SocketException (JvNewStringUTF ("Socket Closed"));
251 gnu::java::net::PlainSocketImpl::accept (gnu::java::net::PlainSocketImpl
*s
)
254 socklen_t addrlen
= sizeof(u
);
257 // Do timeouts via select since SO_RCVTIMEO is not always available.
258 if (timeout
> 0 && native_fd
>= 0 && native_fd
< FD_SETSIZE
)
263 FD_SET(native_fd
, &fset
);
264 tv
.tv_sec
= timeout
/ 1000;
265 tv
.tv_usec
= (timeout
% 1000) * 1000;
267 if ((retval
= _Jv_select (native_fd
+ 1, &fset
, &fset
, NULL
, &tv
)) < 0)
269 else if (retval
== 0)
270 throw new ::java::net::SocketTimeoutException (
271 JvNewStringUTF("Accept timed out"));
274 new_socket
= _Jv_accept (native_fd
, (sockaddr
*) &u
, &addrlen
);
279 _Jv_platform_close_on_exec (new_socket
);
283 if (u
.address
.sin_family
== AF_INET
)
285 raddr
= JvNewByteArray (4);
286 memcpy (elements (raddr
), &u
.address
.sin_addr
, 4);
287 rport
= ntohs (u
.address
.sin_port
);
290 else if (u
.address
.sin_family
== AF_INET6
)
292 raddr
= JvNewByteArray (16);
293 memcpy (elements (raddr
), &u
.address6
.sin6_addr
, 16);
294 rport
= ntohs (u
.address6
.sin6_port
);
298 throw new ::java::net::SocketException (JvNewStringUTF ("invalid family"));
300 s
->native_fd
= new_socket
;
301 s
->localport
= localport
;
302 s
->address
= new ::java::net::InetAddress (raddr
, NULL
);
307 char* strerr
= strerror (errno
);
308 throw_on_sock_closed (this);
309 throw new ::java::io::IOException (JvNewStringUTF (strerr
));
312 // Close(shutdown) the socket.
314 gnu::java::net::PlainSocketImpl::close()
316 // Avoid races from asynchronous finalization.
317 JvSynchronize
sync (this);
319 // Should we use shutdown here? Yes.
320 // How would that effect so_linger? Uncertain.
321 ::shutdown (native_fd
, 2);
322 // Ignore errors in shutdown as we are closing and all the same
323 // errors are handled in the close.
324 int res
= _Jv_close (native_fd
);
328 // These three errors are not errors according to tests performed
329 // on the reference implementation.
330 if (errno
!= ENOTCONN
&& errno
!= ECONNRESET
&& errno
!= EBADF
)
331 throw new ::java::io::IOException (JvNewStringUTF (strerror (errno
)));
333 // Safe place to reset the file pointer.
339 write_helper (jint native_fd
, jbyte
*bytes
, jint len
);
341 // Write a byte to the socket.
343 gnu::java::net::PlainSocketImpl$
SocketOutputStream::write(jint b
)
345 jbyte data
= (jbyte
) b
;
346 write_helper (this$
0->native_fd
, &data
, 1);
349 // Write some bytes to the socket.
351 gnu::java::net::PlainSocketImpl$
SocketOutputStream::write(jbyteArray b
, jint offset
, jint len
)
354 throw new ::java::lang::NullPointerException
;
355 if (offset
< 0 || len
< 0 || offset
+ len
> JvGetArrayLength (b
))
356 throw new ::java::lang::ArrayIndexOutOfBoundsException
;
358 write_helper (this$
0->native_fd
, elements (b
) + offset
* sizeof (jbyte
), len
);
362 write_helper(jint native_fd
, jbyte
*bytes
, jint len
)
368 int r
= _Jv_write (native_fd
, bytes
, len
);
372 if (::java::lang::Thread::interrupted())
374 ::java::io::InterruptedIOException
*iioe
375 = new ::java::io::InterruptedIOException
376 (JvNewStringLatin1 (strerror (errno
)));
377 iioe
->bytesTransferred
= written
;
380 // Some errors should not cause exceptions.
381 if (errno
!= ENOTCONN
&& errno
!= ECONNRESET
&& errno
!= EBADF
)
382 throw new ::java::io::IOException (JvNewStringUTF (strerror (errno
)));
393 gnu::java::net::PlainSocketImpl::sendUrgentData (jint
)
395 throw new ::java::net::SocketException (JvNewStringLatin1 (
396 "PlainSocketImpl: sending of urgent data not supported by this socket"));
400 read_helper (gnu::java::net::PlainSocketImpl
*soc_impl
,
401 jbyte
*bytes
, jint count
);
403 // Read a single byte from the socket.
405 gnu::java::net::PlainSocketImpl$
SocketInputStream::read(void)
409 if (read_helper (this$
0, &data
, 1) == 1)
415 // Read count bytes into the buffer, starting at offset.
417 gnu::java::net::PlainSocketImpl$
SocketInputStream::read(jbyteArray buffer
,
422 throw new ::java::lang::NullPointerException
;
424 jsize bsize
= JvGetArrayLength (buffer
);
426 if (offset
< 0 || count
< 0 || offset
+ count
> bsize
)
427 throw new ::java::lang::ArrayIndexOutOfBoundsException
;
429 return read_helper (this$
0,
430 elements (buffer
) + offset
* sizeof (jbyte
), count
);
434 read_helper (gnu::java::net::PlainSocketImpl
*soc_impl
,
435 jbyte
*bytes
, jint count
)
437 // If zero bytes were requested, short circuit so that recv
438 // doesn't signal EOF.
442 // Do timeouts via select.
443 if (soc_impl
->timeout
> 0
444 && soc_impl
->native_fd
>= 0
445 && soc_impl
->native_fd
< FD_SETSIZE
)
447 // Create the file descriptor set.
450 FD_SET (soc_impl
->native_fd
, &read_fds
);
451 // Create the timeout struct based on our internal timeout value.
452 struct timeval timeout_value
;
453 timeout_value
.tv_sec
= soc_impl
->timeout
/ 1000;
454 timeout_value
.tv_usec
=(soc_impl
->timeout
% 1000) * 1000;
455 // Select on the fds.
457 _Jv_select (soc_impl
->native_fd
+ 1,
458 &read_fds
, NULL
, NULL
, &timeout_value
);
459 // We're only interested in the 0 return.
460 // error returns still require us to try to read
461 // the socket to see what happened.
464 ::java::net::SocketTimeoutException
*timeoutException
=
465 new ::java::net::SocketTimeoutException
466 (JvNewStringUTF ("Read timed out"));
467 throw timeoutException
;
472 int r
= ::recv (soc_impl
->native_fd
, (char *) bytes
, count
, 0);
476 throw_on_sock_closed (soc_impl
);
480 if (::java::lang::Thread::interrupted())
482 ::java::io::InterruptedIOException
*iioe
=
483 new ::java::io::InterruptedIOException
484 (JvNewStringUTF ("Read interrupted"));
485 iioe
->bytesTransferred
= r
== -1 ? 0 : r
;
490 throw_on_sock_closed (soc_impl
);
491 // Some errors cause us to return end of stream...
492 if (errno
== ENOTCONN
)
495 // Other errors need to be signalled.
496 throw new ::java::io::IOException (JvNewStringUTF (strerror (errno
)));
502 // How many bytes are available?
504 gnu::java::net::PlainSocketImpl::available(void)
506 #if defined(FIONREAD) || defined(HAVE_SELECT)
509 bool num_set
= false;
511 #if defined(FIONREAD)
512 r
= ::ioctl (native_fd
, FIONREAD
, &num
);
514 if (r
== -1 && errno
== ENOTTY
)
516 // If the ioctl doesn't work, we don't care.
522 #elif defined(HAVE_SELECT)
533 throw new ::java::io::IOException(JvNewStringUTF(strerror(errno
)));
536 // If we didn't get anything we can use select.
538 #if defined(HAVE_SELECT)
540 if (! num_set
&& native_fd
>= 0 && native_fd
< FD_SETSIZE
)
544 FD_SET (native_fd
, &rd
);
548 r
= _Jv_select (native_fd
+ 1, &rd
, NULL
, NULL
, &tv
);
551 num
= r
== 0 ? 0 : 1;
553 #endif /* HAVE_SELECT */
557 throw new ::java::io::IOException (JvNewStringUTF ("unimplemented"));
562 gnu::java::net::PlainSocketImpl::setOption (jint optID
, ::java::lang::Object
*value
)
565 socklen_t val_len
= sizeof (val
);
568 throw new ::java::net::SocketException (JvNewStringUTF ("Socket closed"));
570 if (_Jv_IsInstanceOf (value
, &::java::lang::Boolean::class$
))
572 ::java::lang::Boolean
*boolobj
=
573 static_cast< ::java::lang::Boolean
*> (value
);
574 if (boolobj
->booleanValue())
578 if (optID
== _Jv_SO_LINGER_
)
584 else if (_Jv_IsInstanceOf (value
, &::java::lang::Integer::class$
))
586 ::java::lang::Integer
*intobj
=
587 static_cast< ::java::lang::Integer
*> (value
);
588 val
= (int) intobj
->intValue();
592 throw new ::java::lang::IllegalArgumentException (
593 JvNewStringLatin1 ("`value' must be Boolean or Integer"));
598 case _Jv_TCP_NODELAY_
:
600 if (::setsockopt (native_fd
, IPPROTO_TCP
, TCP_NODELAY
, (char *) &val
,
604 throw new ::java::lang::InternalError
605 (JvNewStringUTF ("TCP_NODELAY not supported"));
606 #endif /* TCP_NODELAY */
609 case _Jv_SO_KEEPALIVE_
:
610 if (::setsockopt (native_fd
, SOL_SOCKET
, SO_KEEPALIVE
, (char *) &val
,
615 case _Jv_SO_BROADCAST_
:
616 throw new ::java::net::SocketException
617 (JvNewStringUTF ("SO_BROADCAST not valid for TCP"));
620 case _Jv_SO_OOBINLINE_
:
621 if (::setsockopt (native_fd
, SOL_SOCKET
, SO_OOBINLINE
, (char *) &val
,
626 case _Jv_SO_LINGER_
:
629 l_val
.l_onoff
= (val
!= -1);
630 l_val
.l_linger
= val
;
632 if (::setsockopt (native_fd
, SOL_SOCKET
, SO_LINGER
, (char *) &l_val
,
636 throw new ::java::lang::InternalError (
637 JvNewStringUTF ("SO_LINGER not supported"));
638 #endif /* SO_LINGER */
641 case _Jv_SO_SNDBUF_
:
642 case _Jv_SO_RCVBUF_
:
643 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
645 optID
== _Jv_SO_SNDBUF_
? opt
= SO_SNDBUF
: opt
= SO_RCVBUF
;
646 if (::setsockopt (native_fd
, SOL_SOCKET
, opt
, (char *) &val
, val_len
) != 0)
649 throw new ::java::lang::InternalError (
650 JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
654 case _Jv_SO_BINDADDR_
:
655 throw new ::java::net::SocketException (
656 JvNewStringUTF ("SO_BINDADDR: read only option"));
659 case _Jv_IP_MULTICAST_IF_
:
660 throw new ::java::net::SocketException (
661 JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"));
664 case _Jv_IP_MULTICAST_IF2_
:
665 throw new ::java::net::SocketException (
666 JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP"));
669 case _Jv_IP_MULTICAST_LOOP_
:
670 throw new ::java::net::SocketException (
671 JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP"));
675 if (::setsockopt (native_fd
, SOL_SOCKET
, IP_TOS
, (char *) &val
,
680 case _Jv_SO_REUSEADDR_
:
681 #if defined(SO_REUSEADDR)
682 if (::setsockopt (native_fd
, SOL_SOCKET
, SO_REUSEADDR
, (char *) &val
,
687 throw new ::java::lang::InternalError (
688 JvNewStringUTF ("SO_REUSEADDR not supported"));
691 case _Jv_SO_TIMEOUT_
:
700 char* strerr
= strerror (errno
);
701 throw new ::java::net::SocketException (JvNewStringUTF (strerr
));
704 ::java::lang::Object
*
705 gnu::java::net::PlainSocketImpl::getOption (jint optID
)
708 socklen_t val_len
= sizeof(val
);
710 socklen_t addrlen
= sizeof(u
);
712 socklen_t l_val_len
= sizeof(l_val
);
717 case _Jv_TCP_NODELAY_
:
718 if (::getsockopt (native_fd
, IPPROTO_TCP
, TCP_NODELAY
, (char *) &val
,
722 return new ::java::lang::Boolean (val
!= 0);
724 throw new ::java::lang::InternalError
725 (JvNewStringUTF ("TCP_NODELAY not supported"));
729 case _Jv_SO_LINGER_
:
731 if (::getsockopt (native_fd
, SOL_SOCKET
, SO_LINGER
, (char *) &l_val
,
736 return new ::java::lang::Integer (l_val
.l_linger
);
738 return new ::java::lang::Boolean ((jboolean
)false);
740 throw new ::java::lang::InternalError
741 (JvNewStringUTF ("SO_LINGER not supported"));
745 case _Jv_SO_KEEPALIVE_
:
746 if (::getsockopt (native_fd
, SOL_SOCKET
, SO_KEEPALIVE
, (char *) &val
,
750 return new ::java::lang::Boolean (val
!= 0);
752 case _Jv_SO_BROADCAST_
:
753 if (::getsockopt (native_fd
, SOL_SOCKET
, SO_BROADCAST
, (char *) &val
,
756 return new ::java::lang::Boolean ((jboolean
)val
);
758 case _Jv_SO_OOBINLINE_
:
759 if (::getsockopt (native_fd
, SOL_SOCKET
, SO_OOBINLINE
, (char *) &val
,
762 return new ::java::lang::Boolean ((jboolean
)val
);
764 case _Jv_SO_RCVBUF_
:
765 case _Jv_SO_SNDBUF_
:
766 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
768 optID
== _Jv_SO_SNDBUF_
? opt
= SO_SNDBUF
: opt
= SO_RCVBUF
;
769 if (::getsockopt (native_fd
, SOL_SOCKET
, opt
, (char *) &val
, &val_len
) != 0)
772 return new ::java::lang::Integer (val
);
774 throw new ::java::lang::InternalError
775 (JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
778 case _Jv_SO_BINDADDR_
:
779 // cache the local address
780 if (localAddress
== NULL
)
784 if (::getsockname (native_fd
, (sockaddr
*) &u
, &addrlen
) != 0)
787 if (u
.address
.sin_family
== AF_INET
)
789 laddr
= JvNewByteArray (4);
790 memcpy (elements (laddr
), &u
.address
.sin_addr
, 4);
793 else if (u
.address
.sin_family
== AF_INET6
)
795 laddr
= JvNewByteArray (16);
796 memcpy (elements (laddr
), &u
.address6
.sin6_addr
, 16);
800 throw new ::java::net::SocketException
801 (JvNewStringUTF ("invalid family"));
802 localAddress
= new ::java::net::InetAddress (laddr
, NULL
);
807 case _Jv_IP_MULTICAST_IF_
:
808 throw new ::java::net::SocketException
809 (JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"));
812 case _Jv_IP_MULTICAST_IF2_
:
813 throw new ::java::net::SocketException
814 (JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP"));
817 case _Jv_IP_MULTICAST_LOOP_
:
818 throw new ::java::net::SocketException
819 (JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP"));
823 if (::getsockopt (native_fd
, SOL_SOCKET
, IP_TOS
, (char *) &val
,
826 return new ::java::lang::Integer (val
);
829 case _Jv_SO_REUSEADDR_
:
830 #if defined(SO_REUSEADDR)
831 if (::getsockopt (native_fd
, SOL_SOCKET
, SO_REUSEADDR
, (char *) &val
,
835 throw new ::java::lang::InternalError (
836 JvNewStringUTF ("SO_REUSEADDR not supported"));
840 case _Jv_SO_TIMEOUT_
:
841 return new ::java::lang::Integer (timeout
);
849 char* strerr
= strerror (errno
);
850 throw new ::java::net::SocketException (JvNewStringUTF (strerr
));
854 gnu::java::net::PlainSocketImpl::shutdownInput (void)
856 if (::shutdown (native_fd
, 0))
857 throw new ::java::net::SocketException (JvNewStringUTF (strerror (errno
)));
861 gnu::java::net::PlainSocketImpl::shutdownOutput (void)
863 if (::shutdown (native_fd
, 1))
864 throw new ::java::net::SocketException (JvNewStringUTF (strerror (errno
)));