OSDN Git Service

dad1724d6b10efd402731e99976c83fe385d7c2d
[pf3gnuchains/gcc-fork.git] / libjava / gnu / java / net / PlainSocketImpl.java
1 /* PlainSocketImpl.java -- Default socket implementation
2    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
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.classpath.Configuration;
43
44 import java.io.IOException;
45 import java.io.InputStream;
46 import java.io.OutputStream;
47 import java.net.InetAddress;
48 import java.net.InetSocketAddress;
49 import java.net.SocketAddress;
50 import java.net.SocketException;
51 import java.net.SocketImpl;
52 import java.net.SocketOptions;
53
54 /**
55  * Written using on-line Java Platform 1.2 API Specification, as well
56  * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
57  * Status:  Believed complete and correct.
58  */
59
60 /**
61  * Unless the application installs its own SocketImplFactory, this is the
62  * default socket implemetation that will be used.  It simply uses a
63  * combination of Java and native routines to implement standard BSD
64  * style sockets of family AF_INET and types SOCK_STREAM and SOCK_DGRAM
65  *
66  * @author Per Bothner (bothner@cygnus.com)
67  * @author Nic Ferrier (nferrier@tapsellferrier.co.uk)
68  * @author Aaron M. Renn (arenn@urbanophile.com)
69  */
70 public final class PlainSocketImpl extends SocketImpl
71 {
72   // Static initializer to load native library.
73   static
74     {
75       if (Configuration.INIT_LOAD_LIBRARY)
76         {
77           System.loadLibrary("javanet");
78         }
79     }
80   
81   // These fields are mirrored for use in native code to avoid cpp conflicts
82   // when the #defines in system header files are the same as the public fields.
83   static final int _Jv_TCP_NODELAY_ = SocketOptions.TCP_NODELAY,
84                    _Jv_SO_BINDADDR_ = SocketOptions.SO_BINDADDR,
85                    _Jv_SO_REUSEADDR_ = SocketOptions.SO_REUSEADDR,
86                    _Jv_SO_BROADCAST_ = SocketOptions.SO_BROADCAST,
87                    _Jv_SO_OOBINLINE_ = SocketOptions.SO_OOBINLINE,
88                    _Jv_IP_MULTICAST_IF_ = SocketOptions.IP_MULTICAST_IF,
89                    _Jv_IP_MULTICAST_IF2_ = SocketOptions.IP_MULTICAST_IF2,
90                    _Jv_IP_MULTICAST_LOOP_ = SocketOptions.IP_MULTICAST_LOOP,
91                    _Jv_IP_TOS_ = SocketOptions.IP_TOS,
92                    _Jv_SO_LINGER_ = SocketOptions.SO_LINGER,
93                    _Jv_SO_TIMEOUT_ = SocketOptions.SO_TIMEOUT,
94                    _Jv_SO_SNDBUF_ = SocketOptions.SO_SNDBUF,
95                    _Jv_SO_RCVBUF_ = SocketOptions.SO_RCVBUF,
96                    _Jv_SO_KEEPALIVE_ = SocketOptions.SO_KEEPALIVE;
97
98   /**
99    * The OS file handle representing the socket.
100    * This is used for reads and writes to/from the socket and
101    * to close it.
102    *
103    * When the socket is closed this is reset to -1.
104    */
105   int native_fd = -1;
106
107   // This value is set/read by setOption/getOption.
108   int timeout = 0;
109   
110   // localAddress cache
111   InetAddress localAddress;
112
113   // Local address as an InetSocketAddress.
114   InetSocketAddress localSocketAddress;
115
116   /**
117    * A cached copy of the in stream for reading from the socket.
118    */
119   private InputStream in;
120
121   /**
122    * A cached copy of the out stream for writing to the socket.
123    */
124   private OutputStream out;
125
126   /**
127    * Indicates whether a channel initiated whatever operation
128    * is being invoked on this socket.
129    */
130   private boolean inChannelOperation;
131
132   /**
133    * Indicates whether we should ignore whether any associated
134    * channel is set to non-blocking mode. Certain operations
135    * throw an <code>IllegalBlockingModeException</code> if the
136    * associated channel is in non-blocking mode, <i>except</i>
137    * if the operation is invoked by the channel itself.
138    */
139   public final boolean isInChannelOperation()
140   {
141     return inChannelOperation;
142   }
143   
144   /**
145    * Sets our indicator of whether an I/O operation is being
146    * initiated by a channel.
147    */
148   public final void setInChannelOperation(boolean b)
149   {
150     inChannelOperation = b;
151   }
152  
153   /**
154    * Default do nothing constructor
155    */
156   public PlainSocketImpl()
157   {
158   }
159   
160   protected void finalize() throws Throwable
161   {
162     synchronized (this)
163       {
164         if (native_fd != -1)
165           try
166             {
167               close();
168             }
169           catch (IOException ex)
170             {
171             }
172       }
173     super.finalize();
174   }
175
176   public int getNativeFD()
177   {
178     return native_fd;
179   }
180
181   /**
182    * Sets the specified option on a socket to the passed in object.  For
183    * options that take an integer argument, the passed in object is an
184    * Integer.  The option_id parameter is one of the defined constants in
185    * this interface.
186    *
187    * @param option_id The identifier of the option
188    * @param val The value to set the option to
189    *
190    * @exception SocketException If an error occurs
191    */
192   public native void setOption(int optID, Object value) throws SocketException;
193
194   /**
195    * Returns the current setting of the specified option.  The Object returned
196    * will be an Integer for options that have integer values.  The option_id
197    * is one of the defined constants in this interface.
198    *
199    * @param option_id The option identifier
200    *
201    * @return The current value of the option
202    *
203    * @exception SocketException If an error occurs
204    */
205   public native Object getOption(int optID) throws SocketException;
206
207   /**
208    * Flushes the input stream and closes it. If you read from the input stream
209    * after calling this method a <code>IOException</code> will be thrown.
210    * 
211    * @throws IOException if an error occurs
212    */
213   public native void shutdownInput() throws IOException;
214
215   /**
216    * Flushes the output stream and closes it. If you write to the output stream
217    * after calling this method a <code>IOException</code> will be thrown.
218    * 
219    * @throws IOException if an error occurs
220    */
221   public native void shutdownOutput() throws IOException;
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.  This will be created as
226    * a stream socket if the stream parameter is true, or a datagram socket
227    * if the stream parameter is false.
228    *
229    * @param stream true for a stream socket, false for a datagram socket
230    */
231   protected native void create(boolean stream) throws IOException;
232
233   /**
234    * Connects to the remote hostname and port specified as arguments.
235    *
236    * @param hostname The remote hostname to connect to
237    * @param port The remote port to connect to
238    *
239    * @exception IOException If an error occurs
240    */
241   protected void connect(String host, int port) throws IOException
242   {
243     connect(InetAddress.getByName(host), port);
244   }
245
246   /**
247    * Connects to the remote address and port specified as arguments.
248    *
249    * @param addr The remote address to connect to
250    * @param port The remote port to connect to
251    *
252    * @exception IOException If an error occurs
253    */
254   protected void connect(InetAddress host, int port) throws IOException
255   {
256     connect (new InetSocketAddress (host, port), 0);
257   }
258
259   /**
260    * Connects to the remote socket address with a specified timeout.
261    *
262    * @param timeout The timeout to use for this connect, 0 means infinite.
263    *
264    * @exception IOException If an error occurs
265    */
266   protected native void connect(SocketAddress addr, int timeout) throws IOException;
267
268   /**
269    * Binds to the specified port on the specified addr.  Note that this addr
270    * must represent a local IP address.  **** How bind to INADDR_ANY? ****
271    *
272    * @param addr The address to bind to
273    * @param port The port number to bind to
274    *
275    * @exception IOException If an error occurs
276    */
277   protected native void bind(InetAddress host, int port)
278     throws IOException;
279
280   /**
281    * Starts listening for connections on a socket. The queuelen parameter
282    * is how many pending connections will queue up waiting to be serviced
283    * before being accept'ed.  If the queue of pending requests exceeds this
284    * number, additional connections will be refused.
285    *
286    * @param queuelen The length of the pending connection queue
287    * 
288    * @exception IOException If an error occurs
289    */
290   protected native void listen(int queuelen)
291     throws IOException;
292
293   /**
294    * Accepts a new connection on this socket and returns in in the 
295    * passed in SocketImpl.
296    *
297    * @param impl The SocketImpl object to accept this connection.
298    */
299   protected void accept(SocketImpl impl)
300     throws IOException
301   {
302     accept((PlainSocketImpl) impl);
303   }
304
305   private native void accept(PlainSocketImpl impl)
306     throws IOException;
307
308   /**
309    * Returns the number of bytes that the caller can read from this socket
310    * without blocking. 
311    *
312    * @return The number of readable bytes before blocking
313    *
314    * @exception IOException If an error occurs
315    */
316   protected native int available() throws IOException;
317
318   /**
319    * Closes the socket.  This will cause any InputStream or OutputStream
320    * objects for this Socket to be closed as well.
321    * <p>
322    * Note that if the SO_LINGER option is set on this socket, then the
323    * operation could block.
324    *
325    * @exception IOException If an error occurs
326    */
327   protected native void close() throws IOException;
328
329   protected native void sendUrgentData(int data) throws IOException;
330
331   public synchronized InetSocketAddress getLocalAddress()
332   {
333     if (localSocketAddress == null)
334       {
335         try
336           {
337             localSocketAddress
338               = new InetSocketAddress ((InetAddress) getOption(SocketOptions.SO_BINDADDR),
339                                        localport);
340           }
341         catch (SocketException _)
342           {
343             return null;
344           }
345       }
346     return localSocketAddress;
347   }
348
349   /**
350    * Returns an InputStream object for reading from this socket.  This will
351    * be an instance of SocketInputStream.
352    *
353    * @return An input stream attached to the socket.
354    *
355    * @exception IOException If an error occurs
356    */
357   protected synchronized InputStream getInputStream() throws IOException
358   {
359     if (in == null)
360       in = new SocketInputStream();
361     
362     return in;
363   }
364
365   /**
366    * Returns an OutputStream object for writing to this socket.  This will
367    * be an instance of SocketOutputStream.
368    *
369    * @return An output stream attached to the socket.
370    *
371    * @exception IOException If an error occurs
372    */
373   protected synchronized OutputStream getOutputStream() throws IOException
374   {
375     if (out == null)
376       out = new SocketOutputStream();
377     
378     return out;
379   }
380
381   /**
382    * This class contains an implementation of <code>InputStream</code> for 
383    * sockets.  It in an internal only class used by <code>PlainSocketImpl</code>.
384    *
385    * @author Nic Ferrier <nferrier@tapsellferrier.co.uk>
386    */
387   final class SocketInputStream
388     extends InputStream
389   {
390     /**
391      * Returns the number of bytes available to be read before blocking
392      */
393     public int available() throws IOException
394     {
395       return PlainSocketImpl.this.available();
396     }
397
398     /**
399      * This method not only closes the stream, it closes the underlying socket
400      * (and thus any connection) and invalidates any other Input/Output streams
401      * for the underlying impl object
402      */
403     public void close() throws IOException
404     {
405       PlainSocketImpl.this.close();
406     }
407
408     /**
409      * Reads the next byte of data and returns it as an int.  
410      *
411      * @return The byte read (as an int) or -1 if end of stream);
412      *
413      * @exception IOException If an error occurs.
414      */
415     public native int read() throws IOException;
416
417     /**
418      * Reads up to len bytes of data into the caller supplied buffer starting
419      * at offset bytes from the start of the buffer
420      *
421      * @param buf The buffer
422      * @param offset Offset into the buffer to start reading from
423      * @param len The number of bytes to read
424      *
425      * @return The number of bytes actually read or -1 if end of stream
426      *
427      * @exception IOException If an error occurs.
428      */
429     public native int read(byte[] buf, int offset, int len) throws IOException;
430   }
431
432   /**
433    * This class is used internally by <code>PlainSocketImpl</code> to be the 
434    * <code>OutputStream</code> subclass returned by its 
435    * <code>getOutputStream method</code>.  It expects only to  be used in that
436    * context.
437    *
438    * @author Nic Ferrier  <nferrier@tapsellferrier.co.uk>
439    */
440   final class SocketOutputStream
441     extends OutputStream
442   {
443     /**
444      * This method closes the stream and the underlying socket connection. This
445      * action also effectively closes any other InputStream or OutputStream
446      * object associated with the connection.
447      *
448      * @exception IOException If an error occurs
449      */
450     public void close() throws IOException
451     {
452       PlainSocketImpl.this.close();
453     }
454
455     /**
456      * Writes a byte (passed in as an int) to the given output stream
457      * 
458      * @param b The byte to write
459      *
460      * @exception IOException If an error occurs
461      */
462     public native void write(int b) throws IOException;
463
464     /**
465      * Writes len number of bytes from the array buf to the stream starting
466      * at offset bytes into the buffer.
467      *
468      * @param buf The buffer
469      * @param offset Offset into the buffer to start writing from
470      * @param len The number of bytes to write
471      *
472      * @exception IOException If an error occurs.
473      */
474     public native void write(byte[] buf, int offset, int len) throws IOException;
475   }
476 }