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