OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [gnu/] [java/] [net/] [natPlainDatagramSocketImplPosix.cc] - Blame information for rev 756

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.