SocketImpl.java revision 221d0ccb4cc23ee0bf0646e9abe471fb48b3a1a8
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    // BEGIN android-removed
61    // int receiveTimeout;
62    // END android-removed
63
64    boolean streaming = true;
65
66    /**
67     * Waits for an incoming request and blocks until the connection is opened
68     * on the given socket.
69     *
70     * @param newSocket
71     *            the socket to accept connections on.
72     * @throws IOException
73     *             if an error occurs while accepting a new connection.
74     */
75    protected abstract void accept(SocketImpl newSocket) throws IOException;
76
77    /**
78     * Returns the available number of bytes which are readable from this socket
79     * without blocking.
80     *
81     * @return the number of bytes that may be read without blocking.
82     * @throws IOException
83     *             if an error occurs while reading the number of bytes.
84     */
85    protected abstract int available() throws IOException;
86
87    /**
88     * Binds this socket to the specified local host address and port number.
89     *
90     * @param address
91     *            the local machine address to bind this socket to.
92     * @param port
93     *            the port on the local machine to bind this socket to.
94     * @throws IOException
95     *             if an error occurs while binding this socket.
96     */
97    protected abstract void bind(InetAddress address, int port)
98            throws IOException;
99
100    /**
101     * Closes this socket. This makes later access invalid.
102     *
103     * @throws IOException
104     *             if an error occurs while closing this socket.
105     */
106    protected abstract void close() throws IOException;
107
108    /**
109     * Connects this socket to the specified remote host and port number.
110     *
111     * @param host
112     *            the remote host this socket has to be connected to.
113     * @param port
114     *            the remote port on which this socket has to be connected.
115     * @throws IOException
116     *             if an error occurs while connecting to the remote host.
117     */
118    protected abstract void connect(String host, int port) throws IOException;
119
120    /**
121     * Connects this socket to the specified remote host address and port
122     * number.
123     *
124     * @param address
125     *            the remote host address this socket has to be connected to.
126     * @param port
127     *            the remote port on which this socket has to be connected.
128     * @throws IOException
129     *             if an error occurs while connecting to the remote host.
130     */
131    protected abstract void connect(InetAddress address, int port)
132            throws IOException;
133
134    /**
135     * Creates a new unconnected socket. The argument {@code isStreaming}
136     * defines whether the new socket is a streaming or a datagram socket.
137     *
138     * @param isStreaming
139     *            defines whether the type of the new socket is streaming or
140     *            datagram.
141     * @throws IOException
142     *             if an error occurs while creating the socket.
143     */
144    protected abstract void create(boolean isStreaming) throws IOException;
145
146    /**
147     * Gets the file descriptor of this socket.
148     *
149     * @return the file descriptor of this socket.
150     */
151    protected FileDescriptor getFileDescriptor() {
152        return fd;
153    }
154
155    /**
156     * Gets the remote address this socket is connected to.
157     *
158     * @return the remote address of this socket.
159     */
160    protected InetAddress getInetAddress() {
161        return address;
162    }
163
164    /**
165     * Gets the input stream of this socket.
166     *
167     * @return the input stream of this socket.
168     * @throws IOException
169     *             if an error occurs while accessing the input stream.
170     */
171    protected abstract InputStream getInputStream() throws IOException;
172
173    /**
174     * Gets the local port number of this socket. The field is initialized to
175     * {@code -1} and upon demand will go to the IP stack to get the bound
176     * value. See the class comment for the context of the local port.
177     *
178     * @return the local port number this socket is bound to.
179     */
180    protected int getLocalPort() {
181        return localport;
182    }
183
184    /**
185     * Gets the value of the given socket option.
186     *
187     * @param optID
188     *            the socket option to retrieve.
189     * @return the option value.
190     * @throws SocketException
191     *             if an error occurs while accessing the option.
192     */
193    public abstract Object getOption(int optID) throws SocketException;
194
195    /**
196     * Gets the output stream of this socket.
197     *
198     * @return the output stream of this socket.
199     * @throws IOException
200     *             if an error occurs while accessing the output stream.
201     */
202    protected abstract OutputStream getOutputStream() throws IOException;
203
204    /**
205     * Gets the remote port number of this socket. This value is not meaningful
206     * when this instance is wrapped by a {@code ServerSocket}.
207     *
208     * @return the remote port this socket is connected to.
209     */
210    protected int getPort() {
211        return port;
212    }
213
214    /**
215     * Listens for connection requests on this streaming socket. Incoming
216     * connection requests are queued up to the limit specified by {@code
217     * backlog}. Additional requests are rejected. The method {@code listen()}
218     * may only be invoked on streaming sockets.
219     *
220     * @param backlog
221     *            the maximum number of outstanding connection requests.
222     * @throws IOException
223     *             if an error occurs while listening.
224     */
225    protected abstract void listen(int backlog) throws IOException;
226
227    /**
228     * Sets the value for the specified socket option.
229     *
230     * @param optID
231     *            the socket option to be set.
232     * @param val
233     *            the option value.
234     * @throws SocketException
235     *             if an error occurs while setting the option.
236     */
237    public abstract void setOption(int optID, Object val)
238            throws SocketException;
239
240    /**
241     * Returns a string containing a concise, human-readable description of the
242     * socket.
243     *
244     * @return the textual representation of this socket.
245     */
246    @SuppressWarnings("nls")
247    @Override
248    public String toString() {
249        return new StringBuilder(100).append("Socket[addr=").append(
250                getInetAddress()).append(",port=").append(port).append(
251                ",localport=").append(getLocalPort()).append("]").toString();
252    }
253
254    /**
255     * In the IP stack, write at most {@code count} bytes on the socket
256     * from the {@code buffer}, from the {@code offset}.
257     *
258     * @param buffer
259     *            the buffer to read into
260     * @param offset
261     *            the offset into the buffer
262     * @param count
263     *            the number of bytes to write
264     * @return int the actual number of bytes written
265     * @throws IOException
266     *                thrown if an error occurs while writing
267     */
268    int write(byte[] buffer, int offset, int count) throws IOException {
269        if (streaming) {
270            return this.netImpl.write(fd, buffer, offset, count);
271        } else {
272            return this.netImpl.send(fd, buffer, offset, count, port, 0, address);
273        }
274    }
275
276    /**
277     * Closes the input channel of this socket.
278     * <p>
279     * This default implementation always throws an {@link IOException} to
280     * indicate that the subclass should have overridden this method.
281     *
282     * @throws IOException
283     *             always because this method should be overridden.
284     */
285    protected void shutdownInput() throws IOException {
286        throw new IOException("Method has not been implemented");
287    }
288
289    /**
290     * Closes the output channel of this socket.
291     * <p>
292     * This default implementation always throws an {@link IOException} to
293     * indicate that the subclass should have overridden this method.
294     *
295     * @throws IOException
296     *             always because this method should be overridden.
297     */
298    protected void shutdownOutput() throws IOException {
299        throw new IOException("Method has not been implemented");
300    }
301
302    /**
303     * Connects this socket to the remote host address and port number specified
304     * by the {@code SocketAddress} object with the given timeout. This method
305     * will block indefinitely if the timeout is set to zero.
306     *
307     * @param remoteAddr
308     *            the remote host address and port number to connect to.
309     * @param timeout
310     *            the timeout value in milliseconds.
311     * @throws IOException
312     *             if an error occurs while connecting.
313     */
314    protected abstract void connect(SocketAddress remoteAddr, int timeout)
315            throws IOException;
316
317    /**
318     * Returns whether the socket supports urgent data or not. Subclasses should
319     * override this method.
320     *
321     * @return {@code false} because subclasses must override this method.
322     */
323    protected boolean supportsUrgentData() {
324        return false;
325    }
326
327    /**
328     * Sends the single byte of urgent data on the socket.
329     *
330     * @param value
331     *            the byte of urgent data.
332     * @throws IOException
333     *             if an error occurs sending urgent data.
334     */
335    protected abstract void sendUrgentData(int value) throws IOException;
336
337    /**
338     * Sets performance preference for connection time, latency and bandwidth.
339     * Does nothing by default.
340     *
341     * @param connectionTime
342     *            the importance of connect time.
343     * @param latency
344     *            the importance of latency.
345     * @param bandwidth
346     *            the importance of bandwidth.
347     */
348    protected void setPerformancePreferences(int connectionTime, int latency,
349            int bandwidth) {
350        // Our socket implementation only provide one protocol: TCP/IP, so
351        // we do nothing for this method
352    }
353}
354