SocketImpl.java revision 2cd82d7111f68ff63145ef7c393bf1479ff06223
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package java.net;
19
20import java.io.FileDescriptor;
21import java.io.IOException;
22import java.io.InputStream;
23import java.io.OutputStream;
24import org.apache.harmony.luni.platform.INetworkSystem;
25import org.apache.harmony.luni.platform.Platform;
26
27/**
28 * This class is the base of all streaming socket implementation classes.
29 * Streaming sockets are wrapped by two classes, {@code ServerSocket} and
30 * {@code Socket} at the server and client end of a connection. At the server,
31 * there are two types of sockets engaged in communication, the {@code
32 * ServerSocket} on a well known port (referred to as listener) used to
33 * establish a connection and the resulting {@code Socket} (referred to as
34 * host).
35 */
36public abstract class SocketImpl implements SocketOptions {
37
38    /**
39     * The remote address this socket is connected to.
40     */
41    protected InetAddress address;
42
43    /**
44     * The remote port this socket is connected to.
45     */
46    protected int port;
47
48    /**
49     * The file descriptor of this socket.
50     */
51    protected FileDescriptor fd;
52
53    /**
54     * The local port this socket is connected to.
55     */
56    protected int localport;
57
58    INetworkSystem netImpl = Platform.getNetworkSystem();
59
60    boolean streaming = true;
61
62    /**
63     * Waits for an incoming request and blocks until the connection is opened
64     * on the given socket.
65     *
66     * @param newSocket
67     *            the socket to accept connections on.
68     * @throws IOException
69     *             if an error occurs while accepting a new connection.
70     */
71    protected abstract void accept(SocketImpl newSocket) throws IOException;
72
73    /**
74     * Returns the available number of bytes which are readable from this socket
75     * without blocking.
76     *
77     * @return the number of bytes that may be read without blocking.
78     * @throws IOException
79     *             if an error occurs while reading the number of bytes.
80     */
81    protected abstract int available() throws IOException;
82
83    /**
84     * Binds this socket to the specified local host address and port number.
85     *
86     * @param address
87     *            the local machine address to bind this socket to.
88     * @param port
89     *            the port on the local machine to bind this socket to.
90     * @throws IOException
91     *             if an error occurs while binding this socket.
92     */
93    protected abstract void bind(InetAddress address, int port)
94            throws IOException;
95
96    /**
97     * Closes this socket. This makes later access invalid.
98     *
99     * @throws IOException
100     *             if an error occurs while closing this socket.
101     */
102    protected abstract void close() throws IOException;
103
104    /**
105     * Connects this socket to the specified remote host and port number.
106     *
107     * @param host
108     *            the remote host this socket has to be connected to.
109     * @param port
110     *            the remote port on which this socket has to be connected.
111     * @throws IOException
112     *             if an error occurs while connecting to the remote host.
113     */
114    protected abstract void connect(String host, int port) throws IOException;
115
116    /**
117     * Connects this socket to the specified remote host address and port
118     * number.
119     *
120     * @param address
121     *            the remote host address this socket has to be connected to.
122     * @param port
123     *            the remote port on which this socket has to be connected.
124     * @throws IOException
125     *             if an error occurs while connecting to the remote host.
126     */
127    protected abstract void connect(InetAddress address, int port)
128            throws IOException;
129
130    /**
131     * Creates a new unconnected socket. The argument {@code isStreaming}
132     * defines whether the new socket is a streaming or a datagram socket.
133     *
134     * @param isStreaming
135     *            defines whether the type of the new socket is streaming or
136     *            datagram.
137     * @throws IOException
138     *             if an error occurs while creating the socket.
139     */
140    protected abstract void create(boolean isStreaming) throws IOException;
141
142    /**
143     * Gets the file descriptor of this socket.
144     *
145     * @return the file descriptor of this socket.
146     */
147    protected FileDescriptor getFileDescriptor() {
148        return fd;
149    }
150
151    /**
152     * Gets the remote address this socket is connected to.
153     *
154     * @return the remote address of this socket.
155     */
156    protected InetAddress getInetAddress() {
157        return address;
158    }
159
160    /**
161     * Gets the input stream of this socket.
162     *
163     * @return the input stream of this socket.
164     * @throws IOException
165     *             if an error occurs while accessing the input stream.
166     */
167    protected abstract InputStream getInputStream() throws IOException;
168
169    /**
170     * Gets the local port number of this socket. The field is initialized to
171     * {@code -1} and upon demand will go to the IP stack to get the bound
172     * value. See the class comment for the context of the local port.
173     *
174     * @return the local port number this socket is bound to.
175     */
176    protected int getLocalPort() {
177        return localport;
178    }
179
180    /**
181     * Gets the value of the given socket option.
182     *
183     * @param optID
184     *            the socket option to retrieve.
185     * @return the option value.
186     * @throws SocketException
187     *             if an error occurs while accessing the option.
188     */
189    public abstract Object getOption(int optID) throws SocketException;
190
191    /**
192     * Gets the output stream of this socket.
193     *
194     * @return the output stream of this socket.
195     * @throws IOException
196     *             if an error occurs while accessing the output stream.
197     */
198    protected abstract OutputStream getOutputStream() throws IOException;
199
200    /**
201     * Gets the remote port number of this socket. This value is not meaningful
202     * when this instance is wrapped by a {@code ServerSocket}.
203     *
204     * @return the remote port this socket is connected to.
205     */
206    protected int getPort() {
207        return port;
208    }
209
210    /**
211     * Listens for connection requests on this streaming socket. Incoming
212     * connection requests are queued up to the limit specified by {@code
213     * backlog}. Additional requests are rejected. The method {@code listen()}
214     * may only be invoked on streaming sockets.
215     *
216     * @param backlog
217     *            the maximum number of outstanding connection requests.
218     * @throws IOException
219     *             if an error occurs while listening.
220     */
221    protected abstract void listen(int backlog) throws IOException;
222
223    /**
224     * Sets the value for the specified socket option.
225     *
226     * @param optID
227     *            the socket option to be set.
228     * @param val
229     *            the option value.
230     * @throws SocketException
231     *             if an error occurs while setting the option.
232     */
233    public abstract void setOption(int optID, Object val)
234            throws SocketException;
235
236    /**
237     * Returns a string containing a concise, human-readable description of the
238     * socket.
239     *
240     * @return the textual representation of this socket.
241     */
242    @SuppressWarnings("nls")
243    @Override
244    public String toString() {
245        return new StringBuilder(100).append("Socket[addr=").append(
246                getInetAddress()).append(",port=").append(port).append(
247                ",localport=").append(getLocalPort()).append("]").toString();
248    }
249
250    /**
251     * In the IP stack, write at most {@code count} bytes on the socket
252     * from the {@code buffer}, from the {@code offset}.
253     *
254     * @param buffer
255     *            the buffer to read into
256     * @param offset
257     *            the offset into the buffer
258     * @param count
259     *            the number of bytes to write
260     * @return int the actual number of bytes written
261     * @throws IOException
262     *                thrown if an error occurs while writing
263     */
264    int write(byte[] buffer, int offset, int count) throws IOException {
265        if (streaming) {
266            return this.netImpl.write(fd, buffer, offset, count);
267        } else {
268            return this.netImpl.send(fd, buffer, offset, count, port, address);
269        }
270    }
271
272    /**
273     * Closes the input channel of this socket.
274     * <p>
275     * This default implementation always throws an {@link IOException} to
276     * indicate that the subclass should have overridden this method.
277     *
278     * @throws IOException
279     *             always because this method should be overridden.
280     */
281    protected void shutdownInput() throws IOException {
282        throw new IOException("Method has not been implemented");
283    }
284
285    /**
286     * Closes the output channel of this socket.
287     * <p>
288     * This default implementation always throws an {@link IOException} to
289     * indicate that the subclass should have overridden this method.
290     *
291     * @throws IOException
292     *             always because this method should be overridden.
293     */
294    protected void shutdownOutput() throws IOException {
295        throw new IOException("Method has not been implemented");
296    }
297
298    /**
299     * Connects this socket to the remote host address and port number specified
300     * by the {@code SocketAddress} object with the given timeout. This method
301     * will block indefinitely if the timeout is set to zero.
302     *
303     * @param remoteAddr
304     *            the remote host address and port number to connect to.
305     * @param timeout
306     *            the timeout value in milliseconds.
307     * @throws IOException
308     *             if an error occurs while connecting.
309     */
310    protected abstract void connect(SocketAddress remoteAddr, int timeout)
311            throws IOException;
312
313    /**
314     * Returns whether the socket supports urgent data or not. Subclasses should
315     * override this method.
316     *
317     * @return {@code false} because subclasses must override this method.
318     */
319    protected boolean supportsUrgentData() {
320        return false;
321    }
322
323    /**
324     * Sends the single byte of urgent data on the socket.
325     *
326     * @param value
327     *            the byte of urgent data.
328     * @throws IOException
329     *             if an error occurs sending urgent data.
330     */
331    protected abstract void sendUrgentData(int value) throws IOException;
332
333    /**
334     * Sets performance preference for connection time, latency and bandwidth.
335     * Does nothing by default.
336     *
337     * @param connectionTime
338     *            the importance of connect time.
339     * @param latency
340     *            the importance of latency.
341     * @param bandwidth
342     *            the importance of bandwidth.
343     */
344    protected void setPerformancePreferences(int connectionTime, int latency,
345            int bandwidth) {
346        // Our socket implementation only provide one protocol: TCP/IP, so
347        // we do nothing for this method
348    }
349}
350