1 /* Copyright (C) 1998, 1999, 2000, 2002 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 #ifndef DISABLE_JAVA_NET
23 #define NATIVE_CLOSE(s) closesocket (s)
25 // These functions make the Win32 socket API look more POSIXy
27 write(int s
, void *buf
, int len
)
29 return send(s
, (char*)buf
, len
, 0);
33 read(int s
, void *buf
, int len
)
35 return recv(s
, (char*)buf
, len
, 0);
38 // these errors cannot occur on Win32
42 #define ENOPROTOOPT 109
46 #ifdef HAVE_SYS_IOCTL_H
47 #define BSD_COMP /* Get FIONREAD on Solaris2. */
48 #include <sys/ioctl.h>
51 // Pick up FIONREAD on Solaris 2.5.
52 #ifdef HAVE_SYS_FILIO_H
53 #include <sys/filio.h>
56 #include <sys/socket.h>
57 #include <netinet/in.h>
58 #include <netinet/tcp.h>
62 #define NATIVE_CLOSE(s) ::close (s)
65 #endif /* DISABLE_JAVA_NET */
68 // Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2
72 #ifndef HAVE_SOCKLEN_T
73 typedef int socklen_t
;
76 #ifndef DISABLE_JAVA_NET
78 // Avoid macro definitions of bind, connect from system headers, e.g. on
79 // Solaris 7 with _XOPEN_SOURCE. FIXME
81 _Jv_bind (int fd
, struct sockaddr
*addr
, int addrlen
)
83 return ::bind (fd
, addr
, addrlen
);
91 _Jv_connect (int fd
, struct sockaddr
*addr
, int addrlen
)
93 return ::connect (fd
, addr
, addrlen
);
100 // Same problem with accept on Tru64 UNIX with _POSIX_PII_SOCKET
102 _Jv_accept (int fd
, struct sockaddr
*addr
, socklen_t
*addrlen
)
104 return ::accept (fd
, addr
, addrlen
);
111 #endif /* DISABLE_JAVA_NET */
114 #include <gcj/javaprims.h>
115 #include <java/io/IOException.h>
116 #include <java/io/InterruptedIOException.h>
117 #include <java/net/BindException.h>
118 #include <java/net/ConnectException.h>
119 #include <java/net/PlainSocketImpl.h>
120 #include <java/net/InetAddress.h>
121 #include <java/net/InetSocketAddress.h>
122 #include <java/net/SocketException.h>
123 #include <java/net/SocketTimeoutException.h>
124 #include <java/lang/InternalError.h>
125 #include <java/lang/Object.h>
126 #include <java/lang/Boolean.h>
127 #include <java/lang/Class.h>
128 #include <java/lang/Integer.h>
129 #include <java/lang/Thread.h>
130 #include <java/lang/NullPointerException.h>
131 #include <java/lang/ArrayIndexOutOfBoundsException.h>
132 #include <java/lang/IllegalArgumentException.h>
134 #ifdef DISABLE_JAVA_NET
137 java::net::PlainSocketImpl::create (jboolean
)
139 throw new java::io::IOException (
140 JvNewStringLatin1 ("SocketImpl.create: unimplemented"));
144 java::net::PlainSocketImpl::bind (java::net::InetAddress
*, jint
)
146 throw new BindException (
147 JvNewStringLatin1 ("SocketImpl.bind: unimplemented"));
151 java::net::PlainSocketImpl::connect (java::net::SocketAddress
*, jint
)
153 throw new ConnectException (
154 JvNewStringLatin1 ("SocketImpl.connect: unimplemented"));
158 java::net::PlainSocketImpl::listen (jint
)
160 throw new java::io::IOException (
161 JvNewStringLatin1 ("SocketImpl.listen: unimplemented"));
165 java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl
*)
167 throw new java::io::IOException (
168 JvNewStringLatin1 ("SocketImpl.accept: unimplemented"));
172 java::net::PlainSocketImpl::setOption (jint
, java::lang::Object
*)
174 throw new SocketException (
175 JvNewStringLatin1 ("SocketImpl.setOption: unimplemented"));
179 java::net::PlainSocketImpl::getOption (jint
)
181 throw new SocketException (
182 JvNewStringLatin1 ("SocketImpl.getOption: unimplemented"));
186 java::net::PlainSocketImpl::read(void)
188 throw new SocketException (
189 JvNewStringLatin1 ("SocketImpl.read: unimplemented"));
193 java::net::PlainSocketImpl::read(jbyteArray buffer
, jint offset
, jint count
)
195 throw new SocketException (
196 JvNewStringLatin1 ("SocketImpl.read: unimplemented"));
200 java::net::PlainSocketImpl::write(jint b
)
202 throw new SocketException (
203 JvNewStringLatin1 ("SocketImpl.write: unimplemented"));
207 java::net::PlainSocketImpl::write(jbyteArray b
, jint offset
, jint len
)
209 throw new SocketException (
210 JvNewStringLatin1 ("SocketImpl.write: unimplemented"));
214 java::net::PlainSocketImpl::sendUrgentData(jint data
)
216 throw new SocketException (
217 JvNewStringLatin1 ("SocketImpl.sendUrgentData: unimplemented"));
221 java::net::PlainSocketImpl::available(void)
223 throw new SocketException (
224 JvNewStringLatin1 ("SocketImpl.available: unimplemented"));
228 java::net::PlainSocketImpl::close(void)
230 throw new SocketException (
231 JvNewStringLatin1 ("SocketImpl.close: unimplemented"));
235 java::net::PlainSocketImpl::shutdownInput (void)
237 throw new SocketException (
238 JvNewStringLatin1 ("SocketImpl.shutdownInput: unimplemented"));
242 java::net::PlainSocketImpl::shutdownOutput (void)
244 throw new SocketException (
245 JvNewStringLatin1 ("SocketImpl.shutdownOutput: unimplemented"));
248 #else /* DISABLE_JAVA_NET */
252 struct sockaddr_in address
;
254 struct sockaddr_in6 address6
;
259 java::net::PlainSocketImpl::create (jboolean stream
)
261 int sock
= ::socket (AF_INET
, stream
? SOCK_STREAM
: SOCK_DGRAM
, 0);
264 char* strerr
= strerror (errno
);
265 throw new java::io::IOException (JvNewStringUTF (strerr
));
268 _Jv_platform_close_on_exec (sock
);
270 // We use fnum in place of fd here. From leaving fd null we avoid
271 // the double close problem in FileDescriptor.finalize.
276 java::net::PlainSocketImpl::bind (java::net::InetAddress
*host
, jint lport
)
279 struct sockaddr
*ptr
= (struct sockaddr
*) &u
.address
;
280 jbyteArray haddress
= host
->addr
;
281 jbyte
*bytes
= elements (haddress
);
282 int len
= haddress
->length
;
287 u
.address
.sin_family
= AF_INET
;
289 memcpy (&u
.address
.sin_addr
, bytes
, len
);
291 u
.address
.sin_addr
.s_addr
= htonl (INADDR_ANY
);
292 len
= sizeof (struct sockaddr_in
);
293 u
.address
.sin_port
= htons (lport
);
298 u
.address6
.sin6_family
= AF_INET6
;
299 memcpy (&u
.address6
.sin6_addr
, bytes
, len
);
300 len
= sizeof (struct sockaddr_in6
);
301 u
.address6
.sin6_port
= htons (lport
);
305 throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
307 // Enable SO_REUSEADDR, so that servers can reuse ports left in TIME_WAIT.
308 ::setsockopt(fnum
, SOL_SOCKET
, SO_REUSEADDR
, (char *) &i
, sizeof(i
));
310 if (_Jv_bind (fnum
, ptr
, len
) == 0)
313 socklen_t addrlen
= sizeof(u
);
316 else if (::getsockname (fnum
, (sockaddr
*) &u
, &addrlen
) == 0)
317 localport
= ntohs (u
.address
.sin_port
);
323 char* strerr
= strerror (errno
);
324 throw new java::net::BindException (JvNewStringUTF (strerr
));
328 java::net::PlainSocketImpl::connect (java::net::SocketAddress
*addr
,
331 java::net::InetSocketAddress
*tmp
= (java::net::InetSocketAddress
*) addr
;
332 java::net::InetAddress
*host
= tmp
->getAddress();
333 jint rport
= tmp
->getPort();
336 socklen_t addrlen
= sizeof(u
);
337 jbyteArray haddress
= host
->addr
;
338 jbyte
*bytes
= elements (haddress
);
339 int len
= haddress
->length
;
340 struct sockaddr
*ptr
= (struct sockaddr
*) &u
.address
;
343 u
.address
.sin_family
= AF_INET
;
344 memcpy (&u
.address
.sin_addr
, bytes
, len
);
345 len
= sizeof (struct sockaddr_in
);
346 u
.address
.sin_port
= htons (rport
);
351 u
.address6
.sin6_family
= AF_INET6
;
352 memcpy (&u
.address6
.sin6_addr
, bytes
, len
);
353 len
= sizeof (struct sockaddr_in6
);
354 u
.address6
.sin6_port
= htons (rport
);
358 throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
362 int flags
= ::fcntl (fnum
, F_GETFL
);
363 ::fcntl (fnum
, F_SETFL
, flags
| O_NONBLOCK
);
365 if ((_Jv_connect (fnum
, ptr
, len
) != 0) && (errno
!= EINPROGRESS
))
372 tv
.tv_sec
= timeout
/ 1000;
373 tv
.tv_usec
= (timeout
% 1000) * 1000;
376 if ((retval
= _Jv_select (fnum
+ 1, &rset
, NULL
, NULL
, &tv
)) < 0)
378 else if (retval
== 0)
379 throw new java::net::SocketTimeoutException (
380 JvNewStringUTF("Connect timed out"));
384 if (_Jv_connect (fnum
, ptr
, len
) != 0)
390 // A bind may not have been done on this socket; if so, set localport now.
393 if (::getsockname (fnum
, (sockaddr
*) &u
, &addrlen
) == 0)
394 localport
= ntohs (u
.address
.sin_port
);
400 char* strerr
= strerror (errno
);
401 throw new java::net::ConnectException (JvNewStringUTF (strerr
));
405 java::net::PlainSocketImpl::listen (jint backlog
)
407 if (::listen (fnum
, backlog
) != 0)
409 char* strerr
= strerror (errno
);
410 throw new java::io::IOException (JvNewStringUTF (strerr
));
415 java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl
*s
)
418 socklen_t addrlen
= sizeof(u
);
421 // FIXME: implement timeout support for Win32
423 // Do timeouts via select since SO_RCVTIMEO is not always available.
424 if (timeout
> 0 && fnum
>= 0 && fnum
< FD_SETSIZE
)
430 tv
.tv_sec
= timeout
/ 1000;
431 tv
.tv_usec
= (timeout
% 1000) * 1000;
433 if ((retval
= _Jv_select (fnum
+ 1, &rset
, NULL
, NULL
, &tv
)) < 0)
435 else if (retval
== 0)
436 throw new java::io::InterruptedIOException (
437 JvNewStringUTF("Accept timed out"));
441 new_socket
= _Jv_accept (fnum
, (sockaddr
*) &u
, &addrlen
);
445 _Jv_platform_close_on_exec (new_socket
);
449 if (u
.address
.sin_family
== AF_INET
)
451 raddr
= JvNewByteArray (4);
452 memcpy (elements (raddr
), &u
.address
.sin_addr
, 4);
453 rport
= ntohs (u
.address
.sin_port
);
456 else if (u
.address
.sin_family
== AF_INET6
)
458 raddr
= JvNewByteArray (16);
459 memcpy (elements (raddr
), &u
.address6
.sin6_addr
, 16);
460 rport
= ntohs (u
.address6
.sin6_port
);
464 throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
466 s
->fnum
= new_socket
;
467 s
->localport
= localport
;
468 s
->address
= new InetAddress (raddr
, NULL
);
472 char* strerr
= strerror (errno
);
473 throw new java::io::IOException (JvNewStringUTF (strerr
));
476 // Close(shutdown) the socket.
478 java::net::PlainSocketImpl::close()
480 // Avoid races from asynchronous finalization.
481 JvSynchronize
sync (this);
483 // should we use shutdown here? how would that effect so_linger?
484 int res
= NATIVE_CLOSE (fnum
);
488 // These three errors are not errors according to tests performed
489 // on the reference implementation.
490 if (errno
!= ENOTCONN
&& errno
!= ECONNRESET
&& errno
!= EBADF
)
491 throw new java::io::IOException (JvNewStringUTF (strerror (errno
)));
493 // Safe place to reset the file pointer.
498 // Write a byte to the socket.
500 java::net::PlainSocketImpl::write(jint b
)
507 r
= ::write (fnum
, &d
, 1);
510 if (java::lang::Thread::interrupted())
512 java::io::InterruptedIOException
*iioe
513 = new java::io::InterruptedIOException
514 (JvNewStringLatin1 (strerror (errno
)));
515 iioe
->bytesTransferred
= 0;
518 // Some errors should not cause exceptions.
519 if (errno
!= ENOTCONN
&& errno
!= ECONNRESET
&& errno
!= EBADF
)
520 throw new java::io::IOException (JvNewStringUTF (strerror (errno
)));
526 // Write some bytes to the socket.
528 java::net::PlainSocketImpl::write(jbyteArray b
, jint offset
, jint len
)
531 throw new java::lang::NullPointerException
;
532 if (offset
< 0 || len
< 0 || offset
+ len
> JvGetArrayLength (b
))
533 throw new java::lang::ArrayIndexOutOfBoundsException
;
535 jbyte
*bytes
= elements (b
) + offset
;
539 int r
= ::write (fnum
, bytes
, len
);
542 if (java::lang::Thread::interrupted())
544 java::io::InterruptedIOException
*iioe
545 = new java::io::InterruptedIOException
546 (JvNewStringLatin1 (strerror (errno
)));
547 iioe
->bytesTransferred
= written
;
550 // Some errors should not cause exceptions.
551 if (errno
!= ENOTCONN
&& errno
!= ECONNRESET
&& errno
!= EBADF
)
552 throw new java::io::IOException (JvNewStringUTF (strerror (errno
)));
562 java::net::PlainSocketImpl::sendUrgentData (jint
)
564 throw new SocketException (JvNewStringLatin1 (
565 "PlainSocketImpl: sending of urgent data not supported by this socket"));
568 // Read a single byte from the socket.
570 java::net::PlainSocketImpl::read(void)
574 // FIXME: implement timeout support for Win32
576 // Do timeouts via select.
577 if (timeout
> 0 && fnum
>= 0 && fnum
< FD_SETSIZE
)
579 // Create the file descriptor set.
582 FD_SET (fnum
,&read_fds
);
583 // Create the timeout struct based on our internal timeout value.
584 struct timeval timeout_value
;
585 timeout_value
.tv_sec
= timeout
/ 1000;
586 timeout_value
.tv_usec
= (timeout
% 1000) * 1000;
587 // Select on the fds.
588 int sel_retval
= _Jv_select (fnum
+ 1, &read_fds
, NULL
, NULL
, &timeout_value
);
589 // If select returns 0 we've waited without getting data...
590 // that means we've timed out.
592 throw new java::io::InterruptedIOException
593 (JvNewStringUTF ("read timed out") );
594 // If select returns ok we know we either got signalled or read some data...
595 // either way we need to try to read.
599 int r
= ::read (fnum
, &b
, 1);
603 if (java::lang::Thread::interrupted())
605 java::io::InterruptedIOException
*iioe
=
606 new java::io::InterruptedIOException
607 (JvNewStringUTF("read interrupted"));
608 iioe
->bytesTransferred
= r
== -1 ? 0 : r
;
613 // Some errors cause us to return end of stream...
614 if (errno
== ENOTCONN
)
616 // Other errors need to be signalled.
617 throw new java::io::IOException (JvNewStringUTF (strerror (errno
)));
622 // Read count bytes into the buffer, starting at offset.
624 java::net::PlainSocketImpl::read(jbyteArray buffer
, jint offset
, jint count
)
627 throw new java::lang::NullPointerException
;
628 jsize bsize
= JvGetArrayLength (buffer
);
629 if (offset
< 0 || count
< 0 || offset
+ count
> bsize
)
630 throw new java::lang::ArrayIndexOutOfBoundsException
;
631 jbyte
*bytes
= elements (buffer
) + offset
;
633 // FIXME: implement timeout support for Win32
635 // Do timeouts via select.
636 if (timeout
> 0 && fnum
>= 0 && fnum
< FD_SETSIZE
)
638 // Create the file descriptor set.
641 FD_SET (fnum
, &read_fds
);
642 // Create the timeout struct based on our internal timeout value.
643 struct timeval timeout_value
;
644 timeout_value
.tv_sec
= timeout
/ 1000;
645 timeout_value
.tv_usec
=(timeout
% 1000) * 1000;
646 // Select on the fds.
647 int sel_retval
= _Jv_select (fnum
+ 1, &read_fds
, NULL
, NULL
, &timeout_value
);
648 // We're only interested in the 0 return.
649 // error returns still require us to try to read
650 // the socket to see what happened.
653 java::io::InterruptedIOException
*iioe
=
654 new java::io::InterruptedIOException
655 (JvNewStringUTF ("read interrupted"));
656 iioe
->bytesTransferred
= 0;
663 int r
= ::recv (fnum
, (char *) bytes
, count
, 0);
666 if (java::lang::Thread::interrupted())
668 java::io::InterruptedIOException
*iioe
=
669 new java::io::InterruptedIOException
670 (JvNewStringUTF ("read interrupted"));
671 iioe
->bytesTransferred
= r
== -1 ? 0 : r
;
676 // Some errors cause us to return end of stream...
677 if (errno
== ENOTCONN
)
679 // Other errors need to be signalled.
680 throw new java::io::IOException (JvNewStringUTF (strerror (errno
)));
685 // How many bytes are available?
687 java::net::PlainSocketImpl::available(void)
689 #if defined(FIONREAD) || defined(HAVE_SELECT)
692 bool num_set
= false;
694 #if defined(FIONREAD)
695 r
= ::ioctl (fnum
, FIONREAD
, &num
);
696 if (r
== -1 && errno
== ENOTTY
)
698 // If the ioctl doesn't work, we don't care.
704 #elif defined(HAVE_SELECT)
715 throw new java::io::IOException(JvNewStringUTF(strerror(errno
)));
719 // If we didn't get anything we can use select.
721 #if defined(HAVE_SELECT)
723 if (! num_set
&& fnum
>= 0 && fnum
< FD_SETSIZE
)
731 r
= _Jv_select (fnum
+ 1, &rd
, NULL
, NULL
, &tv
);
734 num
= r
== 0 ? 0 : 1;
736 #endif /* HAVE_SELECT */
740 throw new java::io::IOException (JvNewStringUTF ("unimplemented"));
746 java::net::PlainSocketImpl::setOption (jint optID
, java::lang::Object
*value
)
749 socklen_t val_len
= sizeof (val
);
752 throw new java::net::SocketException (JvNewStringUTF ("Socket closed"));
754 if (_Jv_IsInstanceOf (value
, &java::lang::Boolean::class$
))
756 java::lang::Boolean
*boolobj
=
757 static_cast<java::lang::Boolean
*> (value
);
758 if (boolobj
->booleanValue())
762 if (optID
== _Jv_SO_LINGER_
)
768 else if (_Jv_IsInstanceOf (value
, &java::lang::Integer::class$
))
770 java::lang::Integer
*intobj
=
771 static_cast<java::lang::Integer
*> (value
);
772 val
= (int) intobj
->intValue();
776 throw new java::lang::IllegalArgumentException (JvNewStringLatin1 ("`value' must be Boolean or Integer"));
781 case _Jv_TCP_NODELAY_
:
783 if (::setsockopt (fnum
, IPPROTO_TCP
, TCP_NODELAY
, (char *) &val
,
787 throw new java::lang::InternalError (
788 JvNewStringUTF ("TCP_NODELAY not supported"));
789 #endif /* TCP_NODELAY */
792 case _Jv_SO_KEEPALIVE_
:
793 if (::setsockopt (fnum
, SOL_SOCKET
, SO_KEEPALIVE
, (char *) &val
,
798 case _Jv_SO_BROADCAST_
:
799 throw new java::net::SocketException (
800 JvNewStringUTF ("SO_BROADCAST not valid for TCP"));
803 case _Jv_SO_OOBINLINE_
:
804 if (::setsockopt (fnum
, SOL_SOCKET
, SO_OOBINLINE
, (char *) &val
,
809 case _Jv_SO_LINGER_
:
812 l_val
.l_onoff
= (val
!= -1);
813 l_val
.l_linger
= val
;
814 if (::setsockopt (fnum
, SOL_SOCKET
, SO_LINGER
, (char *) &l_val
,
818 throw new java::lang::InternalError (
819 JvNewStringUTF ("SO_LINGER not supported"));
820 #endif /* SO_LINGER */
822 case _Jv_SO_SNDBUF_
:
823 case _Jv_SO_RCVBUF_
:
824 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
826 optID
== _Jv_SO_SNDBUF_
? opt
= SO_SNDBUF
: opt
= SO_RCVBUF
;
827 if (::setsockopt (fnum
, SOL_SOCKET
, opt
, (char *) &val
, val_len
) != 0)
830 throw new java::lang::InternalError (
831 JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
834 case _Jv_SO_BINDADDR_
:
835 throw new java::net::SocketException (
836 JvNewStringUTF ("SO_BINDADDR: read only option"));
838 case _Jv_IP_MULTICAST_IF_
:
839 throw new java::net::SocketException (
840 JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"));
843 case _Jv_IP_MULTICAST_IF2_
:
844 throw new java::net::SocketException (
845 JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP"));
848 case _Jv_IP_MULTICAST_LOOP_
:
849 throw new java::net::SocketException (
850 JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP"));
854 if (::setsockopt (fnum
, SOL_SOCKET
, IP_TOS
, (char *) &val
,
859 case _Jv_SO_REUSEADDR_
:
860 throw new java::net::SocketException (
861 JvNewStringUTF ("SO_REUSEADDR: not valid for TCP"));
863 case _Jv_SO_TIMEOUT_
:
871 char* strerr
= strerror (errno
);
872 throw new java::net::SocketException (JvNewStringUTF (strerr
));
876 java::net::PlainSocketImpl::getOption (jint optID
)
879 socklen_t val_len
= sizeof(val
);
881 socklen_t addrlen
= sizeof(u
);
883 socklen_t l_val_len
= sizeof(l_val
);
888 case _Jv_TCP_NODELAY_
:
889 if (::getsockopt (fnum
, IPPROTO_TCP
, TCP_NODELAY
, (char *) &val
,
893 return new java::lang::Boolean (val
!= 0);
895 throw new java::lang::InternalError (
896 JvNewStringUTF ("TCP_NODELAY not supported"));
900 case _Jv_SO_LINGER_
:
902 if (::getsockopt (fnum
, SOL_SOCKET
, SO_LINGER
, (char *) &l_val
,
906 return new java::lang::Integer (l_val
.l_linger
);
908 return new java::lang::Boolean ((jboolean
)false);
910 throw new java::lang::InternalError (
911 JvNewStringUTF ("SO_LINGER not supported"));
915 case _Jv_SO_KEEPALIVE_
:
916 if (::getsockopt (fnum
, SOL_SOCKET
, SO_KEEPALIVE
, (char *) &val
,
920 return new java::lang::Boolean (val
!= 0);
922 case _Jv_SO_BROADCAST_
:
923 if (::getsockopt (fnum
, SOL_SOCKET
, SO_BROADCAST
, (char *) &val
,
926 return new java::lang::Boolean ((jboolean
)val
);
928 case _Jv_SO_OOBINLINE_
:
929 if (::getsockopt (fnum
, SOL_SOCKET
, SO_OOBINLINE
, (char *) &val
,
932 return new java::lang::Boolean ((jboolean
)val
);
934 case _Jv_SO_RCVBUF_
:
935 case _Jv_SO_SNDBUF_
:
936 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
938 optID
== _Jv_SO_SNDBUF_
? opt
= SO_SNDBUF
: opt
= SO_RCVBUF
;
939 if (::getsockopt (fnum
, SOL_SOCKET
, opt
, (char *) &val
, &val_len
) != 0)
942 return new java::lang::Integer (val
);
944 throw new java::lang::InternalError (
945 JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
948 case _Jv_SO_BINDADDR_
:
949 // cache the local address
950 if (localAddress
== NULL
)
953 if (::getsockname (fnum
, (sockaddr
*) &u
, &addrlen
) != 0)
955 if (u
.address
.sin_family
== AF_INET
)
957 laddr
= JvNewByteArray (4);
958 memcpy (elements (laddr
), &u
.address
.sin_addr
, 4);
961 else if (u
.address
.sin_family
== AF_INET6
)
963 laddr
= JvNewByteArray (16);
964 memcpy (elements (laddr
), &u
.address6
.sin6_addr
, 16);
969 new java::net::SocketException (JvNewStringUTF ("invalid family"));
970 localAddress
= new java::net::InetAddress (laddr
, NULL
);
974 case _Jv_IP_MULTICAST_IF_
:
975 throw new java::net::SocketException (
976 JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"));
979 case _Jv_IP_MULTICAST_IF2_
:
980 throw new java::net::SocketException (
981 JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP"));
984 case _Jv_IP_MULTICAST_LOOP_
:
985 throw new java::net::SocketException(
986 JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP"));
990 if (::getsockopt (fnum
, SOL_SOCKET
, IP_TOS
, (char *) &val
,
993 return new java::lang::Integer (val
);
996 case _Jv_SO_REUSEADDR_
:
997 throw new java::net::SocketException (
998 JvNewStringUTF ("SO_REUSEADDR: not valid for TCP"));
1000 case _Jv_SO_TIMEOUT_
:
1001 return new java::lang::Integer (timeout
);
1004 errno
= ENOPROTOOPT
;
1008 char* strerr
= strerror (errno
);
1009 throw new java::net::SocketException (JvNewStringUTF (strerr
));
1013 java::net::PlainSocketImpl::shutdownInput (void)
1015 if (::shutdown (fnum
, 0))
1016 throw new SocketException (JvNewStringUTF (strerror (errno
)));
1020 java::net::PlainSocketImpl::shutdownOutput (void)
1022 if (::shutdown (fnum
, 1))
1023 throw new SocketException (JvNewStringUTF (strerror (errno
)));
1026 #endif /* DISABLE_JAVA_NET */