source: trunk/gcc/libjava/java/net/natPlainSocketImpl.cc

Last change on this file was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 26.1 KB
Line 
1/* Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation
2
3 This file is part of libgcj.
4
5This software is copyrighted work licensed under the terms of the
6Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
7details. */
8
9#include <config.h>
10#include <platform.h>
11
12#ifndef DISABLE_JAVA_NET
13
14#ifdef WIN32
15
16#include <windows.h>
17#include <winsock.h>
18#include <errno.h>
19#include <string.h>
20#undef STRICT
21#undef MAX_PRIORITY
22#undef MIN_PRIORITY
23#undef FIONREAD
24
25// These functions make the Win32 socket API look more POSIXy
26static inline int
27write(int s, void *buf, int len)
28{
29 return send(s, (char*)buf, len, 0);
30}
31
32static inline int
33read(int s, void *buf, int len)
34{
35 return recv(s, (char*)buf, len, 0);
36}
37
38// these errors cannot occur on Win32
39#else /* WIN32 */
40
41#ifdef HAVE_SYS_IOCTL_H
42#define BSD_COMP /* Get FIONREAD on Solaris2. */
43#include <sys/ioctl.h>
44#endif
45
46// Pick up FIONREAD on Solaris 2.5.
47#ifdef HAVE_SYS_FILIO_H
48#include <sys/filio.h>
49#endif
50
51#include <netinet/in.h>
52#include <netinet/tcp.h>
53#include <errno.h>
54#include <string.h>
55
56#endif /* WIN32 */
57#endif /* DISABLE_JAVA_NET */
58
59#if HAVE_BSTRING_H
60// Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2
61#include <bstring.h>
62#endif
63
64
65#include <gcj/cni.h>
66#include <gcj/javaprims.h>
67#include <java/io/IOException.h>
68#include <java/io/InterruptedIOException.h>
69#include <java/net/BindException.h>
70#include <java/net/ConnectException.h>
71#include <java/net/PlainSocketImpl.h>
72#include <java/net/InetAddress.h>
73#include <java/net/InetSocketAddress.h>
74#include <java/net/SocketException.h>
75#include <java/net/SocketTimeoutException.h>
76#include <java/lang/InternalError.h>
77#include <java/lang/Object.h>
78#include <java/lang/Boolean.h>
79#include <java/lang/Class.h>
80#include <java/lang/Integer.h>
81#include <java/lang/Thread.h>
82#include <java/lang/NullPointerException.h>
83#include <java/lang/ArrayIndexOutOfBoundsException.h>
84#include <java/lang/IllegalArgumentException.h>
85
86#ifdef DISABLE_JAVA_NET
87
88void
89java::net::PlainSocketImpl::create (jboolean)
90{
91 throw new java::io::IOException (
92 JvNewStringLatin1 ("SocketImpl.create: unimplemented"));
93}
94
95void
96java::net::PlainSocketImpl::bind (java::net::InetAddress *, jint)
97{
98 throw new BindException (
99 JvNewStringLatin1 ("SocketImpl.bind: unimplemented"));
100}
101
102void
103java::net::PlainSocketImpl::connect (java::net::SocketAddress *, jint)
104{
105 throw new ConnectException (
106 JvNewStringLatin1 ("SocketImpl.connect: unimplemented"));
107}
108
109void
110java::net::PlainSocketImpl::listen (jint)
111{
112 throw new java::io::IOException (
113 JvNewStringLatin1 ("SocketImpl.listen: unimplemented"));
114}
115
116void
117java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl *)
118{
119 throw new java::io::IOException (
120 JvNewStringLatin1 ("SocketImpl.accept: unimplemented"));
121}
122
123void
124java::net::PlainSocketImpl::setOption (jint, java::lang::Object *)
125{
126 throw new SocketException (
127 JvNewStringLatin1 ("SocketImpl.setOption: unimplemented"));
128}
129
130java::lang::Object *
131java::net::PlainSocketImpl::getOption (jint)
132{
133 throw new SocketException (
134 JvNewStringLatin1 ("SocketImpl.getOption: unimplemented"));
135}
136
137jint
138java::net::PlainSocketImpl::read(void)
139{
140 throw new SocketException (
141 JvNewStringLatin1 ("SocketImpl.read: unimplemented"));
142}
143
144jint
145java::net::PlainSocketImpl::read(jbyteArray buffer, jint offset, jint count)
146{
147 throw new SocketException (
148 JvNewStringLatin1 ("SocketImpl.read: unimplemented"));
149}
150
151void
152java::net::PlainSocketImpl::write(jint b)
153{
154 throw new SocketException (
155 JvNewStringLatin1 ("SocketImpl.write: unimplemented"));
156}
157
158void
159java::net::PlainSocketImpl::write(jbyteArray b, jint offset, jint len)
160{
161 throw new SocketException (
162 JvNewStringLatin1 ("SocketImpl.write: unimplemented"));
163}
164
165void
166java::net::PlainSocketImpl::sendUrgentData(jint data)
167{
168 throw new SocketException (
169 JvNewStringLatin1 ("SocketImpl.sendUrgentData: unimplemented"));
170}
171
172jint
173java::net::PlainSocketImpl::available(void)
174{
175 throw new SocketException (
176 JvNewStringLatin1 ("SocketImpl.available: unimplemented"));
177}
178
179void
180java::net::PlainSocketImpl::close(void)
181{
182 throw new SocketException (
183 JvNewStringLatin1 ("SocketImpl.close: unimplemented"));
184}
185
186void
187java::net::PlainSocketImpl::shutdownInput (void)
188{
189 throw new SocketException (
190 JvNewStringLatin1 ("SocketImpl.shutdownInput: unimplemented"));
191}
192
193void
194java::net::PlainSocketImpl::shutdownOutput (void)
195{
196 throw new SocketException (
197 JvNewStringLatin1 ("SocketImpl.shutdownOutput: unimplemented"));
198}
199
200#else /* DISABLE_JAVA_NET */
201
202union SockAddr
203{
204 struct sockaddr_in address;
205#ifdef HAVE_INET6
206 struct sockaddr_in6 address6;
207#endif
208};
209
210void
211java::net::PlainSocketImpl::create (jboolean stream)
212{
213 int sock = _Jv_socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0);
214
215 if (sock < 0)
216 {
217 char* strerr = strerror (errno);
218 throw new java::io::IOException (JvNewStringUTF (strerr));
219 }
220
221 _Jv_platform_close_on_exec (sock);
222
223 // We use fnum in place of fd here. From leaving fd null we avoid
224 // the double close problem in FileDescriptor.finalize.
225 fnum = sock;
226}
227
228void
229java::net::PlainSocketImpl::bind (java::net::InetAddress *host, jint lport)
230{
231 union SockAddr u;
232 struct sockaddr *ptr = (struct sockaddr *) &u.address;
233 jbyteArray haddress = host->addr;
234 jbyte *bytes = elements (haddress);
235 int len = haddress->length;
236 int i = 1;
237
238 if (len == 4)
239 {
240 u.address.sin_family = AF_INET;
241
242 if (host != NULL)
243 memcpy (&u.address.sin_addr, bytes, len);
244 else
245 u.address.sin_addr.s_addr = htonl (INADDR_ANY);
246
247 len = sizeof (struct sockaddr_in);
248 u.address.sin_port = htons (lport);
249 }
250#ifdef HAVE_INET6
251 else if (len == 16)
252 {
253 u.address6.sin6_family = AF_INET6;
254 memcpy (&u.address6.sin6_addr, bytes, len);
255 len = sizeof (struct sockaddr_in6);
256 u.address6.sin6_port = htons (lport);
257 }
258#endif
259 else
260 throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
261
262 // Enable SO_REUSEADDR, so that servers can reuse ports left in TIME_WAIT.
263 ::setsockopt(fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &i, sizeof(i));
264
265 if (_Jv_bind (fnum, ptr, len) == 0)
266 {
267 address = host;
268 socklen_t addrlen = sizeof(u);
269
270 if (lport != 0)
271 localport = lport;
272 else if (::getsockname (fnum, (sockaddr*) &u, &addrlen) == 0)
273 localport = ntohs (u.address.sin_port);
274 else
275 goto error;
276
277 return;
278 }
279
280 error:
281 char* strerr = strerror (errno);
282 throw new java::net::BindException (JvNewStringUTF (strerr));
283}
284
285void
286java::net::PlainSocketImpl::connect (java::net::SocketAddress *addr,
287 jint timeout)
288{
289 java::net::InetSocketAddress *tmp = (java::net::InetSocketAddress*) addr;
290 java::net::InetAddress *host = tmp->getAddress();
291 jint rport = tmp->getPort();
292
293 union SockAddr u;
294 socklen_t addrlen = sizeof(u);
295 jbyteArray haddress = host->addr;
296 jbyte *bytes = elements (haddress);
297 int len = haddress->length;
298 struct sockaddr *ptr = (struct sockaddr *) &u.address;
299 if (len == 4)
300 {
301 u.address.sin_family = AF_INET;
302 memcpy (&u.address.sin_addr, bytes, len);
303 len = sizeof (struct sockaddr_in);
304 u.address.sin_port = htons (rport);
305 }
306#ifdef HAVE_INET6
307 else if (len == 16)
308 {
309 u.address6.sin6_family = AF_INET6;
310 memcpy (&u.address6.sin6_addr, bytes, len);
311 len = sizeof (struct sockaddr_in6);
312 u.address6.sin6_port = htons (rport);
313 }
314#endif
315 else
316 throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
317
318// FIXME: implement timeout support for Win32
319#ifndef WIN32
320 if (timeout > 0)
321 {
322 int flags = ::fcntl (fnum, F_GETFL);
323 ::fcntl (fnum, F_SETFL, flags | O_NONBLOCK);
324
325 if ((_Jv_connect (fnum, ptr, len) != 0) && (errno != EINPROGRESS))
326 goto error;
327
328 fd_set rset;
329 struct timeval tv;
330 FD_ZERO(&rset);
331 FD_SET(fnum, &rset);
332 tv.tv_sec = timeout / 1000;
333 tv.tv_usec = (timeout % 1000) * 1000;
334 int retval;
335
336 if ((retval = _Jv_select (fnum + 1, &rset, NULL, NULL, &tv)) < 0)
337 goto error;
338 else if (retval == 0)
339 throw new java::net::SocketTimeoutException
340 (JvNewStringUTF ("Connect timed out"));
341 }
342 else
343#endif
344 {
345 if (_Jv_connect (fnum, ptr, len) != 0)
346 goto error;
347 }
348
349 address = host;
350 port = rport;
351
352 // A bind may not have been done on this socket; if so, set localport now.
353 if (localport == 0)
354 {
355 if (::getsockname (fnum, (sockaddr*) &u, &addrlen) == 0)
356 localport = ntohs (u.address.sin_port);
357 else
358 goto error;
359 }
360
361 return;
362
363 error:
364 char* strerr = strerror (errno);
365 throw new java::net::ConnectException (JvNewStringUTF (strerr));
366}
367
368void
369java::net::PlainSocketImpl::listen (jint backlog)
370{
371 if (::listen (fnum, backlog) != 0)
372 {
373 char* strerr = strerror (errno);
374 throw new java::io::IOException (JvNewStringUTF (strerr));
375 }
376}
377
378void
379java::net::PlainSocketImpl::accept (java::net::PlainSocketImpl *s)
380{
381 union SockAddr u;
382 socklen_t addrlen = sizeof(u);
383 int new_socket = 0;
384
385// FIXME: implement timeout support for Win32
386#ifndef WIN32
387 // Do timeouts via select since SO_RCVTIMEO is not always available.
388 if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
389 {
390 fd_set rset;
391 struct timeval tv;
392 FD_ZERO(&rset);
393 FD_SET(fnum, &rset);
394 tv.tv_sec = timeout / 1000;
395 tv.tv_usec = (timeout % 1000) * 1000;
396 int retval;
397 if ((retval = _Jv_select (fnum + 1, &rset, NULL, NULL, &tv)) < 0)
398 goto error;
399 else if (retval == 0)
400 throw new java::io::InterruptedIOException (
401 JvNewStringUTF("Accept timed out"));
402 }
403#endif /* WIN32 */
404
405 new_socket = _Jv_accept (fnum, (sockaddr*) &u, &addrlen);
406
407 if (new_socket < 0)
408 goto error;
409
410 _Jv_platform_close_on_exec (new_socket);
411
412 jbyteArray raddr;
413 jint rport;
414 if (u.address.sin_family == AF_INET)
415 {
416 raddr = JvNewByteArray (4);
417 memcpy (elements (raddr), &u.address.sin_addr, 4);
418 rport = ntohs (u.address.sin_port);
419 }
420#ifdef HAVE_INET6
421 else if (u.address.sin_family == AF_INET6)
422 {
423 raddr = JvNewByteArray (16);
424 memcpy (elements (raddr), &u.address6.sin6_addr, 16);
425 rport = ntohs (u.address6.sin6_port);
426 }
427#endif
428 else
429 throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
430
431 s->fnum = new_socket;
432 s->localport = localport;
433 s->address = new InetAddress (raddr, NULL);
434 s->port = rport;
435 return;
436
437 error:
438 char* strerr = strerror (errno);
439 throw new java::io::IOException (JvNewStringUTF (strerr));
440}
441
442// Close(shutdown) the socket.
443void
444java::net::PlainSocketImpl::close()
445{
446 // Avoid races from asynchronous finalization.
447 JvSynchronize sync (this);
448
449 // should we use shutdown here? how would that effect so_linger?
450 int res = _Jv_close (fnum);
451
452 if (res == -1)
453 {
454 // These three errors are not errors according to tests performed
455 // on the reference implementation.
456 if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF)
457 throw new java::io::IOException (JvNewStringUTF (strerror (errno)));
458 }
459 // Safe place to reset the file pointer.
460 fnum = -1;
461 timeout = 0;
462}
463
464// Write a byte to the socket.
465void
466java::net::PlainSocketImpl::write(jint b)
467{
468 jbyte d =(jbyte) b;
469 int r = 0;
470
471 while (r != 1)
472 {
473 r = _Jv_write (fnum, &d, 1);
474 if (r == -1)
475 {
476 if (java::lang::Thread::interrupted())
477 {
478 java::io::InterruptedIOException *iioe
479 = new java::io::InterruptedIOException
480 (JvNewStringLatin1 (strerror (errno)));
481 iioe->bytesTransferred = 0;
482 throw iioe;
483 }
484 // Some errors should not cause exceptions.
485 if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF)
486 throw new java::io::IOException (JvNewStringUTF (strerror (errno)));
487 break;
488 }
489 }
490}
491
492// Write some bytes to the socket.
493void
494java::net::PlainSocketImpl::write(jbyteArray b, jint offset, jint len)
495{
496 if (! b)
497 throw new java::lang::NullPointerException;
498 if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
499 throw new java::lang::ArrayIndexOutOfBoundsException;
500
501 jbyte *bytes = elements (b) + offset;
502 int written = 0;
503
504 while (len > 0)
505 {
506 int r = _Jv_write (fnum, bytes, len);
507
508 if (r == -1)
509 {
510 if (java::lang::Thread::interrupted())
511 {
512 java::io::InterruptedIOException *iioe
513 = new java::io::InterruptedIOException
514 (JvNewStringLatin1 (strerror (errno)));
515 iioe->bytesTransferred = written;
516 throw iioe;
517 }
518 // Some errors should not cause exceptions.
519 if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF)
520 throw new java::io::IOException (JvNewStringUTF (strerror (errno)));
521 break;
522 }
523
524 written += r;
525 len -= r;
526 bytes += r;
527 }
528}
529
530void
531java::net::PlainSocketImpl::sendUrgentData (jint)
532{
533 throw new SocketException (JvNewStringLatin1 (
534 "PlainSocketImpl: sending of urgent data not supported by this socket"));
535}
536
537// Read a single byte from the socket.
538jint
539java::net::PlainSocketImpl::read(void)
540{
541 jbyte b;
542
543// FIXME: implement timeout support for Win32
544#ifndef WIN32
545 // Do timeouts via select.
546 if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
547 {
548 // Create the file descriptor set.
549 fd_set read_fds;
550 FD_ZERO (&read_fds);
551 FD_SET (fnum,&read_fds);
552 // Create the timeout struct based on our internal timeout value.
553 struct timeval timeout_value;
554 timeout_value.tv_sec = timeout / 1000;
555 timeout_value.tv_usec = (timeout % 1000) * 1000;
556 // Select on the fds.
557 int sel_retval =
558 _Jv_select (fnum + 1, &read_fds, NULL, NULL, &timeout_value);
559 // If select returns 0 we've waited without getting data...
560 // that means we've timed out.
561 if (sel_retval == 0)
562 throw new java::io::InterruptedIOException
563 (JvNewStringUTF ("read timed out") );
564 // If select returns ok we know we either got signalled or read some data...
565 // either way we need to try to read.
566 }
567#endif /* WIN32 */
568
569 int r = _Jv_read (fnum, &b, 1);
570
571 if (r == 0)
572 return -1;
573
574 if (java::lang::Thread::interrupted())
575 {
576 java::io::InterruptedIOException *iioe =
577 new java::io::InterruptedIOException
578 (JvNewStringUTF("read interrupted"));
579 iioe->bytesTransferred = r == -1 ? 0 : r;
580 throw iioe;
581 }
582 else if (r == -1)
583 {
584 // Some errors cause us to return end of stream...
585 if (errno == ENOTCONN)
586 return -1;
587
588 // Other errors need to be signalled.
589 throw new java::io::IOException (JvNewStringUTF (strerror (errno)));
590 }
591
592 return b & 0xFF;
593}
594
595// Read count bytes into the buffer, starting at offset.
596jint
597java::net::PlainSocketImpl::read(jbyteArray buffer, jint offset, jint count)
598{
599 if (! buffer)
600 throw new java::lang::NullPointerException;
601
602 jsize bsize = JvGetArrayLength (buffer);
603
604 if (offset < 0 || count < 0 || offset + count > bsize)
605 throw new java::lang::ArrayIndexOutOfBoundsException;
606
607 jbyte *bytes = elements (buffer) + offset;
608
609// FIXME: implement timeout support for Win32
610#ifndef WIN32
611 // Do timeouts via select.
612 if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
613 {
614 // Create the file descriptor set.
615 fd_set read_fds;
616 FD_ZERO (&read_fds);
617 FD_SET (fnum, &read_fds);
618 // Create the timeout struct based on our internal timeout value.
619 struct timeval timeout_value;
620 timeout_value.tv_sec = timeout / 1000;
621 timeout_value.tv_usec =(timeout % 1000) * 1000;
622 // Select on the fds.
623 int sel_retval =
624 _Jv_select (fnum + 1, &read_fds, NULL, NULL, &timeout_value);
625 // We're only interested in the 0 return.
626 // error returns still require us to try to read
627 // the socket to see what happened.
628 if (sel_retval == 0)
629 {
630 java::io::InterruptedIOException *iioe =
631 new java::io::InterruptedIOException
632 (JvNewStringUTF ("read interrupted"));
633 iioe->bytesTransferred = 0;
634 throw iioe;
635 }
636 }
637#endif
638
639 // Read the socket.
640 int r = ::recv (fnum, (char *) bytes, count, 0);
641
642 if (r == 0)
643 return -1;
644
645 if (java::lang::Thread::interrupted())
646 {
647 java::io::InterruptedIOException *iioe =
648 new java::io::InterruptedIOException
649 (JvNewStringUTF ("read interrupted"));
650 iioe->bytesTransferred = r == -1 ? 0 : r;
651 throw iioe;
652 }
653 else if (r == -1)
654 {
655 // Some errors cause us to return end of stream...
656 if (errno == ENOTCONN)
657 return -1;
658
659 // Other errors need to be signalled.
660 throw new java::io::IOException (JvNewStringUTF (strerror (errno)));
661 }
662
663 return r;
664}
665
666// How many bytes are available?
667jint
668java::net::PlainSocketImpl::available(void)
669{
670#if defined(FIONREAD) || defined(HAVE_SELECT)
671 long num = 0;
672 int r = 0;
673 bool num_set = false;
674
675#if defined(FIONREAD)
676 r = ::ioctl (fnum, FIONREAD, &num);
677
678 if (r == -1 && errno == ENOTTY)
679 {
680 // If the ioctl doesn't work, we don't care.
681 r = 0;
682 num = 0;
683 }
684 else
685 num_set = true;
686#elif defined(HAVE_SELECT)
687 if (fnum < 0)
688 {
689 errno = EBADF;
690 r = -1;
691 }
692#endif
693
694 if (r == -1)
695 {
696 posix_error:
697 throw new java::io::IOException(JvNewStringUTF(strerror(errno)));
698 }
699
700 // If we didn't get anything we can use select.
701
702#if defined(HAVE_SELECT)
703 if (! num_set)
704 if (! num_set && fnum >= 0 && fnum < FD_SETSIZE)
705 {
706 fd_set rd;
707 FD_ZERO (&rd);
708 FD_SET (fnum, &rd);
709 struct timeval tv;
710 tv.tv_sec = 0;
711 tv.tv_usec = 0;
712 r = _Jv_select (fnum + 1, &rd, NULL, NULL, &tv);
713 if(r == -1)
714 goto posix_error;
715 num = r == 0 ? 0 : 1;
716 }
717#endif /* HAVE_SELECT */
718
719 return (jint) num;
720#else
721 throw new java::io::IOException (JvNewStringUTF ("unimplemented"));
722#endif
723}
724
725void
726java::net::PlainSocketImpl::setOption (jint optID, java::lang::Object *value)
727{
728 int val;
729 socklen_t val_len = sizeof (val);
730
731 if (fnum < 0)
732 throw new java::net::SocketException (JvNewStringUTF ("Socket closed"));
733
734 if (_Jv_IsInstanceOf (value, &java::lang::Boolean::class$))
735 {
736 java::lang::Boolean *boolobj =
737 static_cast<java::lang::Boolean *> (value);
738 if (boolobj->booleanValue())
739 val = 1;
740 else
741 {
742 if (optID == _Jv_SO_LINGER_)
743 val = -1;
744 else
745 val = 0;
746 }
747 }
748 else if (_Jv_IsInstanceOf (value, &java::lang::Integer::class$))
749 {
750 java::lang::Integer *intobj =
751 static_cast<java::lang::Integer *> (value);
752 val = (int) intobj->intValue();
753 }
754 else
755 {
756 throw new java::lang::IllegalArgumentException (
757 JvNewStringLatin1 ("`value' must be Boolean or Integer"));
758 }
759
760 switch (optID)
761 {
762 case _Jv_TCP_NODELAY_ :
763#ifdef TCP_NODELAY
764 if (::setsockopt (fnum, IPPROTO_TCP, TCP_NODELAY, (char *) &val,
765 val_len) != 0)
766 goto error;
767#else
768 throw new java::lang::InternalError
769 (JvNewStringUTF ("TCP_NODELAY not supported"));
770#endif /* TCP_NODELAY */
771 return;
772
773 case _Jv_SO_KEEPALIVE_ :
774 if (::setsockopt (fnum, SOL_SOCKET, SO_KEEPALIVE, (char *) &val,
775 val_len) != 0)
776 goto error;
777 break;
778
779 case _Jv_SO_BROADCAST_ :
780 throw new java::net::SocketException
781 (JvNewStringUTF ("SO_BROADCAST not valid for TCP"));
782 break;
783
784 case _Jv_SO_OOBINLINE_ :
785 if (::setsockopt (fnum, SOL_SOCKET, SO_OOBINLINE, (char *) &val,
786 val_len) != 0)
787 goto error;
788 break;
789
790 case _Jv_SO_LINGER_ :
791#ifdef SO_LINGER
792 struct linger l_val;
793 l_val.l_onoff = (val != -1);
794 l_val.l_linger = val;
795
796 if (::setsockopt (fnum, SOL_SOCKET, SO_LINGER, (char *) &l_val,
797 sizeof(l_val)) != 0)
798 goto error;
799#else
800 throw new java::lang::InternalError (
801 JvNewStringUTF ("SO_LINGER not supported"));
802#endif /* SO_LINGER */
803 return;
804
805 case _Jv_SO_SNDBUF_ :
806 case _Jv_SO_RCVBUF_ :
807#if defined(SO_SNDBUF) && defined(SO_RCVBUF)
808 int opt;
809 optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
810 if (::setsockopt (fnum, SOL_SOCKET, opt, (char *) &val, val_len) != 0)
811 goto error;
812#else
813 throw new java::lang::InternalError (
814 JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
815#endif
816 return;
817
818 case _Jv_SO_BINDADDR_ :
819 throw new java::net::SocketException (
820 JvNewStringUTF ("SO_BINDADDR: read only option"));
821 return;
822
823 case _Jv_IP_MULTICAST_IF_ :
824 throw new java::net::SocketException (
825 JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"));
826 return;
827
828 case _Jv_IP_MULTICAST_IF2_ :
829 throw new java::net::SocketException (
830 JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP"));
831 break;
832
833 case _Jv_IP_MULTICAST_LOOP_ :
834 throw new java::net::SocketException (
835 JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP"));
836 break;
837
838 case _Jv_IP_TOS_ :
839 if (::setsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val,
840 val_len) != 0)
841 goto error;
842 break;
843
844 case _Jv_SO_REUSEADDR_ :
845 throw new java::net::SocketException (
846 JvNewStringUTF ("SO_REUSEADDR: not valid for TCP"));
847 return;
848
849 case _Jv_SO_TIMEOUT_ :
850 timeout = val;
851 return;
852
853 default :
854 errno = ENOPROTOOPT;
855 }
856
857 error:
858 char* strerr = strerror (errno);
859 throw new java::net::SocketException (JvNewStringUTF (strerr));
860}
861
862java::lang::Object *
863java::net::PlainSocketImpl::getOption (jint optID)
864{
865 int val;
866 socklen_t val_len = sizeof(val);
867 union SockAddr u;
868 socklen_t addrlen = sizeof(u);
869 struct linger l_val;
870 socklen_t l_val_len = sizeof(l_val);
871
872 switch (optID)
873 {
874#ifdef TCP_NODELAY
875 case _Jv_TCP_NODELAY_ :
876 if (::getsockopt (fnum, IPPROTO_TCP, TCP_NODELAY, (char *) &val,
877 &val_len) != 0)
878 goto error;
879 else
880 return new java::lang::Boolean (val != 0);
881#else
882 throw new java::lang::InternalError
883 (JvNewStringUTF ("TCP_NODELAY not supported"));
884#endif
885 break;
886
887 case _Jv_SO_LINGER_ :
888#ifdef SO_LINGER
889 if (::getsockopt (fnum, SOL_SOCKET, SO_LINGER, (char *) &l_val,
890 &l_val_len) != 0)
891 goto error;
892
893 if (l_val.l_onoff)
894 return new java::lang::Integer (l_val.l_linger);
895 else
896 return new java::lang::Boolean ((jboolean)false);
897#else
898 throw new java::lang::InternalError
899 (JvNewStringUTF ("SO_LINGER not supported"));
900#endif
901 break;
902
903 case _Jv_SO_KEEPALIVE_ :
904 if (::getsockopt (fnum, SOL_SOCKET, SO_KEEPALIVE, (char *) &val,
905 &val_len) != 0)
906 goto error;
907 else
908 return new java::lang::Boolean (val != 0);
909
910 case _Jv_SO_BROADCAST_ :
911 if (::getsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &val,
912 &val_len) != 0)
913 goto error;
914 return new java::lang::Boolean ((jboolean)val);
915
916 case _Jv_SO_OOBINLINE_ :
917 if (::getsockopt (fnum, SOL_SOCKET, SO_OOBINLINE, (char *) &val,
918 &val_len) != 0)
919 goto error;
920 return new java::lang::Boolean ((jboolean)val);
921
922 case _Jv_SO_RCVBUF_ :
923 case _Jv_SO_SNDBUF_ :
924#if defined(SO_SNDBUF) && defined(SO_RCVBUF)
925 int opt;
926 optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
927 if (::getsockopt (fnum, SOL_SOCKET, opt, (char *) &val, &val_len) != 0)
928 goto error;
929 else
930 return new java::lang::Integer (val);
931#else
932 throw new java::lang::InternalError
933 (JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
934#endif
935 break;
936 case _Jv_SO_BINDADDR_:
937 // cache the local address
938 if (localAddress == NULL)
939 {
940 jbyteArray laddr;
941
942 if (::getsockname (fnum, (sockaddr*) &u, &addrlen) != 0)
943 goto error;
944
945 if (u.address.sin_family == AF_INET)
946 {
947 laddr = JvNewByteArray (4);
948 memcpy (elements (laddr), &u.address.sin_addr, 4);
949 }
950#ifdef HAVE_INET6
951 else if (u.address.sin_family == AF_INET6)
952 {
953 laddr = JvNewByteArray (16);
954 memcpy (elements (laddr), &u.address6.sin6_addr, 16);
955 }
956#endif
957 else
958 throw new java::net::SocketException
959 (JvNewStringUTF ("invalid family"));
960 localAddress = new java::net::InetAddress (laddr, NULL);
961 }
962
963 return localAddress;
964 break;
965 case _Jv_IP_MULTICAST_IF_ :
966 throw new java::net::SocketException
967 (JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"));
968 break;
969
970 case _Jv_IP_MULTICAST_IF2_ :
971 throw new java::net::SocketException
972 (JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP"));
973 break;
974
975 case _Jv_IP_MULTICAST_LOOP_ :
976 throw new java::net::SocketException
977 (JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP"));
978 break;
979
980 case _Jv_IP_TOS_ :
981 if (::getsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val,
982 &val_len) != 0)
983 goto error;
984 return new java::lang::Integer (val);
985 break;
986
987 case _Jv_SO_REUSEADDR_ :
988 throw new java::net::SocketException
989 (JvNewStringUTF ("SO_REUSEADDR: not valid for TCP"));
990 break;
991
992 case _Jv_SO_TIMEOUT_ :
993 return new java::lang::Integer (timeout);
994 break;
995
996 default :
997 errno = ENOPROTOOPT;
998 }
999
1000 error:
1001 char* strerr = strerror (errno);
1002 throw new java::net::SocketException (JvNewStringUTF (strerr));
1003}
1004
1005void
1006java::net::PlainSocketImpl::shutdownInput (void)
1007{
1008 if (::shutdown (fnum, 0))
1009 throw new SocketException (JvNewStringUTF (strerror (errno)));
1010}
1011
1012void
1013java::net::PlainSocketImpl::shutdownOutput (void)
1014{
1015 if (::shutdown (fnum, 1))
1016 throw new SocketException (JvNewStringUTF (strerror (errno)));
1017}
1018
1019#endif /* DISABLE_JAVA_NET */
Note: See TracBrowser for help on using the repository browser.