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