]> gcc.gnu.org Git - gcc.git/blob - libjava/java/net/natPlainDatagramSocketImpl.cc
natPlainDatagramSocket.cc: removed #include <ws2tcpip.h>; the mingw header is broken...
[gcc.git] / libjava / java / net / natPlainDatagramSocketImpl.cc
1 /* Copyright (C) 1999, 2000, 2002 Free Software Foundation
2
3 This file is part of libgcj.
4
5 This software is copyrighted work licensed under the terms of the
6 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
7 details. */
8
9 #include <config.h>
10
11 #include <platform.h>
12
13 #ifdef WIN32
14 #include <errno.h>
15 #include <string.h>
16 #ifndef ENOPROTOOPT
17 #define ENOPROTOOPT 109
18 #endif
19
20 #define NATIVE_CLOSE(s) closesocket (s)
21
22 #else /* WIN32 */
23
24 #ifdef HAVE_SYS_SOCKET_H
25 #include <sys/socket.h>
26 #endif
27 #ifdef HAVE_NETINET_IN_H
28 #include <netinet/in.h>
29 #endif
30 #ifdef HAVE_ARPA_INET_H
31 #include <arpa/inet.h>
32 #endif
33 #include <errno.h>
34 #include <string.h>
35
36 #define NATIVE_CLOSE(s) ::close (s)
37
38 #endif /* WIN32 */
39
40 #if HAVE_BSTRING_H
41 // Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2
42 #include <bstring.h>
43 #endif
44
45 #ifndef DISABLE_JAVA_NET
46 // Avoid macro definitions of bind from system headers, e.g. on
47 // Solaris 7 with _XOPEN_SOURCE. FIXME
48 static inline int
49 _Jv_bind (int fd, struct sockaddr *addr, int addrlen)
50 {
51 return ::bind (fd, addr, addrlen);
52 }
53 #endif /* DISABLE_JAVA_NET */
54
55 #ifdef bind
56 #undef bind
57 #endif
58
59 #include <gcj/cni.h>
60 #include <java/io/IOException.h>
61 #include <java/io/InterruptedIOException.h>
62 #include <java/net/BindException.h>
63 #include <java/net/SocketException.h>
64 #include <java/net/PlainDatagramSocketImpl.h>
65 #include <java/net/InetAddress.h>
66 #include <java/net/DatagramPacket.h>
67 #include <java/lang/InternalError.h>
68 #include <java/lang/Object.h>
69 #include <java/lang/Boolean.h>
70 #include <java/lang/Integer.h>
71
72 #ifdef DISABLE_JAVA_NET
73
74 void
75 java::net::PlainDatagramSocketImpl::create ()
76 {
77 throw new SocketException (
78 JvNewStringLatin1 ("DatagramSocketImpl.create: unimplemented"));
79 }
80
81 void
82 java::net::PlainDatagramSocketImpl::bind (jint, java::net::InetAddress *)
83 {
84 throw new BindException (
85 JvNewStringLatin1 ("DatagramSocketImpl.bind: unimplemented"));
86 }
87
88 jint
89 java::net::PlainDatagramSocketImpl::peek (java::net::InetAddress *)
90 {
91 throw new java::io::IOException (
92 JvNewStringLatin1 ("DatagramSocketImpl.peek: unimplemented"));
93 }
94
95 jint
96 java::net::PlainDatagramSocketImpl::peekData(java::net::DatagramPacket *)
97 {
98 throw new java::io::IOException (
99 JvNewStringLatin1 ("DatagramSocketImpl.peekData: unimplemented"));
100 }
101
102 void
103 java::net::PlainDatagramSocketImpl::close ()
104 {
105 throw new java::io::IOException (
106 JvNewStringLatin1 ("DatagramSocketImpl.close: unimplemented"));
107 }
108
109 void
110 java::net::PlainDatagramSocketImpl::send (java::net::DatagramPacket *)
111 {
112 throw new java::io::IOException (
113 JvNewStringLatin1 ("DatagramSocketImpl.send: unimplemented"));
114 }
115
116 void
117 java::net::PlainDatagramSocketImpl::receive (java::net::DatagramPacket *)
118 {
119 throw new java::io::IOException (
120 JvNewStringLatin1 ("DatagramSocketImpl.receive: unimplemented"));
121 }
122
123 void
124 java::net::PlainDatagramSocketImpl::setTimeToLive (jint)
125 {
126 throw new java::io::IOException (
127 JvNewStringLatin1 ("DatagramSocketImpl.setTimeToLive: unimplemented"));
128 }
129
130 jint
131 java::net::PlainDatagramSocketImpl::getTimeToLive ()
132 {
133 throw new java::io::IOException (
134 JvNewStringLatin1 ("DatagramSocketImpl.getTimeToLive: unimplemented"));
135 }
136
137 void
138 java::net::PlainDatagramSocketImpl::mcastGrp (java::net::InetAddress *,
139 jboolean)
140 {
141 throw new java::io::IOException (
142 JvNewStringLatin1 ("DatagramSocketImpl.mcastGrp: unimplemented"));
143 }
144
145 void
146 java::net::PlainDatagramSocketImpl::setOption (jint, java::lang::Object *)
147 {
148 throw new SocketException (
149 JvNewStringLatin1 ("DatagramSocketImpl.setOption: unimplemented"));
150 }
151
152 java::lang::Object *
153 java::net::PlainDatagramSocketImpl::getOption (jint)
154 {
155 throw new SocketException (
156 JvNewStringLatin1 ("DatagramSocketImpl.getOption: unimplemented"));
157 }
158
159 #else /* DISABLE_JAVA_NET */
160
161 #ifndef HAVE_SOCKLEN_T
162 typedef int socklen_t;
163 #endif
164
165 union SockAddr
166 {
167 struct sockaddr_in address;
168 #ifdef HAVE_INET6
169 struct sockaddr_in6 address6;
170 #endif
171 };
172
173 union McastReq
174 {
175 #if HAVE_STRUCT_IP_MREQ
176 struct ip_mreq mreq;
177 #endif
178 #if HAVE_STRUCT_IPV6_MREQ
179 struct ipv6_mreq mreq6;
180 #endif
181 };
182
183 union InAddr
184 {
185 struct in_addr addr;
186 #ifdef HAVE_INET6
187 struct in6_addr addr6;
188 #endif
189 };
190
191
192 // FIXME: routines here and/or in natPlainSocketImpl.cc could throw
193 // NoRouteToHostException; also consider UnknownHostException, ConnectException.
194
195 void
196 java::net::PlainDatagramSocketImpl::create ()
197 {
198 int sock = ::socket (AF_INET, SOCK_DGRAM, 0);
199 if (sock < 0)
200 {
201 char* strerr = strerror (errno);
202 throw new java::net::SocketException (JvNewStringUTF (strerr));
203 }
204
205 _Jv_platform_close_on_exec (sock);
206
207 // We use fnum in place of fd here. From leaving fd null we avoid
208 // the double close problem in FileDescriptor.finalize.
209 fnum = sock;
210 }
211
212 void
213 java::net::PlainDatagramSocketImpl::bind (jint lport,
214 java::net::InetAddress *host)
215 {
216 union SockAddr u;
217 struct sockaddr *ptr = (struct sockaddr *) &u.address;
218 // FIXME: Use getaddrinfo() to get actual protocol instead of assuming ipv4.
219 jbyteArray haddress = host->addr;
220 jbyte *bytes = elements (haddress);
221 int len = haddress->length;
222
223 if (len == 4)
224 {
225 u.address.sin_family = AF_INET;
226 if (host != NULL)
227 memcpy (&u.address.sin_addr, bytes, len);
228 else
229 u.address.sin_addr.s_addr = htonl (INADDR_ANY);
230 len = sizeof (struct sockaddr_in);
231 u.address.sin_port = htons (lport);
232 }
233 #ifdef HAVE_INET6
234 else if (len == 16)
235 {
236 u.address6.sin6_family = AF_INET6;
237 memcpy (&u.address6.sin6_addr, bytes, len);
238 len = sizeof (struct sockaddr_in6);
239 u.address6.sin6_port = htons (lport);
240 }
241 #endif
242 else
243 throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
244
245 if (_Jv_bind (fnum, ptr, len) == 0)
246 {
247 socklen_t addrlen = sizeof(u);
248 if (lport != 0)
249 localPort = lport;
250 else if (::getsockname (fnum, (sockaddr*) &u, &addrlen) == 0)
251 localPort = ntohs (u.address.sin_port);
252 else
253 goto error;
254 /* Allow broadcast by default. */
255 int broadcast = 1;
256 if (::setsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &broadcast,
257 sizeof (broadcast)) != 0)
258 goto error;
259 return;
260 }
261 error:
262 char* strerr = strerror (errno);
263 throw new java::net::BindException (JvNewStringUTF (strerr));
264 }
265
266 jint
267 java::net::PlainDatagramSocketImpl::peek (java::net::InetAddress *i)
268 {
269 // FIXME: Deal with Multicast and if the socket is connected.
270 union SockAddr u;
271 socklen_t addrlen = sizeof(u);
272 ssize_t retlen =
273 ::recvfrom (fnum, (char *) NULL, 0, MSG_PEEK, (sockaddr*) &u,
274 &addrlen);
275 if (retlen < 0)
276 goto error;
277 // FIXME: Deal with Multicast addressing and if the socket is connected.
278 jbyteArray raddr;
279 jint rport;
280 if (u.address.sin_family == AF_INET)
281 {
282 raddr = JvNewByteArray (4);
283 memcpy (elements (raddr), &u.address.sin_addr, 4);
284 rport = ntohs (u.address.sin_port);
285 }
286 #ifdef HAVE_INET6
287 else if (u.address.sin_family == AF_INET6)
288 {
289 raddr = JvNewByteArray (16);
290 memcpy (elements (raddr), &u.address6.sin6_addr, 16);
291 rport = ntohs (u.address6.sin6_port);
292 }
293 #endif
294 else
295 throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
296
297 i->addr = raddr;
298 return rport;
299 error:
300 char* strerr = strerror (errno);
301 throw new java::io::IOException (JvNewStringUTF (strerr));
302 }
303
304 jint
305 java::net::PlainDatagramSocketImpl::peekData(java::net::DatagramPacket *p)
306 {
307 // FIXME: Deal with Multicast and if the socket is connected.
308 union SockAddr u;
309 socklen_t addrlen = sizeof(u);
310 jbyte *dbytes = elements (p->getData());
311 ssize_t retlen = 0;
312
313 // FIXME: implement timeout support for Win32
314 #ifndef WIN32
315 // Do timeouts via select since SO_RCVTIMEO is not always available.
316 if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
317 {
318 fd_set rset;
319 struct timeval tv;
320 FD_ZERO(&rset);
321 FD_SET(fnum, &rset);
322 tv.tv_sec = timeout / 1000;
323 tv.tv_usec = (timeout % 1000) * 1000;
324 int retval;
325 if ((retval = _Jv_select (fnum + 1, &rset, NULL, NULL, &tv)) < 0)
326 goto error;
327 else if (retval == 0)
328 throw new java::io::InterruptedIOException ();
329 }
330 #endif /* WIN32 */
331
332 retlen =
333 ::recvfrom (fnum, (char *) dbytes, p->getLength(), MSG_PEEK, (sockaddr*) &u,
334 &addrlen);
335 if (retlen < 0)
336 goto error;
337 // FIXME: Deal with Multicast addressing and if the socket is connected.
338 jbyteArray raddr;
339 jint rport;
340 if (u.address.sin_family == AF_INET)
341 {
342 raddr = JvNewByteArray (4);
343 memcpy (elements (raddr), &u.address.sin_addr, 4);
344 rport = ntohs (u.address.sin_port);
345 }
346 #ifdef HAVE_INET6
347 else if (u.address.sin_family == AF_INET6)
348 {
349 raddr = JvNewByteArray (16);
350 memcpy (elements (raddr), &u.address6.sin6_addr, 16);
351 rport = ntohs (u.address6.sin6_port);
352 }
353 #endif
354 else
355 throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
356
357 p->setAddress (new InetAddress (raddr, NULL));
358 p->setPort (rport);
359 p->setLength ((jint) retlen);
360 return rport;
361 error:
362 char* strerr = strerror (errno);
363 throw new java::io::IOException (JvNewStringUTF (strerr));
364 }
365
366 // Close(shutdown) the socket.
367 void
368 java::net::PlainDatagramSocketImpl::close ()
369 {
370 // Avoid races from asynchronous finalization.
371 JvSynchronize sync (this);
372
373 // The method isn't declared to throw anything, so we disregard
374 // the return value.
375 NATIVE_CLOSE (fnum);
376 fnum = -1;
377 timeout = 0;
378 }
379
380 void
381 java::net::PlainDatagramSocketImpl::send (java::net::DatagramPacket *p)
382 {
383 // FIXME: Deal with Multicast and if the socket is connected.
384 jint rport = p->getPort();
385 union SockAddr u;
386 jbyteArray haddress = p->getAddress()->addr;
387 jbyte *bytes = elements (haddress);
388 int len = haddress->length;
389 struct sockaddr *ptr = (struct sockaddr *) &u.address;
390 jbyte *dbytes = elements (p->getData());
391 if (len == 4)
392 {
393 u.address.sin_family = AF_INET;
394 memcpy (&u.address.sin_addr, bytes, len);
395 len = sizeof (struct sockaddr_in);
396 u.address.sin_port = htons (rport);
397 }
398 #ifdef HAVE_INET6
399 else if (len == 16)
400 {
401 u.address6.sin6_family = AF_INET6;
402 memcpy (&u.address6.sin6_addr, bytes, len);
403 len = sizeof (struct sockaddr_in6);
404 u.address6.sin6_port = htons (rport);
405 }
406 #endif
407 else
408 throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
409
410 if (::sendto (fnum, (char *) dbytes, p->getLength(), 0, ptr, len) >= 0)
411 return;
412
413 char* strerr = strerror (errno);
414 throw new java::io::IOException (JvNewStringUTF (strerr));
415 }
416
417 void
418 java::net::PlainDatagramSocketImpl::receive (java::net::DatagramPacket *p)
419 {
420 // FIXME: Deal with Multicast and if the socket is connected.
421 union SockAddr u;
422 socklen_t addrlen = sizeof(u);
423 jbyte *dbytes = elements (p->getData());
424 ssize_t retlen = 0;
425
426 // FIXME: implement timeout support for Win32
427 #ifndef WIN32
428 // Do timeouts via select since SO_RCVTIMEO is not always available.
429 if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
430 {
431 fd_set rset;
432 struct timeval tv;
433 FD_ZERO(&rset);
434 FD_SET(fnum, &rset);
435 tv.tv_sec = timeout / 1000;
436 tv.tv_usec = (timeout % 1000) * 1000;
437 int retval;
438 if ((retval = _Jv_select (fnum + 1, &rset, NULL, NULL, &tv)) < 0)
439 goto error;
440 else if (retval == 0)
441 throw new java::io::InterruptedIOException ();
442 }
443 #endif /* WIN32 */
444
445 retlen =
446 ::recvfrom (fnum, (char *) dbytes, p->getLength(), 0, (sockaddr*) &u,
447 &addrlen);
448 if (retlen < 0)
449 goto error;
450 // FIXME: Deal with Multicast addressing and if the socket is connected.
451 jbyteArray raddr;
452 jint rport;
453 if (u.address.sin_family == AF_INET)
454 {
455 raddr = JvNewByteArray (4);
456 memcpy (elements (raddr), &u.address.sin_addr, 4);
457 rport = ntohs (u.address.sin_port);
458 }
459 #ifdef HAVE_INET6
460 else if (u.address.sin_family == AF_INET6)
461 {
462 raddr = JvNewByteArray (16);
463 memcpy (elements (raddr), &u.address6.sin6_addr, 16);
464 rport = ntohs (u.address6.sin6_port);
465 }
466 #endif
467 else
468 throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
469
470 p->setAddress (new InetAddress (raddr, NULL));
471 p->setPort (rport);
472 p->setLength ((jint) retlen);
473 return;
474 error:
475 char* strerr = strerror (errno);
476 throw new java::io::IOException (JvNewStringUTF (strerr));
477 }
478
479 void
480 java::net::PlainDatagramSocketImpl::setTimeToLive (jint ttl)
481 {
482 // Assumes IPPROTO_IP rather than IPPROTO_IPV6 since socket created is IPv4.
483 char val = (char) ttl;
484 socklen_t val_len = sizeof(val);
485 if (::setsockopt (fnum, IPPROTO_IP, IP_MULTICAST_TTL, &val, val_len) == 0)
486 return;
487
488 char* strerr = strerror (errno);
489 throw new java::io::IOException (JvNewStringUTF (strerr));
490 }
491
492 jint
493 java::net::PlainDatagramSocketImpl::getTimeToLive ()
494 {
495 // Assumes IPPROTO_IP rather than IPPROTO_IPV6 since socket created is IPv4.
496 char val;
497 socklen_t val_len = sizeof(val);
498 if (::getsockopt (fnum, IPPROTO_IP, IP_MULTICAST_TTL, &val, &val_len) == 0)
499 return ((int) val) & 0xFF;
500
501 char* strerr = strerror (errno);
502 throw new java::io::IOException (JvNewStringUTF (strerr));
503 }
504
505 void
506 java::net::PlainDatagramSocketImpl::mcastGrp (java::net::InetAddress *inetaddr,
507 jboolean join)
508 {
509 union McastReq u;
510 jbyteArray haddress = inetaddr->addr;
511 jbyte *bytes = elements (haddress);
512 int len = haddress->length;
513 int level, opname;
514 const char *ptr;
515 if (0)
516 ;
517 #if HAVE_STRUCT_IP_MREQ
518 else if (len == 4)
519 {
520 level = IPPROTO_IP;
521 opname = join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
522 memcpy (&u.mreq.imr_multiaddr, bytes, len);
523 // FIXME: If a non-default interface is set, use it; see Stevens p. 501.
524 // Maybe not, see note in last paragraph at bottom of Stevens p. 497.
525 u.mreq.imr_interface.s_addr = htonl (INADDR_ANY);
526 len = sizeof (struct ip_mreq);
527 ptr = (const char *) &u.mreq;
528 }
529 #endif
530 #if HAVE_STRUCT_IPV6_MREQ
531 else if (len == 16)
532 {
533 level = IPPROTO_IPV6;
534
535 /* Prefer new RFC 2553 names. */
536 #ifndef IPV6_JOIN_GROUP
537 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
538 #endif
539 #ifndef IPV6_LEAVE_GROUP
540 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
541 #endif
542
543 opname = join ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP;
544 memcpy (&u.mreq6.ipv6mr_multiaddr, bytes, len);
545 // FIXME: If a non-default interface is set, use it; see Stevens p. 501.
546 // Maybe not, see note in last paragraph at bottom of Stevens p. 497.
547 u.mreq6.ipv6mr_interface = 0;
548 len = sizeof (struct ipv6_mreq);
549 ptr = (const char *) &u.mreq6;
550 }
551 #endif
552 else
553 throw new java::net::SocketException (JvNewStringUTF ("invalid length"));
554
555 if (::setsockopt (fnum, level, opname, ptr, len) == 0)
556 return;
557
558 char* strerr = strerror (errno);
559 throw new java::io::IOException (JvNewStringUTF (strerr));
560 }
561
562 void
563 java::net::PlainDatagramSocketImpl::setOption (jint optID,
564 java::lang::Object *value)
565 {
566 int val;
567 socklen_t val_len = sizeof (val);
568
569 if (fnum < 0)
570 throw new java::net::SocketException (JvNewStringUTF ("Socket closed"));
571
572 if (_Jv_IsInstanceOf (value, &java::lang::Boolean::class$))
573 {
574 java::lang::Boolean *boolobj =
575 static_cast<java::lang::Boolean *> (value);
576 val = boolobj->booleanValue() ? 1 : 0;
577 }
578 else if (_Jv_IsInstanceOf (value, &java::lang::Integer::class$))
579 {
580 java::lang::Integer *intobj =
581 static_cast<java::lang::Integer *> (value);
582 val = (int) intobj->intValue();
583 }
584 // Else assume value to be an InetAddress for use with IP_MULTICAST_IF.
585
586 switch (optID)
587 {
588 case _Jv_TCP_NODELAY_ :
589 throw new java::net::SocketException (
590 JvNewStringUTF ("TCP_NODELAY not valid for UDP"));
591 return;
592 case _Jv_SO_LINGER_ :
593 throw new java::net::SocketException (
594 JvNewStringUTF ("SO_LINGER not valid for UDP"));
595 return;
596 case _Jv_SO_KEEPALIVE_ :
597 throw new java::net::SocketException (
598 JvNewStringUTF ("SO_KEEPALIVE not valid for UDP"));
599 return;
600
601 case _Jv_SO_BROADCAST_ :
602 if (::setsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &val,
603 val_len) != 0)
604 goto error;
605 break;
606
607 case _Jv_SO_OOBINLINE_ :
608 throw new java::net::SocketException (
609 JvNewStringUTF ("SO_OOBINLINE: not valid for UDP"));
610 break;
611
612 case _Jv_SO_SNDBUF_ :
613 case _Jv_SO_RCVBUF_ :
614 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
615 int opt;
616 optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
617 if (::setsockopt (fnum, SOL_SOCKET, opt, (char *) &val, val_len) != 0)
618 goto error;
619 #else
620 throw new java::lang::InternalError (
621 JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
622 #endif
623 return;
624 case _Jv_SO_REUSEADDR_ :
625 #if defined(SO_REUSEADDR)
626 if (::setsockopt (fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
627 val_len) != 0)
628 goto error;
629 #else
630 throw new java::lang::InternalError (
631 JvNewStringUTF ("SO_REUSEADDR not supported"));
632 #endif
633 return;
634 case _Jv_SO_BINDADDR_ :
635 throw new java::net::SocketException (
636 JvNewStringUTF ("SO_BINDADDR: read only option"));
637 return;
638 case _Jv_IP_MULTICAST_IF_ :
639 union InAddr u;
640 jbyteArray haddress;
641 jbyte *bytes;
642 int len;
643 int level, opname;
644 const char *ptr;
645
646 haddress = ((java::net::InetAddress *) value)->addr;
647 bytes = elements (haddress);
648 len = haddress->length;
649 if (len == 4)
650 {
651 level = IPPROTO_IP;
652 opname = IP_MULTICAST_IF;
653 memcpy (&u.addr, bytes, len);
654 len = sizeof (struct in_addr);
655 ptr = (const char *) &u.addr;
656 }
657 // Tru64 UNIX V5.0 has struct sockaddr_in6, but no IPV6_MULTICAST_IF
658 #if defined (HAVE_INET6) && defined (IPV6_MULTICAST_IF)
659 else if (len == 16)
660 {
661 level = IPPROTO_IPV6;
662 opname = IPV6_MULTICAST_IF;
663 memcpy (&u.addr6, bytes, len);
664 len = sizeof (struct in6_addr);
665 ptr = (const char *) &u.addr6;
666 }
667 #endif
668 else
669 throw
670 new java::net::SocketException (JvNewStringUTF ("invalid length"));
671
672 if (::setsockopt (fnum, level, opname, ptr, len) != 0)
673 goto error;
674 return;
675
676 case _Jv_IP_MULTICAST_IF2_ :
677 throw new java::net::SocketException (
678 JvNewStringUTF ("IP_MULTICAST_IF2: not yet implemented"));
679 break;
680
681 case _Jv_IP_MULTICAST_LOOP_ :
682 throw new java::net::SocketException (
683 JvNewStringUTF ("IP_MULTICAST_LOOP: not yet implemented"));
684 break;
685
686 case _Jv_IP_TOS_ :
687 if (::setsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val,
688 val_len) != 0)
689 goto error;
690 return;
691
692 case _Jv_SO_TIMEOUT_ :
693 timeout = val;
694 return;
695 default :
696 errno = ENOPROTOOPT;
697 }
698
699 error:
700 char* strerr = strerror (errno);
701 throw new java::net::SocketException (JvNewStringUTF (strerr));
702 }
703
704 java::lang::Object *
705 java::net::PlainDatagramSocketImpl::getOption (jint optID)
706 {
707 int val;
708 socklen_t val_len = sizeof(val);
709 union SockAddr u;
710 socklen_t addrlen = sizeof(u);
711
712 switch (optID)
713 {
714 case _Jv_TCP_NODELAY_ :
715 throw new java::net::SocketException (
716 JvNewStringUTF ("TCP_NODELAY not valid for UDP"));
717 break;
718 case _Jv_SO_LINGER_ :
719 throw new java::net::SocketException (
720 JvNewStringUTF ("SO_LINGER not valid for UDP"));
721 break;
722 case _Jv_SO_KEEPALIVE_ :
723 throw new java::net::SocketException (
724 JvNewStringUTF ("SO_KEEPALIVE not valid for UDP"));
725 break;
726
727 case _Jv_SO_BROADCAST_ :
728 if (::getsockopt (fnum, SOL_SOCKET, SO_BROADCAST, (char *) &val,
729 &val_len) != 0)
730 goto error;
731 return new java::lang::Boolean (val != 0);
732
733 case _Jv_SO_OOBINLINE_ :
734 throw new java::net::SocketException (
735 JvNewStringUTF ("SO_OOBINLINE not valid for UDP"));
736 break;
737
738 case _Jv_SO_RCVBUF_ :
739 case _Jv_SO_SNDBUF_ :
740 #if defined(SO_SNDBUF) && defined(SO_RCVBUF)
741 int opt;
742 optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
743 if (::getsockopt (fnum, SOL_SOCKET, opt, (char *) &val, &val_len) != 0)
744 goto error;
745 else
746 return new java::lang::Integer (val);
747 #else
748 throw new java::lang::InternalError (
749 JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
750 #endif
751 break;
752 case _Jv_SO_BINDADDR_:
753 // cache the local address
754 if (localAddress == NULL)
755 {
756 jbyteArray laddr;
757 if (::getsockname (fnum, (sockaddr*) &u, &addrlen) != 0)
758 goto error;
759 if (u.address.sin_family == AF_INET)
760 {
761 laddr = JvNewByteArray (4);
762 memcpy (elements (laddr), &u.address.sin_addr, 4);
763 }
764 #ifdef HAVE_INET6
765 else if (u.address.sin_family == AF_INET6)
766 {
767 laddr = JvNewByteArray (16);
768 memcpy (elements (laddr), &u.address6.sin6_addr, 16);
769 }
770 #endif
771 else
772 throw new java::net::SocketException (JvNewStringUTF ("invalid family"));
773 localAddress = new java::net::InetAddress (laddr, NULL);
774 }
775 return localAddress;
776 break;
777 case _Jv_SO_REUSEADDR_ :
778 #if defined(SO_REUSEADDR)
779 if (::getsockopt (fnum, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
780 &val_len) != 0)
781 goto error;
782 return new java::lang::Boolean (val != 0);
783 #else
784 throw new java::lang::InternalError (
785 JvNewStringUTF ("SO_REUSEADDR not supported"));
786 #endif
787 break;
788 case _Jv_IP_MULTICAST_IF_ :
789 #ifdef HAVE_INET_NTOA
790 struct in_addr inaddr;
791 socklen_t inaddr_len;
792 char *bytes;
793
794 inaddr_len = sizeof(inaddr);
795 if (::getsockopt (fnum, IPPROTO_IP, IP_MULTICAST_IF, (char *) &inaddr,
796 &inaddr_len) != 0)
797 goto error;
798
799 bytes = inet_ntoa (inaddr);
800
801 return java::net::InetAddress::getByName (JvNewStringLatin1 (bytes));
802 #else
803 throw new java::net::SocketException (
804 JvNewStringUTF ("IP_MULTICAST_IF: not available - no inet_ntoa()"));
805 #endif
806 break;
807 case _Jv_SO_TIMEOUT_ :
808 return new java::lang::Integer (timeout);
809 break;
810
811 case _Jv_IP_MULTICAST_IF2_ :
812 throw new java::net::SocketException (
813 JvNewStringUTF ("IP_MULTICAST_IF2: not yet implemented"));
814 break;
815
816 case _Jv_IP_MULTICAST_LOOP_ :
817 if (::getsockopt (fnum, SOL_SOCKET, IP_MULTICAST_LOOP, (char *) &val,
818 &val_len) != 0)
819 goto error;
820 return new java::lang::Boolean (val != 0);
821
822 case _Jv_IP_TOS_ :
823 if (::getsockopt (fnum, SOL_SOCKET, IP_TOS, (char *) &val,
824 &val_len) != 0)
825 goto error;
826 return new java::lang::Integer (val);
827
828 default :
829 errno = ENOPROTOOPT;
830 }
831
832 error:
833 char* strerr = strerror (errno);
834 throw new java::net::SocketException (JvNewStringUTF (strerr));
835 }
836
837 #endif /* DISABLE_JAVA_NET */
This page took 0.075732 seconds and 5 git commands to generate.