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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 756 jeremybenn
/* Copyright (C) 2003, 2004, 2005, 2006, 2007  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_SYS_IOCTL_H
13
#define BSD_COMP /* Get FIONREAD on Solaris2. */
14
#include <sys/ioctl.h>
15
#endif
16
 
17
// Pick up FIONREAD on Solaris 2.5.
18
#ifdef HAVE_SYS_FILIO_H
19
#include <sys/filio.h>
20
#endif
21
 
22
#include <netinet/in.h>
23
#include <netinet/tcp.h>
24
#include <errno.h>
25
#include <string.h>
26
 
27
#if HAVE_BSTRING_H
28
// Needed for bzero, implicitly used by FD_ZERO on IRIX 5.2 
29
#include <bstring.h>
30
#endif
31
 
32
#include <gcj/cni.h>
33
#include <gcj/javaprims.h>
34
#include <gnu/java/net/PlainSocketImpl.h>
35
#include <gnu/java/net/PlainSocketImpl$SocketInputStream.h>
36
#include <gnu/java/net/PlainSocketImpl$SocketOutputStream.h>
37
#include <java/io/IOException.h>
38
#include <java/io/InterruptedIOException.h>
39
#include <java/net/BindException.h>
40
#include <java/net/ConnectException.h>
41
#include <java/net/InetAddress.h>
42
#include <java/net/InetSocketAddress.h>
43
#include <java/net/SocketException.h>
44
#include <java/net/SocketTimeoutException.h>
45
#include <java/lang/InternalError.h>
46
#include <java/lang/Object.h>
47
#include <java/lang/Boolean.h>
48
#include <java/lang/Class.h>
49
#include <java/lang/Integer.h>
50
#include <java/lang/Thread.h>
51
#include <java/lang/NullPointerException.h>
52
#include <java/lang/ArrayIndexOutOfBoundsException.h>
53
#include <java/lang/IllegalArgumentException.h>
54
#include <java/net/UnknownHostException.h>
55
 
56
union SockAddr
57
{
58
  struct sockaddr_in address;
59
#ifdef HAVE_INET6
60
  struct sockaddr_in6 address6;
61
#endif
62
};
63
 
64
void
65
gnu::java::net::PlainSocketImpl::create (jboolean stream)
66
{
67
  // We might already have been create()d in the nio case.
68
  if (native_fd != -1)
69
    return;
70
 
71
  int sock = _Jv_socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0);
72
 
73
  if (sock < 0)
74
    {
75
      char* strerr = strerror (errno);
76
      throw new ::java::io::IOException (JvNewStringUTF (strerr));
77
    }
78
 
79
  // We use native_fd in place of fd here.  From leaving fd null we avoid
80
  // the double close problem in FileDescriptor.finalize.
81
  native_fd = sock;
82
}
83
 
84
void
85
gnu::java::net::PlainSocketImpl::bind (::java::net::InetAddress *host, jint lport)
86
{
87
  union SockAddr u;
88
  struct sockaddr *ptr = (struct sockaddr *) &u.address;
89
  jbyteArray haddress = host->addr;
90
  jbyte *bytes = elements (haddress);
91
  int len = haddress->length;
92
  int i = 1;
93
 
94
  // The following is needed for OS X/PPC, otherwise bind() fails with an
95
  // error. I found the issue and following fix on some mailing list, but
96
  // no explanation was given as to why this solved the problem.
97
  memset (&u, 0, sizeof (u));
98
 
99
  if (len == 4)
100
    {
101
      u.address.sin_family = AF_INET;
102
      memcpy (&u.address.sin_addr, bytes, len);
103
      len = sizeof (struct sockaddr_in);
104
      u.address.sin_port = htons (lport);
105
    }
106
#ifdef HAVE_INET6
107
  else if (len == 16)
108
    {
109
      u.address6.sin6_family = AF_INET6;
110
      memcpy (&u.address6.sin6_addr, bytes, len);
111
      len = sizeof (struct sockaddr_in6);
112
      u.address6.sin6_port = htons (lport);
113
    }
114
#endif
115
  else
116
    throw new ::java::net::SocketException (JvNewStringUTF ("invalid length"));
117
 
118
  // Enable SO_REUSEADDR, so that servers can reuse ports left in TIME_WAIT.
119
  ::setsockopt(native_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &i, sizeof(i));
120
 
121
  if (_Jv_bind (native_fd, ptr, len) == 0)
122
    {
123
      socklen_t addrlen = sizeof(u);
124
 
125
      if (lport != 0)
126
        localport = lport;
127
      else if (::getsockname (native_fd, (sockaddr*) &u, &addrlen) == 0)
128
        localport = ntohs (u.address.sin_port);
129
      else
130
        goto error;
131
 
132
      return;
133
    }
134
 
135
 error:
136
  char* strerr = strerror (errno);
137
  throw new ::java::net::BindException (JvNewStringUTF (strerr));
138
}
139
 
140
void
141
gnu::java::net::PlainSocketImpl::connect (::java::net::SocketAddress *addr,
142
                                          jint timeout)
143
{
144
  ::java::net::InetSocketAddress *tmp = (::java::net::InetSocketAddress*) addr;
145
  ::java::net::InetAddress *host = tmp->getAddress();
146
  if (! host)
147
    throw new ::java::net::UnknownHostException(tmp->toString());
148
 
149
  jint rport = tmp->getPort();
150
 
151
  // Set the SocketImpl's address and port fields before we try to
152
  // connect.  Note that the fact that these are set doesn't imply
153
  // that we're actually connected to anything.  We need to record
154
  // this data before we attempt the connect, since non-blocking
155
  // SocketChannels will use this and almost certainly throw timeout
156
  // exceptions.
157
  address = host;
158
  port = rport;
159
 
160
  union SockAddr u;
161
  socklen_t addrlen = sizeof(u);
162
  jbyteArray haddress = host->addr;
163
  jbyte *bytes = elements (haddress);
164
  int len = haddress->length;
165
  struct sockaddr *ptr = (struct sockaddr *) &u.address;
166
  if (len == 4)
167
    {
168
      u.address.sin_family = AF_INET;
169
      memcpy (&u.address.sin_addr, bytes, len);
170
      len = sizeof (struct sockaddr_in);
171
      u.address.sin_port = htons (rport);
172
    }
173
#ifdef HAVE_INET6
174
  else if (len == 16)
175
    {
176
      u.address6.sin6_family = AF_INET6;
177
      memcpy (&u.address6.sin6_addr, bytes, len);
178
      len = sizeof (struct sockaddr_in6);
179
      u.address6.sin6_port = htons (rport);
180
    }
181
#endif
182
  else
183
    throw new ::java::net::SocketException (JvNewStringUTF ("invalid length"));
184
 
185
  if (timeout > 0)
186
    {
187
      int flags = ::fcntl (native_fd, F_GETFL);
188
      ::fcntl (native_fd, F_SETFL, flags | O_NONBLOCK);
189
 
190
      if ((_Jv_connect (native_fd, ptr, len) != 0) && (errno != EINPROGRESS))
191
        goto error;
192
 
193
      fd_set fset;
194
      struct timeval tv;
195
      FD_ZERO(&fset);
196
      FD_SET(native_fd, &fset);
197
      tv.tv_sec = timeout / 1000;
198
      tv.tv_usec = (timeout % 1000) * 1000;
199
      int retval;
200
 
201
      if ((retval = _Jv_select (native_fd + 1, &fset, &fset, NULL, &tv)) < 0)
202
        goto error;
203
      else if (retval == 0)
204
        throw new ::java::net::SocketTimeoutException
205
          (JvNewStringUTF ("Connect timed out"));
206
       // Set the socket back into a blocking state.
207
       ::fcntl (native_fd, F_SETFL, flags);
208
    }
209
  else
210
    {
211
      if (_Jv_connect (native_fd, ptr, len) != 0)
212
        goto error;
213
    }
214
 
215
  // A bind may not have been done on this socket; if so, set localport now.
216
  if (localport == 0)
217
    {
218
      if (::getsockname (native_fd, (sockaddr*) &u, &addrlen) == 0)
219
        localport = ntohs (u.address.sin_port);
220
      else
221
        goto error;
222
    }
223
 
224
  return;
225
 
226
 error:
227
  char* strerr = strerror (errno);
228
  throw new ::java::net::ConnectException (JvNewStringUTF (strerr));
229
}
230
 
231
void
232
gnu::java::net::PlainSocketImpl::listen (jint backlog)
233
{
234
  if (::listen (native_fd, backlog) != 0)
235
    {
236
      char* strerr = strerror (errno);
237
      throw new ::java::io::IOException (JvNewStringUTF (strerr));
238
    }
239
}
240
 
241
static void
242
throw_on_sock_closed (gnu::java::net::PlainSocketImpl *soc_impl)
243
{
244
    // Avoid races from asynchronous close().
245
    JvSynchronize sync (soc_impl);
246
    if (soc_impl->native_fd == -1)
247
      {
248
        using namespace java::net;
249
        // Socket was closed.
250
        SocketException *se =
251
            new SocketException (JvNewStringUTF ("Socket Closed"));
252
        throw se;
253
      }
254
}
255
 
256
void
257
gnu::java::net::PlainSocketImpl::accept (gnu::java::net::PlainSocketImpl *s)
258
{
259
  union SockAddr u;
260
  socklen_t addrlen = sizeof(u);
261
  int new_socket = 0;
262
 
263
  // Do timeouts via select since SO_RCVTIMEO is not always available.
264
  if (timeout > 0 && native_fd >= 0 && native_fd < FD_SETSIZE)
265
    {
266
      fd_set fset;
267
      struct timeval tv;
268
      FD_ZERO(&fset);
269
      FD_SET(native_fd, &fset);
270
      tv.tv_sec = timeout / 1000;
271
      tv.tv_usec = (timeout % 1000) * 1000;
272
      int retval;
273
      if ((retval = _Jv_select (native_fd + 1, &fset, &fset, NULL, &tv)) < 0)
274
        goto error;
275
      else if (retval == 0)
276
        throw new ::java::net::SocketTimeoutException (
277
                                          JvNewStringUTF("Accept timed out"));
278
    }
279
 
280
  new_socket = _Jv_accept (native_fd, (sockaddr*) &u, &addrlen);
281
 
282
  if (new_socket < 0)
283
    goto error;
284
 
285
  jbyteArray raddr;
286
  jint rport;
287
  if (u.address.sin_family == AF_INET)
288
    {
289
      raddr = JvNewByteArray (4);
290
      memcpy (elements (raddr), &u.address.sin_addr, 4);
291
      rport = ntohs (u.address.sin_port);
292
    }
293
#ifdef HAVE_INET6
294
  else if (u.address.sin_family == AF_INET6)
295
    {
296
      raddr = JvNewByteArray (16);
297
      memcpy (elements (raddr), &u.address6.sin6_addr, 16);
298
      rport = ntohs (u.address6.sin6_port);
299
    }
300
#endif
301
  else
302
    throw new ::java::net::SocketException (JvNewStringUTF ("invalid family"));
303
 
304
  s->native_fd = new_socket;
305
  s->localport = localport;
306
  s->address = ::java::net::InetAddress::getByAddress (raddr);
307
  s->port = rport;
308
  return;
309
 
310
 error:
311
  char* strerr = strerror (errno);
312
  throw_on_sock_closed (this);
313
  throw new ::java::io::IOException (JvNewStringUTF (strerr));
314
}
315
 
316
// Close(shutdown) the socket.
317
void
318
gnu::java::net::PlainSocketImpl::close()
319
{
320
  // Avoid races from asynchronous finalization.
321
  JvSynchronize sync (this);
322
 
323
  // Should we use shutdown here? Yes.
324
  // How would that effect so_linger? Uncertain.
325
  ::shutdown (native_fd, 2);
326
  // Ignore errors in shutdown as we are closing and all the same
327
  // errors are handled in the close.
328
  int res = _Jv_close (native_fd);
329
 
330
  if (res == -1)
331
    {
332
      // These three errors are not errors according to tests performed
333
      // on the reference implementation.
334
      if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF)
335
        throw new ::java::io::IOException  (JvNewStringUTF (strerror (errno)));
336
    }
337
  // Safe place to reset the file pointer.
338
  native_fd = -1;
339
  timeout = 0;
340
}
341
 
342
static void
343
write_helper (jint native_fd, jbyte *bytes, jint len);
344
 
345
// Write a byte to the socket.
346
void
347
gnu::java::net::PlainSocketImpl$SocketOutputStream::write(jint b)
348
{
349
  jbyte data = (jbyte) b;
350
  write_helper (this$0->native_fd, &data, 1);
351
}
352
 
353
// Write some bytes to the socket.
354
void
355
gnu::java::net::PlainSocketImpl$SocketOutputStream::write(jbyteArray b, jint offset, jint len)
356
{
357
  if (! b)
358
    throw new ::java::lang::NullPointerException;
359
  if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
360
    throw new ::java::lang::ArrayIndexOutOfBoundsException;
361
 
362
  write_helper (this$0->native_fd, elements (b) + offset, len);
363
}
364
 
365
static void
366
write_helper(jint native_fd, jbyte *bytes, jint len)
367
{
368
  int written = 0;
369
 
370
  while (len > 0)
371
    {
372
      int r = _Jv_write (native_fd, bytes, len);
373
 
374
      if (r == -1)
375
        {
376
          if (::java::lang::Thread::interrupted())
377
            {
378
              ::java::io::InterruptedIOException *iioe
379
                = new ::java::io::InterruptedIOException
380
                (JvNewStringLatin1 (strerror (errno)));
381
              iioe->bytesTransferred = written;
382
              throw iioe;
383
            }
384
          // Some errors should not cause exceptions.
385
          if (errno != ENOTCONN && errno != ECONNRESET && errno != EBADF)
386
            throw new ::java::io::IOException (JvNewStringUTF (strerror (errno)));
387
          break;
388
        }
389
 
390
      written += r;
391
      len -= r;
392
      bytes += r;
393
    }
394
}
395
 
396
void
397
gnu::java::net::PlainSocketImpl::sendUrgentData (jint)
398
{
399
  throw new ::java::net::SocketException (JvNewStringLatin1 (
400
    "PlainSocketImpl: sending of urgent data not supported by this socket"));
401
}
402
 
403
static jint
404
read_helper (gnu::java::net::PlainSocketImpl *soc_impl,
405
             jbyte *bytes, jint count);
406
 
407
// Read a single byte from the socket.
408
jint
409
gnu::java::net::PlainSocketImpl$SocketInputStream::read(void)
410
{
411
  jbyte data;
412
 
413
  if (read_helper (this$0, &data, 1) == 1)
414
    return data & 0xFF;
415
 
416
  return -1;
417
}
418
 
419
// Read count bytes into the buffer, starting at offset.
420
jint
421
gnu::java::net::PlainSocketImpl$SocketInputStream::read(jbyteArray buffer,
422
                                                        jint offset,
423
                                                        jint count)
424
{
425
 if (! buffer)
426
    throw new ::java::lang::NullPointerException;
427
 
428
  jsize bsize = JvGetArrayLength (buffer);
429
 
430
  if (offset < 0 || count < 0 || offset + count > bsize)
431
    throw new ::java::lang::ArrayIndexOutOfBoundsException;
432
 
433
  return read_helper (this$0, elements (buffer) + offset, count);
434
}
435
 
436
static jint
437
read_helper (gnu::java::net::PlainSocketImpl *soc_impl,
438
             jbyte *bytes, jint count)
439
{
440
  // If zero bytes were requested, short circuit so that recv
441
  // doesn't signal EOF.
442
  if (count == 0)
443
    return 0;
444
 
445
  // Do timeouts via select.
446
  if (soc_impl->timeout > 0
447
      && soc_impl->native_fd >= 0
448
      && soc_impl->native_fd < FD_SETSIZE)
449
    {
450
      // Create the file descriptor set.
451
      fd_set read_fds;
452
      FD_ZERO (&read_fds);
453
      FD_SET (soc_impl->native_fd, &read_fds);
454
      // Create the timeout struct based on our internal timeout value.
455
      struct timeval timeout_value;
456
      timeout_value.tv_sec = soc_impl->timeout / 1000;
457
      timeout_value.tv_usec =(soc_impl->timeout % 1000) * 1000;
458
      // Select on the fds.
459
      int sel_retval =
460
        _Jv_select (soc_impl->native_fd + 1,
461
                    &read_fds, NULL, NULL, &timeout_value);
462
      // We're only interested in the 0 return.
463
      // error returns still require us to try to read 
464
      // the socket to see what happened.
465
      if (sel_retval == 0)
466
        {
467
          ::java::net::SocketTimeoutException *timeoutException =
468
            new ::java::net::SocketTimeoutException
469
            (JvNewStringUTF ("Read timed out"));
470
          throw timeoutException;
471
        }
472
    }
473
 
474
  // Read the socket.
475
  int r = ::recv (soc_impl->native_fd, (char *) bytes, count, 0);
476
 
477
  if (r == 0)
478
    {
479
      throw_on_sock_closed (soc_impl);
480
      return -1;
481
    }
482
 
483
  if (::java::lang::Thread::interrupted())
484
    {
485
      ::java::io::InterruptedIOException *iioe =
486
        new ::java::io::InterruptedIOException
487
        (JvNewStringUTF ("Read interrupted"));
488
      iioe->bytesTransferred = r == -1 ? 0 : r;
489
      throw iioe;
490
    }
491
  else if (r == -1)
492
    {
493
      throw_on_sock_closed (soc_impl);
494
      // Some errors cause us to return end of stream...
495
      if (errno == ENOTCONN)
496
        return -1;
497
 
498
      // Other errors need to be signalled.
499
      throw new ::java::io::IOException (JvNewStringUTF (strerror (errno)));
500
    }
501
 
502
  return r;
503
}
504
 
505
// How many bytes are available?
506
jint
507
gnu::java::net::PlainSocketImpl::available(void)
508
{
509
#if defined(FIONREAD) || defined(HAVE_SELECT)
510
  int num = 0;
511
  int r = 0;
512
  bool num_set = false;
513
 
514
#if defined(FIONREAD)
515
  r = ::ioctl (native_fd, FIONREAD, &num);
516
 
517
  if (r == -1 && errno == ENOTTY)
518
    {
519
      // If the ioctl doesn't work, we don't care.
520
      r = 0;
521
      num = 0;
522
    }
523
  else
524
    num_set = true;
525
#elif defined(HAVE_SELECT)
526
  if (native_fd < 0)
527
    {
528
      errno = EBADF;
529
      r = -1;
530
    }
531
#endif
532
 
533
  if (r == -1)
534
    {
535
    posix_error:
536
      throw new ::java::io::IOException(JvNewStringUTF(strerror(errno)));
537
    }
538
 
539
  // If we didn't get anything we can use select.
540
 
541
#if defined(HAVE_SELECT)
542
  if (! num_set)
543
    if (! num_set && native_fd >= 0 && native_fd < FD_SETSIZE)
544
      {
545
        fd_set rd;
546
        FD_ZERO (&rd);
547
        FD_SET (native_fd, &rd);
548
        struct timeval tv;
549
        tv.tv_sec = 0;
550
        tv.tv_usec = 0;
551
        r = _Jv_select (native_fd + 1, &rd, NULL, NULL, &tv);
552
        if(r == -1)
553
          goto posix_error;
554
        num = r == 0 ? 0 : 1;
555
      }
556
#endif /* HAVE_SELECT */
557
 
558
  return (jint) num;
559
#else
560
  throw new ::java::io::IOException (JvNewStringUTF ("unimplemented"));
561
#endif
562
}
563
 
564
void
565
gnu::java::net::PlainSocketImpl::setOption (jint optID, ::java::lang::Object *value)
566
{
567
  int val;
568
  socklen_t val_len = sizeof (val);
569
 
570
  if (native_fd < 0)
571
    throw new ::java::net::SocketException (JvNewStringUTF ("Socket closed"));
572
 
573
  if (_Jv_IsInstanceOf (value, &::java::lang::Boolean::class$))
574
    {
575
      ::java::lang::Boolean *boolobj =
576
        static_cast< ::java::lang::Boolean *> (value);
577
      if (boolobj->booleanValue())
578
        val = 1;
579
      else
580
        {
581
          if (optID == _Jv_SO_LINGER_)
582
            val = -1;
583
          else
584
            val = 0;
585
        }
586
    }
587
  else if (_Jv_IsInstanceOf (value, &::java::lang::Integer::class$))
588
    {
589
      ::java::lang::Integer *intobj =
590
        static_cast< ::java::lang::Integer *> (value);
591
      val = (int) intobj->intValue();
592
    }
593
  else
594
    {
595
      throw new ::java::lang::IllegalArgumentException (
596
        JvNewStringLatin1 ("`value' must be Boolean or Integer"));
597
    }
598
 
599
  switch (optID)
600
    {
601
      case _Jv_TCP_NODELAY_ :
602
#ifdef TCP_NODELAY
603
        if (::setsockopt (native_fd, IPPROTO_TCP, TCP_NODELAY, (char *) &val,
604
                          val_len) != 0)
605
          goto error;
606
#else
607
        throw new ::java::lang::InternalError
608
          (JvNewStringUTF ("TCP_NODELAY not supported"));
609
#endif /* TCP_NODELAY */
610
        return;
611
 
612
      case _Jv_SO_KEEPALIVE_ :
613
        if (::setsockopt (native_fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &val,
614
                          val_len) != 0)
615
          goto error;
616
        return;
617
 
618
      case _Jv_SO_BROADCAST_ :
619
        throw new ::java::net::SocketException
620
          (JvNewStringUTF ("SO_BROADCAST not valid for TCP"));
621
        return;
622
 
623
      case _Jv_SO_OOBINLINE_ :
624
        if (::setsockopt (native_fd, SOL_SOCKET, SO_OOBINLINE, (char *) &val,
625
                          val_len) != 0)
626
          goto error;
627
        return;
628
 
629
      case _Jv_SO_LINGER_ :
630
#ifdef SO_LINGER
631
        struct linger l_val;
632
        l_val.l_onoff = (val != -1);
633
        l_val.l_linger = val;
634
 
635
        if (::setsockopt (native_fd, SOL_SOCKET, SO_LINGER, (char *) &l_val,
636
                          sizeof(l_val)) != 0)
637
          goto error;
638
#else
639
        throw new ::java::lang::InternalError (
640
          JvNewStringUTF ("SO_LINGER not supported"));
641
#endif /* SO_LINGER */
642
        return;
643
 
644
      case _Jv_SO_SNDBUF_ :
645
      case _Jv_SO_RCVBUF_ :
646
#if defined(SO_SNDBUF) && defined(SO_RCVBUF)
647
        int opt;
648
        optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
649
        if (::setsockopt (native_fd, SOL_SOCKET, opt, (char *) &val, val_len) != 0)
650
          goto error;
651
#else
652
        throw new ::java::lang::InternalError (
653
          JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
654
#endif 
655
        return;
656
 
657
      case _Jv_SO_BINDADDR_ :
658
        throw new ::java::net::SocketException (
659
          JvNewStringUTF ("SO_BINDADDR: read only option"));
660
        return;
661
 
662
      case _Jv_IP_MULTICAST_IF_ :
663
        throw new ::java::net::SocketException (
664
          JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"));
665
        return;
666
 
667
      case _Jv_IP_MULTICAST_IF2_ :
668
        throw new ::java::net::SocketException (
669
          JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP"));
670
        return;
671
 
672
      case _Jv_IP_MULTICAST_LOOP_ :
673
        throw new ::java::net::SocketException (
674
          JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP"));
675
        return;
676
 
677
      case _Jv_IP_TOS_ :
678
        if (::setsockopt (native_fd, SOL_SOCKET, IP_TOS, (char *) &val,
679
                          val_len) != 0)
680
          goto error;
681
        return;
682
 
683
      case _Jv_SO_REUSEADDR_ :
684
#if defined(SO_REUSEADDR)
685
        if (::setsockopt (native_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
686
            val_len) != 0)
687
          goto error;
688
        return;
689
#else
690
        throw new ::java::lang::InternalError (
691
          JvNewStringUTF ("SO_REUSEADDR not supported"));
692
#endif 
693
 
694
      case _Jv_SO_TIMEOUT_ :
695
        timeout = val;
696
        return;
697
 
698
      default :
699
        errno = ENOPROTOOPT;
700
    }
701
 
702
 error:
703
  char* strerr = strerror (errno);
704
  throw new ::java::net::SocketException (JvNewStringUTF (strerr));
705
}
706
 
707
::java::lang::Object *
708
gnu::java::net::PlainSocketImpl::getOption (jint optID)
709
{
710
  int val;
711
  socklen_t val_len = sizeof(val);
712
  union SockAddr u;
713
  socklen_t addrlen = sizeof(u);
714
  struct linger l_val;
715
  socklen_t l_val_len = sizeof(l_val);
716
 
717
  switch (optID)
718
    {
719
#ifdef TCP_NODELAY
720
    case _Jv_TCP_NODELAY_ :
721
      if (::getsockopt (native_fd, IPPROTO_TCP, TCP_NODELAY, (char *) &val,
722
                        &val_len) != 0)
723
        goto error;
724
      else
725
        return new ::java::lang::Boolean (val != 0);
726
#else
727
      throw new ::java::lang::InternalError
728
        (JvNewStringUTF ("TCP_NODELAY not supported"));
729
#endif       
730
      break;
731
 
732
    case _Jv_SO_LINGER_ :
733
#ifdef SO_LINGER
734
      if (::getsockopt (native_fd, SOL_SOCKET, SO_LINGER, (char *) &l_val,
735
                        &l_val_len) != 0)
736
        goto error;
737
 
738
      if (l_val.l_onoff)
739
        return new ::java::lang::Integer (l_val.l_linger);
740
      else
741
        return new ::java::lang::Boolean ((jboolean)false);
742
#else
743
      throw new ::java::lang::InternalError
744
        (JvNewStringUTF ("SO_LINGER not supported"));
745
#endif
746
      break;
747
 
748
    case _Jv_SO_KEEPALIVE_ :
749
      if (::getsockopt (native_fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &val,
750
                        &val_len) != 0)
751
        goto error;
752
      else
753
        return new ::java::lang::Boolean (val != 0);
754
 
755
    case _Jv_SO_BROADCAST_ :
756
      if (::getsockopt (native_fd, SOL_SOCKET, SO_BROADCAST, (char *) &val,
757
                        &val_len) != 0)
758
        goto error;
759
      return new ::java::lang::Boolean ((jboolean)val);
760
 
761
    case _Jv_SO_OOBINLINE_ :
762
      if (::getsockopt (native_fd, SOL_SOCKET, SO_OOBINLINE, (char *) &val,
763
                        &val_len) != 0)
764
        goto error;
765
      return new ::java::lang::Boolean ((jboolean)val);
766
 
767
    case _Jv_SO_RCVBUF_ :
768
    case _Jv_SO_SNDBUF_ :
769
#if defined(SO_SNDBUF) && defined(SO_RCVBUF)
770
      int opt;
771
      optID == _Jv_SO_SNDBUF_ ? opt = SO_SNDBUF : opt = SO_RCVBUF;
772
      if (::getsockopt (native_fd, SOL_SOCKET, opt, (char *) &val, &val_len) != 0)
773
        goto error;
774
      else
775
        return new ::java::lang::Integer (val);
776
#else
777
      throw new ::java::lang::InternalError
778
        (JvNewStringUTF ("SO_RCVBUF/SO_SNDBUF not supported"));
779
#endif    
780
      break;
781
    case _Jv_SO_BINDADDR_:
782
      // cache the local address 
783
      if (localAddress == NULL)
784
        {
785
          jbyteArray laddr;
786
 
787
          if (::getsockname (native_fd, (sockaddr*) &u, &addrlen) != 0)
788
            goto error;
789
 
790
          if (u.address.sin_family == AF_INET)
791
            {
792
              laddr = JvNewByteArray (4);
793
              memcpy (elements (laddr), &u.address.sin_addr, 4);
794
            }
795
#ifdef HAVE_INET6
796
          else if (u.address.sin_family == AF_INET6)
797
            {
798
              laddr = JvNewByteArray (16);
799
              memcpy (elements (laddr), &u.address6.sin6_addr, 16);
800
            }
801
#endif
802
          else
803
            throw new ::java::net::SocketException
804
              (JvNewStringUTF ("invalid family"));
805
          localAddress = ::java::net::InetAddress::getByAddress (laddr);
806
        }
807
 
808
      return localAddress;
809
      break;
810
    case _Jv_IP_MULTICAST_IF_ :
811
      throw new ::java::net::SocketException
812
        (JvNewStringUTF ("IP_MULTICAST_IF: not valid for TCP"));
813
      break;
814
 
815
    case _Jv_IP_MULTICAST_IF2_ :
816
      throw new ::java::net::SocketException
817
        (JvNewStringUTF ("IP_MULTICAST_IF2: not valid for TCP"));
818
      break;
819
 
820
    case _Jv_IP_MULTICAST_LOOP_ :
821
      throw new ::java::net::SocketException
822
        (JvNewStringUTF ("IP_MULTICAST_LOOP: not valid for TCP"));
823
      break;
824
 
825
    case _Jv_IP_TOS_ :
826
      if (::getsockopt (native_fd, SOL_SOCKET, IP_TOS, (char *) &val,
827
                        &val_len) != 0)
828
        goto error;
829
      return new ::java::lang::Integer (val);
830
      break;
831
 
832
    case _Jv_SO_REUSEADDR_ :
833
#if defined(SO_REUSEADDR)
834
      if (::getsockopt (native_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &val,
835
                        &val_len) != 0)
836
        goto error;
837
#else
838
        throw new ::java::lang::InternalError (
839
          JvNewStringUTF ("SO_REUSEADDR not supported"));
840
#endif 
841
      break;
842
 
843
    case _Jv_SO_TIMEOUT_ :
844
      return new ::java::lang::Integer (timeout);
845
      break;
846
 
847
    default :
848
      errno = ENOPROTOOPT;
849
    }
850
 
851
 error:
852
  char* strerr = strerror (errno);
853
  throw new ::java::net::SocketException (JvNewStringUTF (strerr));
854
}
855
 
856
void
857
gnu::java::net::PlainSocketImpl::shutdownInput (void)
858
{
859
  if (::shutdown (native_fd, 0))
860
    throw new ::java::net::SocketException (JvNewStringUTF (strerror (errno)));
861
}
862
 
863
void
864
gnu::java::net::PlainSocketImpl::shutdownOutput (void)
865
{
866
  if (::shutdown (native_fd, 1))
867
    throw new ::java::net::SocketException (JvNewStringUTF (strerror (errno)));
868
}

powered by: WebSVN 2.1.0

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