1 /* Copyright (C) 1998, 1999 Cygnus Solutions
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
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <netinet/in.h>
14 #include <netinet/tcp.h>
20 #include <javaprims.h>
21 #include <java/io/IOException.h>
22 #include <java/io/FileDescriptor.h>
23 #include <java/net/BindException.h>
24 #include <java/net/ConnectException.h>
25 #include <java/net/PlainSocketImpl.h>
26 #include <java/net/InetAddress.h>
27 #include <java/net/SocketException.h>
28 #include <java/lang/InternalError.h>
29 #include <java/lang/Object.h>
30 #include <java/lang/Boolean.h>
31 #include <java/lang/Class.h>
32 #include <java/lang/Integer.h>
34 #ifndef HAVE_SOCKLEN_T
35 typedef int socklen_t;
40 struct sockaddr_in address;
42 struct sockaddr_in6 address6;
47 java::net::PlainSocketImpl::create (jboolean stream)
49 int sock = ::socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0);
53 char* strerr = strerror (errno);
54 sprintf (msg, "SocketImpl.create: %.*s", 80, strerr);
55 JvThrow (new java::io::IOException (JvNewStringUTF (msg)));
58 fd = new java::io::FileDescriptor (sock);
62 java::net::PlainSocketImpl::bind (java::net::InetAddress *host, jint lport)
65 jbyteArray haddress = host->address;
66 jbyte *bytes = elements (haddress);
67 int len = haddress->length;
68 struct sockaddr *ptr = (struct sockaddr *) &u.address;
71 u.address.sin_family = AF_INET;
72 memcpy (&u.address.sin_addr, bytes, len);
73 len = sizeof (struct sockaddr_in);
74 u.address.sin_port = htons (lport);
79 u.address6.sin6_family = AF_INET6;
80 memcpy (&u.address6.sin6_addr, bytes, len);
81 len = sizeof (struct sockaddr_in6);
82 u.address6.sin6_port = htons (lport);
87 if (::bind (fnum, ptr, len) == 0)
95 char* strerr = strerror (errno);
96 sprintf (msg, "SocketImpl.bind: %.*s", 80, strerr);
97 JvThrow (new java::net::BindException (JvNewStringUTF (msg)));
101 java::net::PlainSocketImpl::connect (java::net::InetAddress *host, jint rport)
104 socklen_t addrlen = sizeof(u);
105 jbyteArray haddress = host->address;
106 jbyte *bytes = elements (haddress);
107 int len = haddress->length;
108 struct sockaddr *ptr = (struct sockaddr *) &u.address;
111 u.address.sin_family = AF_INET;
112 memcpy (&u.address.sin_addr, bytes, len);
113 len = sizeof (struct sockaddr_in);
114 u.address.sin_port = htons (rport);
119 u.address6.sin6_family = AF_INET6;
120 memcpy (&u.address6.sin6_addr, bytes, len);
121 len = sizeof (struct sockaddr_in6);
122 u.address6.sin6_port = htons (rport);
127 if (::connect (fnum, ptr, len) != 0)
131 if (::getsockname (fnum, (sockaddr*) &u, &addrlen) != 0)
133 localport = ntohs (u.address.sin_port);
137 char* strerr = strerror (errno);
138 sprintf (msg, "SocketImpl.connect: %.*s", 80, strerr);
139 JvThrow (new java::net::ConnectException (JvNewStringUTF (msg)));
143 java::net::PlainSocketImpl::listen (jint backlog)
145 if (::listen (fnum, backlog) != 0)
148 char* strerr = strerror (errno);
149 sprintf (msg, "SocketImpl.listen: %.*s", 80, strerr);
150 JvThrow (new java::io::IOException (JvNewStringUTF (msg)));
155 java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl *s)
158 socklen_t addrlen = sizeof(u);
159 int new_socket = ::accept (fnum, (sockaddr*) &u, &addrlen);
164 if (u.address.sin_family == AF_INET)
166 raddr = JvNewByteArray (4);
167 memcpy (elements (raddr), &u.address.sin_addr, 4);
168 rport = ntohs (u.address.sin_port);
171 else if (u.address.sin_family == AF_INET6)
173 raddr = JvNewByteArray (16);
174 memcpy (elements (raddr), &u.address6.sin6_addr, 16);
175 rport = ntohs (u.address6.sin6_port);
180 s->fnum = new_socket;
181 s->localport = localport;
182 s->address = new InetAddress (raddr, NULL);
184 s->fd = new java::io::FileDescriptor (new_socket);
188 char* strerr = strerror (errno);
189 sprintf (msg, "SocketImpl.accept: %.*s", 80, strerr);
190 JvThrow (new java::io::IOException (JvNewStringUTF (msg)));
194 java::net::PlainSocketImpl::setOption (jint optID, java::lang::Object *value)
197 socklen_t val_len = sizeof (val);
199 if ( _Jv_IsInstanceOf(value,
200 java::lang::Class::forName(JvNewStringUTF("java.lang.Boolean"))))
202 java::lang::Boolean *boolobj =
203 static_cast<java::lang::Boolean *> (value);
204 if (boolobj->booleanValue())
208 if (optID == _Jv_SO_LINGER_)
214 else // assume value is an Integer
216 java::lang::Integer *intobj =
217 static_cast<java::lang::Integer *> (value);
218 val = (int) intobj->intValue();
223 case _Jv_TCP_NODELAY_ :
225 if (::setsockopt (fnum, IPPROTO_TCP, TCP_NODELAY, (char *) &val,
229 JvThrow (new java::lang::InternalError (
230 JvNewStringUTF ("TCP_NODELAY not supported")));
231 #endif /* TCP_NODELAY */
233 case _Jv_SO_LINGER_ :
236 l_val.l_onoff = (val != -1);
237 l_val.l_linger = val;
238 if (::setsockopt (fnum, SOL_SOCKET, SO_LINGER, (char *) &l_val,
242 JvThrow (new java::lang::InternalError (
243 JvNewStringUTF ("SO_LINGER not supported")));
244 #endif /* SO_LINGER */
246 case _Jv_SO_SNDBUF_ :
247 case _Jv_SO_RCVBUF_ :
248 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
250 optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
251 if (::setsockopt (fnum, SOL_SOCKET, opt, (char *) &val, val_len) != 0)
254 JvThrow (new java::lang::InternalError (
255 JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported")));
258 case _Jv_SO_BINDADDR_ :
259 JvThrow (new java::net::SocketException (
260 JvNewStringUTF ("SO_BINDADDR: read only option")));
262 case _Jv_IP_MULTICAST_IF_ :
263 JvThrow (new java::lang::InternalError (
264 JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP")));
266 case _Jv_SO_REUSEADDR_ :
267 JvThrow (new java::lang::InternalError (
268 JvNewStringUTF ("SO_REUSEADDR: option not implemented")));
270 case _Jv_SO_TIMEOUT_ :
271 JvThrow (new java::lang::InternalError (
272 JvNewStringUTF ("SO_TIMEOUT: option not implemented")));
280 char* strerr = strerror (errno);
281 sprintf (msg, "SocketImpl.setOption: %.*s", 80, strerr);
282 JvThrow (new java::net::SocketException (JvNewStringUTF (msg)));
286 java::net::PlainSocketImpl::getOption (jint optID)
289 socklen_t val_len = sizeof(val);
291 socklen_t addrlen = sizeof(u);
293 socklen_t l_val_len = sizeof(l_val);
298 case _Jv_TCP_NODELAY_ :
299 if (::getsockopt (fnum, IPPROTO_TCP, TCP_NODELAY, (char *) &val,
303 return new java::lang::Boolean (val != 0);
305 JvThrow (new java::lang::InternalError (
306 JvNewStringUTF ("TCP_NODELAY not supported")));
310 case _Jv_SO_LINGER_ :
312 if (::getsockopt (fnum, SOL_SOCKET, SO_LINGER, (char *) &l_val,
316 return new java::lang::Integer (l_val.l_linger);
318 return new java::lang::Boolean (false);
320 JvThrow (new java::lang::InternalError (
321 JvNewStringUTF ("SO_LINGER not supported")));
324 case _Jv_SO_RCVBUF_ :
325 case _Jv_SO_SNDBUF_ :
326 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
328 optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
329 if (::getsockopt (fnum, SOL_SOCKET, opt, (char *) &val, &val_len) != 0)
332 return new java::lang::Integer (val);
334 JvThrow (new java::lang::InternalError (
335 JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported")));
338 case _Jv_SO_BINDADDR_:
340 if (::getsockname (fnum, (sockaddr*) &u, &addrlen) != 0)
342 if (u.address.sin_family == AF_INET)
344 laddr = JvNewByteArray (4);
345 memcpy (elements (laddr), &u.address.sin_addr, 4);
348 else if (u.address.sin_family == AF_INET6)
350 laddr = JvNewByteArray (16);
351 memcpy (elements (laddr), &u.address6.sin6_addr, 16);
356 return new java::net::InetAddress (laddr, NULL);
358 case _Jv_IP_MULTICAST_IF_ :
359 JvThrow (new java::lang::InternalError (
360 JvNewStringUTF ("IP_MULTICAST_IF: option not implemented")));
362 case _Jv_SO_REUSEADDR_ :
363 JvThrow (new java::lang::InternalError (
364 JvNewStringUTF ("SO_REUSEADDR: option not implemented")));
366 case _Jv_SO_TIMEOUT_ :
367 JvThrow (new java::lang::InternalError (
368 JvNewStringUTF ("SO_TIMEOUT: option not implemented")));
376 char* strerr = strerror (errno);
377 sprintf (msg, "SocketImpl.getOption: %.*s", 80, strerr);
378 JvThrow (new java::net::SocketException (JvNewStringUTF (msg)));