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