1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.  Oracle designates this
9  * particular file as subject to the "Classpath" exception as provided
10  * by Oracle in the LICENSE file that accompanied this code.
11  *
12  * This code is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  * version 2 for more details (a copy is included in the LICENSE file that
16  * accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License version
19  * 2 along with this work; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23  * or visit www.oracle.com if you need additional information or have any
24  * questions.
25  */
26 
27 package java.net;
28 
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.io.OutputStream;
32 import java.io.FileDescriptor;
33 import java.util.Set;
34 
35 /**
36  * The abstract class {@code SocketImpl} is a common superclass
37  * of all classes that actually implement sockets. It is used to
38  * create both client and server sockets.
39  * <p>
40  * A "plain" socket implements these methods exactly as
41  * described, without attempting to go through a firewall or proxy.
42  *
43  * @author  unascribed
44  * @since   1.0
45  */
46 public abstract class SocketImpl implements SocketOptions {
47     /**
48      * The actual Socket object.
49      */
50     Socket socket = null;
51     ServerSocket serverSocket = null;
52 
53     /**
54      * The file descriptor object for this socket.
55      */
56     protected FileDescriptor fd;
57 
58     /**
59      * The IP address of the remote end of this socket.
60      */
61     protected InetAddress address;
62 
63     /**
64      * The port number on the remote host to which this socket is connected.
65      */
66     protected int port;
67 
68     /**
69      * The local port number to which this socket is connected.
70      */
71     protected int localport;
72 
73     /**
74      * Creates either a stream or a datagram socket.
75      *
76      * @param      stream   if {@code true}, create a stream socket;
77      *                      otherwise, create a datagram socket.
78      * @exception  IOException  if an I/O error occurs while creating the
79      *               socket.
80      */
create(boolean stream)81     protected abstract void create(boolean stream) throws IOException;
82 
83     /**
84      * Connects this socket to the specified port on the named host.
85      *
86      * @param      host   the name of the remote host.
87      * @param      port   the port number.
88      * @exception  IOException  if an I/O error occurs when connecting to the
89      *               remote host.
90      */
connect(String host, int port)91     protected abstract void connect(String host, int port) throws IOException;
92 
93     /**
94      * Connects this socket to the specified port number on the specified host.
95      *
96      * @param      address   the IP address of the remote host.
97      * @param      port      the port number.
98      * @exception  IOException  if an I/O error occurs when attempting a
99      *               connection.
100      */
connect(InetAddress address, int port)101     protected abstract void connect(InetAddress address, int port) throws IOException;
102 
103     /**
104      * Connects this socket to the specified port number on the specified host.
105      * A timeout of zero is interpreted as an infinite timeout. The connection
106      * will then block until established or an error occurs.
107      *
108      * @param      address   the Socket address of the remote host.
109      * @param     timeout  the timeout value, in milliseconds, or zero for no timeout.
110      * @exception  IOException  if an I/O error occurs when attempting a
111      *               connection.
112      * @since 1.4
113      */
connect(SocketAddress address, int timeout)114     protected abstract void connect(SocketAddress address, int timeout) throws IOException;
115 
116     /**
117      * Binds this socket to the specified local IP address and port number.
118      *
119      * @param      host   an IP address that belongs to a local interface.
120      * @param      port   the port number.
121      * @exception  IOException  if an I/O error occurs when binding this socket.
122      */
bind(InetAddress host, int port)123     protected abstract void bind(InetAddress host, int port) throws IOException;
124 
125     /**
126      * Sets the maximum queue length for incoming connection indications
127      * (a request to connect) to the {@code count} argument. If a
128      * connection indication arrives when the queue is full, the
129      * connection is refused.
130      *
131      * @param      backlog   the maximum length of the queue.
132      * @exception  IOException  if an I/O error occurs when creating the queue.
133      */
listen(int backlog)134     protected abstract void listen(int backlog) throws IOException;
135 
136     /**
137      * Accepts a connection.
138      *
139      * @param      s   the accepted connection.
140      * @exception  IOException  if an I/O error occurs when accepting the
141      *               connection.
142      */
accept(SocketImpl s)143     protected abstract void accept(SocketImpl s) throws IOException;
144 
145     /**
146      * Returns an input stream for this socket.
147      *
148      * @return     a stream for reading from this socket.
149      * @exception  IOException  if an I/O error occurs when creating the
150      *               input stream.
151     */
getInputStream()152     protected abstract InputStream getInputStream() throws IOException;
153 
154     /**
155      * Returns an output stream for this socket.
156      *
157      * @return     an output stream for writing to this socket.
158      * @exception  IOException  if an I/O error occurs when creating the
159      *               output stream.
160      */
getOutputStream()161     protected abstract OutputStream getOutputStream() throws IOException;
162 
163     /**
164      * Returns the number of bytes that can be read from this socket
165      * without blocking.
166      *
167      * @return     the number of bytes that can be read from this socket
168      *             without blocking.
169      * @exception  IOException  if an I/O error occurs when determining the
170      *               number of bytes available.
171      */
available()172     protected abstract int available() throws IOException;
173 
174     /**
175      * Closes this socket.
176      *
177      * @exception  IOException  if an I/O error occurs when closing this socket.
178      */
close()179     protected abstract void close() throws IOException;
180 
181     /**
182      * Places the input stream for this socket at "end of stream".
183      * Any data sent to this socket is acknowledged and then
184      * silently discarded.
185      *
186      * If you read from a socket input stream after invoking this method on the
187      * socket, the stream's {@code available} method will return 0, and its
188      * {@code read} methods will return {@code -1} (end of stream).
189      *
190      * @exception IOException if an I/O error occurs when shutting down this
191      * socket.
192      * @see java.net.Socket#shutdownOutput()
193      * @see java.net.Socket#close()
194      * @see java.net.Socket#setSoLinger(boolean, int)
195      * @since 1.3
196      */
shutdownInput()197     protected void shutdownInput() throws IOException {
198       throw new IOException("Method not implemented!");
199     }
200 
201     /**
202      * Disables the output stream for this socket.
203      * For a TCP socket, any previously written data will be sent
204      * followed by TCP's normal connection termination sequence.
205      *
206      * If you write to a socket output stream after invoking
207      * shutdownOutput() on the socket, the stream will throw
208      * an IOException.
209      *
210      * @exception IOException if an I/O error occurs when shutting down this
211      * socket.
212      * @see java.net.Socket#shutdownInput()
213      * @see java.net.Socket#close()
214      * @see java.net.Socket#setSoLinger(boolean, int)
215      * @since 1.3
216      */
shutdownOutput()217     protected void shutdownOutput() throws IOException {
218       throw new IOException("Method not implemented!");
219     }
220 
221     /**
222      * Returns the value of this socket's {@code fd} field.
223      *
224      * @return  the value of this socket's {@code fd} field.
225      * @see     java.net.SocketImpl#fd
226      */
getFileDescriptor()227     protected FileDescriptor getFileDescriptor() {
228         return fd;
229     }
230 
231     // Android-added: getFD$() for testing.
232     /**
233      * Gets socket's underlying {@link FileDescriptor}.
234      *
235      * @hide used by java.nio tests
236      *
237      * @return socket's underlying {@link FileDescriptor}.
238      */
getFD$()239     public FileDescriptor getFD$() {
240         return fd;
241     }
242 
243     /**
244      * Returns the value of this socket's {@code address} field.
245      *
246      * @return  the value of this socket's {@code address} field.
247      * @see     java.net.SocketImpl#address
248      */
getInetAddress()249     protected InetAddress getInetAddress() {
250         return address;
251     }
252 
253     /**
254      * Returns the value of this socket's {@code port} field.
255      *
256      * @return  the value of this socket's {@code port} field.
257      * @see     java.net.SocketImpl#port
258      */
getPort()259     protected int getPort() {
260         return port;
261     }
262 
263     /**
264      * Returns whether or not this SocketImpl supports sending
265      * urgent data. By default, false is returned
266      * unless the method is overridden in a sub-class
267      *
268      * @return  true if urgent data supported
269      * @see     java.net.SocketImpl#address
270      * @since 1.4
271      */
supportsUrgentData()272     protected boolean supportsUrgentData () {
273         return false; // must be overridden in sub-class
274     }
275 
276     /**
277      * Send one byte of urgent data on the socket.
278      * The byte to be sent is the low eight bits of the parameter
279      * @param data The byte of data to send
280      * @exception IOException if there is an error
281      *  sending the data.
282      * @since 1.4
283      */
sendUrgentData(int data)284     protected abstract void sendUrgentData (int data) throws IOException;
285 
286     /**
287      * Returns the value of this socket's {@code localport} field.
288      *
289      * @return  the value of this socket's {@code localport} field.
290      * @see     java.net.SocketImpl#localport
291      */
getLocalPort()292     protected int getLocalPort() {
293         return localport;
294     }
295 
setSocket(Socket soc)296     void setSocket(Socket soc) {
297         this.socket = soc;
298     }
299 
getSocket()300     Socket getSocket() {
301         return socket;
302     }
303 
setServerSocket(ServerSocket soc)304     void setServerSocket(ServerSocket soc) {
305         this.serverSocket = soc;
306     }
307 
getServerSocket()308     ServerSocket getServerSocket() {
309         return serverSocket;
310     }
311 
312     /**
313      * Returns the address and port of this socket as a {@code String}.
314      *
315      * @return  a string representation of this socket.
316      */
toString()317     public String toString() {
318         return "Socket[addr=" + getInetAddress() +
319             ",port=" + getPort() + ",localport=" + getLocalPort()  + "]";
320     }
321 
reset()322     void reset() throws IOException {
323         address = null;
324         port = 0;
325         localport = 0;
326     }
327 
328     /**
329      * Sets performance preferences for this socket.
330      *
331      * <p> Sockets use the TCP/IP protocol by default.  Some implementations
332      * may offer alternative protocols which have different performance
333      * characteristics than TCP/IP.  This method allows the application to
334      * express its own preferences as to how these tradeoffs should be made
335      * when the implementation chooses from the available protocols.
336      *
337      * <p> Performance preferences are described by three integers
338      * whose values indicate the relative importance of short connection time,
339      * low latency, and high bandwidth.  The absolute values of the integers
340      * are irrelevant; in order to choose a protocol the values are simply
341      * compared, with larger values indicating stronger preferences. Negative
342      * values represent a lower priority than positive values. If the
343      * application prefers short connection time over both low latency and high
344      * bandwidth, for example, then it could invoke this method with the values
345      * {@code (1, 0, 0)}.  If the application prefers high bandwidth above low
346      * latency, and low latency above short connection time, then it could
347      * invoke this method with the values {@code (0, 1, 2)}.
348      *
349      * By default, this method does nothing, unless it is overridden in
350      * a sub-class.
351      *
352      * @param  connectionTime
353      *         An {@code int} expressing the relative importance of a short
354      *         connection time
355      *
356      * @param  latency
357      *         An {@code int} expressing the relative importance of low
358      *         latency
359      *
360      * @param  bandwidth
361      *         An {@code int} expressing the relative importance of high
362      *         bandwidth
363      *
364      * @since 1.5
365      */
setPerformancePreferences(int connectionTime, int latency, int bandwidth)366     protected void setPerformancePreferences(int connectionTime,
367                                           int latency,
368                                           int bandwidth)
369     {
370         /* Not implemented yet */
371     }
372 
373     /**
374      * Called to set a socket option.
375      *
376      * @param <T> The type of the socket option value
377      * @param name The socket option
378      *
379      * @param value The value of the socket option. A value of {@code null}
380      *              may be valid for some options.
381      *
382      * @throws UnsupportedOperationException if the SocketImpl does not
383      *         support the option
384      *
385      * @throws IOException if an I/O error occurs, or if the socket is closed.
386      *
387      * @since 9
388      */
setOption(SocketOption<T> name, T value)389     protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
390         if (name == StandardSocketOptions.SO_KEEPALIVE &&
391                 (getSocket() != null)) {
392             setOption(SocketOptions.SO_KEEPALIVE, value);
393         } else if (name == StandardSocketOptions.SO_SNDBUF &&
394                 (getSocket() != null)) {
395             setOption(SocketOptions.SO_SNDBUF, value);
396         } else if (name == StandardSocketOptions.SO_RCVBUF) {
397             setOption(SocketOptions.SO_RCVBUF, value);
398         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
399             setOption(SocketOptions.SO_REUSEADDR, value);
400         } else if (name == StandardSocketOptions.SO_REUSEPORT &&
401             supportedOptions().contains(name)) {
402             setOption(SocketOptions.SO_REUSEPORT, value);
403         } else if (name == StandardSocketOptions.SO_LINGER &&
404                 (getSocket() != null)) {
405             setOption(SocketOptions.SO_LINGER, value);
406         } else if (name == StandardSocketOptions.IP_TOS) {
407             setOption(SocketOptions.IP_TOS, value);
408         } else if (name == StandardSocketOptions.TCP_NODELAY &&
409                 (getSocket() != null)) {
410             setOption(SocketOptions.TCP_NODELAY, value);
411         } else {
412             throw new UnsupportedOperationException("unsupported option");
413         }
414     }
415 
416     /**
417      * Called to get a socket option.
418      *
419      * @param <T> The type of the socket option value
420      * @param name The socket option
421      *
422      * @return the value of the named option
423      *
424      * @throws UnsupportedOperationException if the SocketImpl does not
425      *         support the option.
426      *
427      * @throws IOException if an I/O error occurs, or if the socket is closed.
428      *
429      * @since 9
430      */
431     @SuppressWarnings("unchecked")
getOption(SocketOption<T> name)432     protected <T> T getOption(SocketOption<T> name) throws IOException {
433         if (name == StandardSocketOptions.SO_KEEPALIVE &&
434                 (getSocket() != null)) {
435             return (T)getOption(SocketOptions.SO_KEEPALIVE);
436         } else if (name == StandardSocketOptions.SO_SNDBUF &&
437                 (getSocket() != null)) {
438             return (T)getOption(SocketOptions.SO_SNDBUF);
439         } else if (name == StandardSocketOptions.SO_RCVBUF) {
440             return (T)getOption(SocketOptions.SO_RCVBUF);
441         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
442             return (T)getOption(SocketOptions.SO_REUSEADDR);
443         } else if (name == StandardSocketOptions.SO_REUSEPORT &&
444             supportedOptions().contains(name)) {
445             return (T)getOption(SocketOptions.SO_REUSEPORT);
446         } else if (name == StandardSocketOptions.SO_LINGER &&
447                 (getSocket() != null)) {
448             return (T)getOption(SocketOptions.SO_LINGER);
449         } else if (name == StandardSocketOptions.IP_TOS) {
450             return (T)getOption(SocketOptions.IP_TOS);
451         } else if (name == StandardSocketOptions.TCP_NODELAY &&
452                 (getSocket() != null)) {
453             return (T)getOption(SocketOptions.TCP_NODELAY);
454         } else {
455             throw new UnsupportedOperationException("unsupported option");
456         }
457     }
458 
459     private static final Set<SocketOption<?>> socketOptions;
460 
461     private static final Set<SocketOption<?>> serverSocketOptions;
462 
463     static {
464         socketOptions = Set.of(StandardSocketOptions.SO_KEEPALIVE,
465                                StandardSocketOptions.SO_SNDBUF,
466                                StandardSocketOptions.SO_RCVBUF,
467                                StandardSocketOptions.SO_REUSEADDR,
468                                StandardSocketOptions.SO_LINGER,
469                                StandardSocketOptions.IP_TOS,
470                                StandardSocketOptions.TCP_NODELAY);
471 
472         serverSocketOptions = Set.of(StandardSocketOptions.SO_RCVBUF,
473                                      StandardSocketOptions.SO_REUSEADDR,
474                                      StandardSocketOptions.IP_TOS);
475     }
476 
477     /**
478      * Returns a set of SocketOptions supported by this impl
479      * and by this impl's socket (Socket or ServerSocket)
480      *
481      * @return a Set of SocketOptions
482      *
483      * @since 9
484      */
supportedOptions()485     protected Set<SocketOption<?>> supportedOptions() {
486         if (getSocket() != null) {
487             return socketOptions;
488         } else {
489             return serverSocketOptions;
490         }
491     }
492 }
493