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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [java/] [net/] [PlainSocketImpl.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* PlainSocketImpl.java -- Default socket implementation
2
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
3
   Free Software Foundation, Inc.
4
 
5
This file is part of GNU Classpath.
6
 
7
GNU Classpath is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2, or (at your option)
10
any later version.
11
 
12
GNU Classpath is distributed in the hope that it will be useful, but
13
WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GNU Classpath; see the file COPYING.  If not, write to the
19
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20
02110-1301 USA.
21
 
22
Linking this library statically or dynamically with other modules is
23
making a combined work based on this library.  Thus, the terms and
24
conditions of the GNU General Public License cover the whole
25
combination.
26
 
27
As a special exception, the copyright holders of this library give you
28
permission to link this library with independent modules to produce an
29
executable, regardless of the license terms of these independent
30
modules, and to copy and distribute the resulting executable under
31
terms of your choice, provided that you also meet, for each linked
32
independent module, the terms and conditions of the license of that
33
module.  An independent module is a module which is not derived from
34
or based on this library.  If you modify this library, you may extend
35
this exception to your version of the library, but you are not
36
obligated to do so.  If you do not wish to do so, delete this
37
exception statement from your version. */
38
 
39
 
40
package gnu.java.net;
41
 
42
import gnu.java.nio.SocketChannelImpl;
43
import gnu.java.nio.VMChannel;
44
 
45
import java.io.InputStream;
46
import java.io.IOException;
47
import java.io.InterruptedIOException;
48
import java.io.OutputStream;
49
import java.net.InetAddress;
50
import java.net.InetSocketAddress;
51
import java.net.SocketAddress;
52
import java.net.SocketException;
53
import java.net.SocketImpl;
54
import java.net.SocketTimeoutException;
55
import java.nio.ByteBuffer;
56
 
57
/**
58
 * Written using on-line Java Platform 1.2 API Specification, as well
59
 * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
60
 * Status:  Believed complete and correct.
61
 */
62
 
63
/**
64
 * Unless the application installs its own SocketImplFactory, this is the
65
 * default socket implemetation that will be used.  It simply uses a
66
 * combination of Java and native routines to implement standard BSD
67
 * style sockets of family AF_INET and types SOCK_STREAM and SOCK_DGRAM
68
 *
69
 * @author Per Bothner (bothner@cygnus.com)
70
 * @author Nic Ferrier (nferrier@tapsellferrier.co.uk)
71
 * @author Aaron M. Renn (arenn@urbanophile.com)
72
 */
73
public class PlainSocketImpl extends SocketImpl
74
{
75
 
76
  /**
77
   * The underlying plain socket VM implementation.
78
   */
79
  protected VMPlainSocketImpl impl;
80
 
81
  /**
82
   * A cached copy of the in stream for reading from the socket.
83
   */
84
  private InputStream in;
85
 
86
  /**
87
   * A cached copy of the out stream for writing to the socket.
88
   */
89
  private OutputStream out;
90
 
91
  /**
92
   * Indicates whether a channel initiated whatever operation
93
   * is being invoked on this socket.
94
   */
95
  private boolean inChannelOperation;
96
 
97
  /**
98
   * The socket channel we use for IO operation. Package-private for
99
   * use by inner classes.
100
   */
101
  SocketChannelImpl channel;
102
 
103
  /**
104
   * Indicates whether we should ignore whether any associated
105
   * channel is set to non-blocking mode. Certain operations
106
   * throw an <code>IllegalBlockingModeException</code> if the
107
   * associated channel is in non-blocking mode, <i>except</i>
108
   * if the operation is invoked by the channel itself.
109
   */
110
  public final boolean isInChannelOperation()
111
  {
112
    return inChannelOperation;
113
  }
114
 
115
  /**
116
   * Sets our indicator of whether an I/O operation is being
117
   * initiated by a channel.
118
   */
119
  public final void setInChannelOperation(boolean b)
120
  {
121
    inChannelOperation = b;
122
  }
123
 
124
  /**
125
   * Default do nothing constructor.
126
   */
127
  public PlainSocketImpl()
128
  {
129
    this.impl = new VMPlainSocketImpl();
130
  }
131
 
132
  /**
133
   * Sets the specified option on a socket to the passed in object.  For
134
   * options that take an integer argument, the passed in object is an
135
   * Integer.  The option_id parameter is one of the defined constants in
136
   * this interface.
137
   *
138
   * @param optionId The identifier of the option
139
   * @param value The value to set the option to
140
   *
141
   * @throws SocketException if an error occurs
142
   */
143
  public void setOption(int optionId, Object value) throws SocketException
144
  {
145
    switch (optionId)
146
      {
147
        case SO_LINGER:
148
        case IP_MULTICAST_LOOP:
149
        case SO_BROADCAST:
150
        case SO_KEEPALIVE:
151
        case SO_OOBINLINE:
152
        case TCP_NODELAY:
153
        case IP_TOS:
154
        case SO_RCVBUF:
155
        case SO_SNDBUF:
156
        case SO_TIMEOUT:
157
        case SO_REUSEADDR:
158
          impl.setOption(optionId, value);
159
          return;
160
        default:
161
          throw new SocketException("Unrecognized TCP option: " + optionId);
162
      }
163
  }
164
 
165
  /**
166
   * Returns the current setting of the specified option.  The Object returned
167
   * will be an Integer for options that have integer values.  The option_id
168
   * is one of the defined constants in this interface.
169
   *
170
   * @param optionId the option identifier
171
   *
172
   * @return the current value of the option
173
   *
174
   * @throws SocketException if an error occurs
175
   */
176
  public Object getOption(int optionId) throws SocketException
177
  {
178
    if (optionId == SO_BINDADDR)
179
      {
180
        try
181
          {
182
            return channel.getVMChannel().getLocalAddress().getAddress();
183
          }
184
        catch (IOException ioe)
185
          {
186
            SocketException se = new SocketException();
187
            se.initCause(ioe);
188
            throw se;
189
          }
190
      }
191
 
192
    // This filters options which are invalid for TCP.
193
    switch (optionId)
194
    {
195
      case SO_LINGER:
196
      case IP_MULTICAST_LOOP:
197
      case SO_BROADCAST:
198
      case SO_KEEPALIVE:
199
      case SO_OOBINLINE:
200
      case TCP_NODELAY:
201
      case IP_TOS:
202
      case SO_RCVBUF:
203
      case SO_SNDBUF:
204
      case SO_TIMEOUT:
205
      case SO_REUSEADDR:
206
        return impl.getOption(optionId);
207
      default:
208
        throw new SocketException("Unrecognized TCP option: " + optionId);
209
    }
210
 
211
  }
212
 
213
  public void shutdownInput() throws IOException
214
  {
215
    impl.shutdownInput();
216
  }
217
 
218
  public void shutdownOutput() throws IOException
219
  {
220
    impl.shutdownOutput();
221
  }
222
 
223
  /**
224
   * Creates a new socket that is not bound to any local address/port and
225
   * is not connected to any remote address/port.  The stream parameter will be
226
   * ignored since PlainSocketImpl always is a stream socket. Datagram sockets
227
   * are handled by PlainDatagramSocketImpl.
228
   *
229
   * @param stream <code>true</code> for stream sockets, <code>false</code> for
230
   *        datagram sockets
231
   */
232
  protected synchronized void create(boolean stream) throws IOException
233
  {
234
    channel = new SocketChannelImpl(false);
235
    VMChannel vmchannel = channel.getVMChannel();
236
    vmchannel.initSocket(stream);
237
    channel.configureBlocking(true);
238
    impl.getState().setChannelFD(vmchannel.getState());
239
  }
240
 
241
  /**
242
   * Connects to the remote hostname and port specified as arguments.
243
   *
244
   * @param hostname the remote hostname to connect to
245
   * @param port the remote port to connect to
246
   *
247
   * @throws IOException If an error occurs
248
   */
249
  protected synchronized void connect(String hostname, int port)
250
    throws IOException
251
  {
252
    connect(InetAddress.getByName(hostname), port);
253
  }
254
 
255
  /**
256
   * Connects to the remote address and port specified as arguments.
257
   *
258
   * @param addr the remote address to connect to
259
   * @param port the remote port to connect to
260
   *
261
   * @throws IOException If an error occurs
262
   */
263
  protected void connect(InetAddress addr, int port) throws IOException
264
  {
265
    connect(new InetSocketAddress(addr, port), 0);
266
  }
267
 
268
  /**
269
   * Connects to the remote socket address with a specified timeout.
270
   *
271
   * @param address the remote address to connect to
272
   * @param timeout the timeout to use for this connect, 0 means infinite.
273
   *
274
   * @throws IOException If an error occurs
275
   */
276
  protected synchronized void connect(SocketAddress address, int timeout)
277
    throws IOException
278
  {
279
    if (channel == null)
280
      create(true);
281
    boolean connected = channel.connect(address, timeout);
282
    if (!connected)
283
      throw new SocketTimeoutException("connect timed out");
284
 
285
    // Using the given SocketAddress is important to preserve
286
    // hostnames given by the caller.
287
    InetSocketAddress addr = (InetSocketAddress) address;
288
    this.address = addr.getAddress();
289
    this.port = addr.getPort();
290
  }
291
 
292
  /**
293
   * Binds to the specified port on the specified addr.  Note that this addr
294
   * must represent a local IP address.  **** How bind to INADDR_ANY? ****
295
   *
296
   * @param addr the address to bind to
297
   * @param port the port number to bind to
298
   *
299
   * @throws IOException if an error occurs
300
   */
301
  protected synchronized void bind(InetAddress addr, int port)
302
    throws IOException
303
  {
304
    if (channel == null)
305
      create(true);
306
    impl.bind(new InetSocketAddress(addr, port));
307
    localport = channel.getVMChannel().getLocalAddress().getPort();
308
  }
309
 
310
  /**
311
   * Starts listening for connections on a socket. The queuelen parameter
312
   * is how many pending connections will queue up waiting to be serviced
313
   * before being accept'ed.  If the queue of pending requests exceeds this
314
   * number, additional connections will be refused.
315
   *
316
   * @param queuelen The length of the pending connection queue
317
   *
318
   * @throws IOException If an error occurs
319
   */
320
  protected synchronized void listen(int queuelen)
321
    throws IOException
322
  {
323
    impl.listen(queuelen);
324
  }
325
 
326
  /**
327
   * Accepts a new connection on this socket and returns in in the
328
   * passed in SocketImpl.
329
   *
330
   * @param impl The SocketImpl object to accept this connection.
331
   */
332
  protected synchronized void accept(SocketImpl impl)
333
    throws IOException
334
  {
335
    if (channel == null)
336
        create(true);
337
    if (!(impl instanceof PlainSocketImpl))
338
      throw new IOException("incompatible SocketImpl: "
339
                            + impl.getClass().getName());
340
    PlainSocketImpl that = (PlainSocketImpl) impl;
341
    VMChannel c = channel.getVMChannel().accept();
342
    that.impl.getState().setChannelFD(c.getState());
343
    that.channel = new SocketChannelImpl(c);
344
    that.setOption(SO_REUSEADDR, Boolean.TRUE);
345
    // Reset the inherited timeout.
346
    that.setOption(SO_TIMEOUT, Integer.valueOf(0));
347
 
348
  }
349
 
350
  /**
351
   * Returns the number of bytes that the caller can read from this socket
352
   * without blocking.
353
   *
354
   * @return the number of readable bytes before blocking
355
   *
356
   * @throws IOException if an error occurs
357
   */
358
  protected int available() throws IOException
359
  {
360
    if (channel == null)
361
      throw new SocketException("not connected");
362
    return channel.getVMChannel().available();
363
  }
364
 
365
  /**
366
   * Closes the socket.  This will cause any InputStream or OutputStream
367
   * objects for this Socket to be closed as well.
368
   *
369
   * <p>
370
   * Note that if the SO_LINGER option is set on this socket, then the
371
   * operation could block.
372
   * </p>
373
   *
374
   * @throws IOException if an error occurs
375
   */
376
  protected void close() throws IOException
377
  {
378
    if (impl.getState().isValid())
379
      impl.close();
380
 
381
    address = null;
382
    port = -1;
383
  }
384
 
385
  public void sendUrgentData(int data) throws IOException
386
  {
387
    impl.sendUrgentData(data);
388
  }
389
 
390
  /**
391
   * Returns an InputStream object for reading from this socket.  This will
392
   * be an instance of SocketInputStream.
393
   *
394
   * @return An input stream attached to the socket.
395
   *
396
   * @exception IOException If an error occurs
397
   */
398
  protected synchronized InputStream getInputStream() throws IOException
399
  {
400
    if (in == null)
401
      in = new SocketInputStream();
402
 
403
    return in;
404
  }
405
 
406
  /**
407
   * Returns an OutputStream object for writing to this socket.  This will
408
   * be an instance of SocketOutputStream.
409
   *
410
   * @return An output stream attached to the socket.
411
   *
412
   * @exception IOException If an error occurs
413
   */
414
  protected synchronized OutputStream getOutputStream() throws IOException
415
  {
416
    if (out == null)
417
      out = new SocketOutputStream();
418
 
419
    return out;
420
  }
421
 
422
  public VMChannel getVMChannel()
423
  {
424
    if (channel == null)
425
      return null;
426
    return channel.getVMChannel();
427
  }
428
 
429
  /* (non-Javadoc)
430
   * @see java.net.SocketImpl#getInetAddress()
431
   */
432
  protected InetAddress getInetAddress()
433
  {
434
    if (channel == null)
435
      return null;
436
 
437
    try
438
      {
439
        InetSocketAddress remote = channel.getVMChannel().getPeerAddress();
440
        if (remote == null)
441
          return null;
442
        // To mimic behavior of the RI the InetAddress instance which was
443
        // used to establish the connection is returned instead of one that
444
        // was created by the native layer (this preserves exact hostnames).
445
        if (address != null)
446
          return address;
447
 
448
        return remote.getAddress();
449
      }
450
    catch (IOException ioe)
451
      {
452
        return null;
453
      }
454
  }
455
 
456
  /* (non-Javadoc)
457
   * @see java.net.SocketImpl#getLocalPort()
458
   */
459
  protected int getLocalPort()
460
  {
461
    if (channel == null)
462
      return -1;
463
    try
464
      {
465
        InetSocketAddress local = channel.getVMChannel().getLocalAddress();
466
        if (local == null)
467
          return -1;
468
        return local.getPort();
469
      }
470
    catch (IOException ioe)
471
      {
472
        return -1;
473
      }
474
  }
475
 
476
  public InetSocketAddress getLocalAddress()
477
  {
478
    if (channel == null)
479
      return null;
480
    try
481
      {
482
        return channel.getVMChannel().getLocalAddress();
483
      }
484
    catch (IOException ioe)
485
      {
486
        return null;
487
      }
488
  }
489
 
490
  /* (non-Javadoc)
491
   * @see java.net.SocketImpl#getPort()
492
   */
493
  protected int getPort()
494
  {
495
    if (channel == null)
496
      return -1;
497
 
498
    try
499
      {
500
        InetSocketAddress remote = channel.getVMChannel().getPeerAddress();
501
        if (remote == null)
502
          return -1;
503
        return remote.getPort();
504
      }
505
    catch (IOException ioe)
506
      {
507
        return -1;
508
      }
509
  }
510
 
511
  /**
512
   * This class contains an implementation of <code>InputStream</code> for
513
   * sockets.  It in an internal only class used by <code>PlainSocketImpl</code>.
514
   *
515
   * @author Nic Ferrier <nferrier@tapsellferrier.co.uk>
516
   */
517
  final class SocketInputStream
518
    extends InputStream
519
  {
520
    /**
521
     * Returns the number of bytes available to be read before blocking
522
     */
523
    public int available() throws IOException
524
    {
525
      return PlainSocketImpl.this.available();
526
    }
527
 
528
    /**
529
     * This method not only closes the stream, it closes the underlying socket
530
     * (and thus any connection) and invalidates any other Input/Output streams
531
     * for the underlying impl object
532
     */
533
    public void close() throws IOException
534
    {
535
      PlainSocketImpl.this.close();
536
    }
537
 
538
    /**
539
     * Reads the next byte of data and returns it as an int.
540
     *
541
     * @return The byte read (as an int) or -1 if end of stream);
542
     *
543
     * @exception IOException If an error occurs.
544
     */
545
    public int read() throws IOException
546
    {
547
      if (channel == null)
548
        throw new SocketException("not connected");
549
      while (true)
550
        {
551
          try
552
            {
553
              return channel.getVMChannel().read();
554
            }
555
          catch (SocketTimeoutException ste)
556
            {
557
              throw ste;
558
            }
559
          catch (InterruptedIOException iioe)
560
            {
561
              // Ignore; NIO may throw this; net io shouldn't
562
            }
563
        }
564
    }
565
 
566
    /**
567
     * Reads up to len bytes of data into the caller supplied buffer starting
568
     * at offset bytes from the start of the buffer
569
     *
570
     * @param buf The buffer
571
     * @param offset Offset into the buffer to start reading from
572
     * @param len The number of bytes to read
573
     *
574
     * @return The number of bytes actually read or -1 if end of stream
575
     *
576
     * @exception IOException If an error occurs.
577
     */
578
    public int read (byte[] buf, int offset, int len) throws IOException
579
    {
580
      if (channel == null)
581
        throw new SocketException("not connected");
582
      ByteBuffer b = ByteBuffer.wrap(buf, offset, len);
583
      while (true)
584
        {
585
          try
586
            {
587
              return channel.read(b);
588
            }
589
          catch (SocketTimeoutException ste)
590
            {
591
              throw ste;
592
            }
593
          catch (InterruptedIOException iioe)
594
            {
595
              // Ignored; NIO may throw this; net IO not.
596
            }
597
        }
598
    }
599
  }
600
 
601
  /**
602
   * This class is used internally by <code>PlainSocketImpl</code> to be the
603
   * <code>OutputStream</code> subclass returned by its
604
   * <code>getOutputStream method</code>.  It expects only to  be used in that
605
   * context.
606
   *
607
   * @author Nic Ferrier  <nferrier@tapsellferrier.co.uk>
608
   */
609
  final class SocketOutputStream
610
    extends OutputStream
611
  {
612
    /**
613
     * This method closes the stream and the underlying socket connection. This
614
     * action also effectively closes any other InputStream or OutputStream
615
     * object associated with the connection.
616
     *
617
     * @exception IOException If an error occurs
618
     */
619
    public void close() throws IOException
620
    {
621
      PlainSocketImpl.this.close();
622
    }
623
 
624
    /**
625
     * Writes a byte (passed in as an int) to the given output stream
626
     *
627
     * @param b The byte to write
628
     *
629
     * @exception IOException If an error occurs
630
     */
631
    public void write(int b) throws IOException
632
    {
633
      if (channel == null)
634
        throw new SocketException("not connected");
635
      while (true)
636
        {
637
          try
638
            {
639
              channel.getVMChannel().write(b);
640
              return;
641
            }
642
          catch (InterruptedIOException iioe)
643
            {
644
              // Ignored.
645
            }
646
        }
647
    }
648
 
649
    /**
650
     * Writes len number of bytes from the array buf to the stream starting
651
     * at offset bytes into the buffer.
652
     *
653
     * @param buf The buffer
654
     * @param offset Offset into the buffer to start writing from
655
     * @param len The number of bytes to write
656
     *
657
     * @exception IOException If an error occurs.
658
     */
659
    public void write (byte[] buf, int offset, int len) throws IOException
660
    {
661
      if (channel == null)
662
        throw new SocketException("not connected");
663
      ByteBuffer b = ByteBuffer.wrap(buf, offset, len);
664
      while (b.hasRemaining())
665
        {
666
          try
667
            {
668
              if (channel.write(b) == -1)
669
                throw new IOException("channel has been closed");
670
            }
671
          catch (InterruptedIOException iioe)
672
            {
673
              // Ignored.
674
            }
675
        }
676
    }
677
  }
678
}

powered by: WebSVN 2.1.0

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