1 /* Copyright (C) 1998, 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
12 #ifndef DISABLE_JAVA_NET
19 #define ENOPROTOOPT 109
21 #else /* USE_WINSOCK */
23 #include <sys/socket.h>
24 #include <netinet/in.h>
25 #include <netinet/tcp.h>
28 #endif /* USE_WINSOCK */
29 #endif /* DISABLE_JAVA_NET */
32 // Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2
37 #include <gcj/javaprims.h>
38 #include <java/io/IOException.h>
39 #include <java/io/FileDescriptor.h>
40 #include <java/io/InterruptedIOException.h>
41 #include <java/net/BindException.h>
42 #include <java/net/ConnectException.h>
43 #include <java/net/PlainSocketImpl.h>
44 #include <java/net/InetAddress.h>
45 #include <java/net/SocketException.h>
46 #include <java/lang/InternalError.h>
47 #include <java/lang/Object.h>
48 #include <java/lang/Boolean.h>
49 #include <java/lang/Class.h>
50 #include <java/lang/Integer.h>
52 #define BooleanClass _CL_Q34java4lang7Boolean
53 extern java::lang::Class BooleanClass
;
55 #ifdef DISABLE_JAVA_NET
58 java::net::PlainSocketImpl::create (jboolean
)
60 JvThrow (new java::io::IOException (JvNewStringLatin1 ("SocketImpl.create: unimplemented")));
64 java::net::PlainSocketImpl::bind (java::net::InetAddress
*, jint
)
66 JvThrow (new BindException (JvNewStringLatin1 ("SocketImpl.bind: unimplemented")));
70 java::net::PlainSocketImpl::connect (java::net::InetAddress
*, jint
)
72 JvThrow (new ConnectException (JvNewStringLatin1 ("SocketImpl.connect: unimplemented")));
76 java::net::PlainSocketImpl::listen (jint
)
78 JvThrow (new java::io::IOException (JvNewStringLatin1 ("SocketImpl.listen: unimplemented")));
82 java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl
*)
84 JvThrow (new java::io::IOException (JvNewStringLatin1 ("SocketImpl.accept: unimplemented")));
88 java::net::PlainSocketImpl::setOption (jint
, java::lang::Object
*)
90 JvThrow (new SocketException (JvNewStringLatin1 ("SocketImpl.setOption: unimplemented")));
94 java::net::PlainSocketImpl::getOption (jint
)
96 JvThrow (new SocketException (JvNewStringLatin1 ("SocketImpl.getOption: unimplemented")));
99 #else /* DISABLE_JAVA_NET */
101 #ifndef HAVE_SOCKLEN_T
102 typedef int socklen_t
;
107 struct sockaddr_in address
;
109 struct sockaddr_in6 address6
;
114 java::net::PlainSocketImpl::create (jboolean stream
)
116 int sock
= ::socket (AF_INET
, stream
? SOCK_STREAM
: SOCK_DGRAM
, 0);
119 char* strerr
= strerror (errno
);
120 JvThrow (new java::io::IOException (JvNewStringUTF (strerr
)));
123 fd
= new java::io::FileDescriptor (sock
);
127 java::net::PlainSocketImpl::bind (java::net::InetAddress
*host
, jint lport
)
130 struct sockaddr
*ptr
= (struct sockaddr
*) &u
.address
;
131 jbyteArray haddress
= host
->address
;
132 jbyte
*bytes
= elements (haddress
);
133 int len
= haddress
->length
;
138 u
.address
.sin_family
= AF_INET
;
140 memcpy (&u
.address
.sin_addr
, bytes
, len
);
142 u
.address
.sin_addr
.s_addr
= htonl (INADDR_ANY
);
143 len
= sizeof (struct sockaddr_in
);
144 u
.address
.sin_port
= htons (lport
);
149 u
.address6
.sin6_family
= AF_INET6
;
150 memcpy (&u
.address6
.sin6_addr
, bytes
, len
);
151 len
= sizeof (struct sockaddr_in6
);
152 u
.address6
.sin6_port
= htons (lport
);
158 // Enable SO_REUSEADDR, so that servers can reuse ports left in TIME_WAIT.
159 ::setsockopt(fnum
, SOL_SOCKET
, SO_REUSEADDR
, (char *) &i
, sizeof(i
));
161 if (::bind (fnum
, ptr
, len
) == 0)
164 socklen_t addrlen
= sizeof(u
);
167 else if (::getsockname (fnum
, (sockaddr
*) &u
, &addrlen
) == 0)
168 localport
= ntohs (u
.address
.sin_port
);
174 char* strerr
= strerror (errno
);
175 JvThrow (new java::net::BindException (JvNewStringUTF (strerr
)));
179 java::net::PlainSocketImpl::connect (java::net::InetAddress
*host
, jint rport
)
182 socklen_t addrlen
= sizeof(u
);
183 jbyteArray haddress
= host
->address
;
184 jbyte
*bytes
= elements (haddress
);
185 int len
= haddress
->length
;
186 struct sockaddr
*ptr
= (struct sockaddr
*) &u
.address
;
189 u
.address
.sin_family
= AF_INET
;
190 memcpy (&u
.address
.sin_addr
, bytes
, len
);
191 len
= sizeof (struct sockaddr_in
);
192 u
.address
.sin_port
= htons (rport
);
197 u
.address6
.sin6_family
= AF_INET6
;
198 memcpy (&u
.address6
.sin6_addr
, bytes
, len
);
199 len
= sizeof (struct sockaddr_in6
);
200 u
.address6
.sin6_port
= htons (rport
);
205 if (::connect (fnum
, ptr
, len
) != 0)
209 // A bind may not have been done on this socket; if so, set localport now.
211 if (::getsockname (fnum
, (sockaddr
*) &u
, &addrlen
) == 0)
212 localport
= ntohs (u
.address
.sin_port
);
217 char* strerr
= strerror (errno
);
218 JvThrow (new java::net::ConnectException (JvNewStringUTF (strerr
)));
222 java::net::PlainSocketImpl::listen (jint backlog
)
224 if (::listen (fnum
, backlog
) != 0)
226 char* strerr
= strerror (errno
);
227 JvThrow (new java::io::IOException (JvNewStringUTF (strerr
)));
232 java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl
*s
)
235 socklen_t addrlen
= sizeof(u
);
238 // Do timeouts via select since SO_RCVTIMEO is not always available.
245 tv
.tv_sec
= timeout
/ 1000;
246 tv
.tv_usec
= (timeout
% 1000) * 1000;
248 if ((retval
= _Jv_select (fnum
+ 1, &rset
, NULL
, NULL
, &tv
)) < 0)
250 else if (retval
== 0)
251 JvThrow (new java::io::InterruptedIOException (
252 JvNewStringUTF("Accept timed out")));
255 new_socket
= ::accept (fnum
, (sockaddr
*) &u
, &addrlen
);
260 if (u
.address
.sin_family
== AF_INET
)
262 raddr
= JvNewByteArray (4);
263 memcpy (elements (raddr
), &u
.address
.sin_addr
, 4);
264 rport
= ntohs (u
.address
.sin_port
);
267 else if (u
.address
.sin_family
== AF_INET6
)
269 raddr
= JvNewByteArray (16);
270 memcpy (elements (raddr
), &u
.address6
.sin6_addr
, 16);
271 rport
= ntohs (u
.address6
.sin6_port
);
276 s
->fnum
= new_socket
;
277 s
->localport
= localport
;
278 s
->address
= new InetAddress (raddr
, NULL
);
280 s
->fd
= new java::io::FileDescriptor (new_socket
);
283 char* strerr
= strerror (errno
);
284 JvThrow (new java::io::IOException (JvNewStringUTF (strerr
)));
288 java::net::PlainSocketImpl::setOption (jint optID
, java::lang::Object
*value
)
291 socklen_t val_len
= sizeof (val
);
293 if (_Jv_IsInstanceOf (value
, &BooleanClass
))
295 java::lang::Boolean
*boolobj
=
296 static_cast<java::lang::Boolean
*> (value
);
297 if (boolobj
->booleanValue())
301 if (optID
== _Jv_SO_LINGER_
)
307 else // assume value is an Integer
309 java::lang::Integer
*intobj
=
310 static_cast<java::lang::Integer
*> (value
);
311 val
= (int) intobj
->intValue();
316 case _Jv_TCP_NODELAY_
:
318 if (::setsockopt (fnum
, IPPROTO_TCP
, TCP_NODELAY
, (char *) &val
,
322 JvThrow (new java::lang::InternalError (
323 JvNewStringUTF ("TCP_NODELAY not supported")));
324 #endif /* TCP_NODELAY */
326 case _Jv_SO_LINGER_
:
329 l_val
.l_onoff
= (val
!= -1);
330 l_val
.l_linger
= val
;
331 if (::setsockopt (fnum
, SOL_SOCKET
, SO_LINGER
, (char *) &l_val
,
335 JvThrow (new java::lang::InternalError (
336 JvNewStringUTF ("SO_LINGER not supported")));
337 #endif /* SO_LINGER */
339 case _Jv_SO_SNDBUF_
:
340 case _Jv_SO_RCVBUF_
:
341 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
343 optID
== _Jv_SO_SNDBUF_
? opt
= SO_SNDBUF
: opt
= SO_RCVBUF
;
344 if (::setsockopt (fnum
, SOL_SOCKET
, opt
, (char *) &val
, val_len
) != 0)
347 JvThrow (new java::lang::InternalError (
348 JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported")));
351 case _Jv_SO_BINDADDR_
:
352 JvThrow (new java::net::SocketException (
353 JvNewStringUTF ("SO_BINDADDR: read only option")));
355 case _Jv_IP_MULTICAST_IF_
:
356 JvThrow (new java::net::SocketException (
357 JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP")));
359 case _Jv_SO_REUSEADDR_
:
360 JvThrow (new java::net::SocketException (
361 JvNewStringUTF ("SO_REUSEADDR: not valid for TCP")));
363 case _Jv_SO_TIMEOUT_
:
371 char* strerr
= strerror (errno
);
372 JvThrow (new java::net::SocketException (JvNewStringUTF (strerr
)));
376 java::net::PlainSocketImpl::getOption (jint optID
)
379 socklen_t val_len
= sizeof(val
);
381 socklen_t addrlen
= sizeof(u
);
383 socklen_t l_val_len
= sizeof(l_val
);
388 case _Jv_TCP_NODELAY_
:
389 if (::getsockopt (fnum
, IPPROTO_TCP
, TCP_NODELAY
, (char *) &val
,
393 return new java::lang::Boolean (val
!= 0);
395 JvThrow (new java::lang::InternalError (
396 JvNewStringUTF ("TCP_NODELAY not supported")));
400 case _Jv_SO_LINGER_
:
402 if (::getsockopt (fnum
, SOL_SOCKET
, SO_LINGER
, (char *) &l_val
,
406 return new java::lang::Integer (l_val
.l_linger
);
408 return new java::lang::Boolean ((__java_boolean
)false);
410 JvThrow (new java::lang::InternalError (
411 JvNewStringUTF ("SO_LINGER not supported")));
414 case _Jv_SO_RCVBUF_
:
415 case _Jv_SO_SNDBUF_
:
416 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
418 optID
== _Jv_SO_SNDBUF_
? opt
= SO_SNDBUF
: opt
= SO_RCVBUF
;
419 if (::getsockopt (fnum
, SOL_SOCKET
, opt
, (char *) &val
, &val_len
) != 0)
422 return new java::lang::Integer (val
);
424 JvThrow (new java::lang::InternalError (
425 JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported")));
428 case _Jv_SO_BINDADDR_
:
429 // cache the local address
430 if (localAddress
== NULL
)
433 if (::getsockname (fnum
, (sockaddr
*) &u
, &addrlen
) != 0)
435 if (u
.address
.sin_family
== AF_INET
)
437 laddr
= JvNewByteArray (4);
438 memcpy (elements (laddr
), &u
.address
.sin_addr
, 4);
441 else if (u
.address
.sin_family
== AF_INET6
)
443 laddr
= JvNewByteArray (16);
444 memcpy (elements (laddr
), &u
.address6
.sin6_addr
, 16);
449 localAddress
= new java::net::InetAddress (laddr
, NULL
);
453 case _Jv_IP_MULTICAST_IF_
:
454 JvThrow (new java::net::SocketException (
455 JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP")));
457 case _Jv_SO_REUSEADDR_
:
458 JvThrow (new java::net::SocketException (
459 JvNewStringUTF ("SO_REUSEADDR: not valid for TCP")));
461 case _Jv_SO_TIMEOUT_
:
462 return new java::lang::Integer (timeout
);
469 char* strerr
= strerror (errno
);
470 JvThrow (new java::net::SocketException (JvNewStringUTF (strerr
)));
473 #endif /* DISABLE_JAVA_NET */