1/*
2 * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26
27package sun.security.ssl;
28
29import java.io.*;
30import java.nio.channels.SocketChannel;
31import java.net.*;
32
33import javax.net.ssl.*;
34
35/**
36 * Abstract base class for SSLSocketImpl. Its purpose is to house code with
37 * no SSL related logic (or no logic at all). This makes SSLSocketImpl shorter
38 * and easier to read. It contains a few constants and static methods plus
39 * overridden java.net.Socket methods.
40 *
41 * Methods are defined final to ensure that they are not accidentally
42 * overridden in SSLSocketImpl.
43 *
44 * @see javax.net.ssl.SSLSocket
45 * @see SSLSocketImpl
46 *
47 */
48abstract class BaseSSLSocketImpl extends SSLSocket {
49
50    /*
51     * Normally "self" is "this" ... but not when this connection is
52     * layered over a preexisting socket.  If we're using an existing
53     * socket, we delegate some actions to it.  Else, we delegate
54     * instead to "super".  This is important to ensure that we don't
55     * recurse infinitely ... e.g. close() calling itself, or doing
56     * I/O in terms of our own streams.
57     */
58    final Socket self;
59
60    BaseSSLSocketImpl() {
61        super();
62        this.self = this;
63    }
64
65    BaseSSLSocketImpl(Socket socket) {
66        super();
67        this.self = socket;
68    }
69
70    //
71    // CONSTANTS AND STATIC METHODS
72    //
73
74    /**
75     * TLS requires that a close_notify warning alert is sent before the
76     * connection is closed in order to avoid truncation attacks. Some
77     * implementations (MS IIS and others) don't do that. The property
78     * below controls whether we accept that or treat it as an error.
79     *
80     * The default is "false", i.e. tolerate the broken behavior.
81     */
82    private final static String PROP_NAME =
83                                "com.sun.net.ssl.requireCloseNotify";
84
85    final static boolean requireCloseNotify =
86                                Debug.getBooleanProperty(PROP_NAME, false);
87
88    //
89    // MISC SOCKET METHODS
90    //
91
92    /**
93     * Returns the unique {@link java.nio.SocketChannel SocketChannel} object
94     * associated with this socket, if any.
95     * @see java.net.Socket#getChannel
96     */
97    public final SocketChannel getChannel() {
98        if (self == this) {
99            return super.getChannel();
100        } else {
101            return self.getChannel();
102        }
103    }
104
105    /**
106     * Binds the address to the socket.
107     * @see java.net.Socket#bind
108     */
109    public void bind(SocketAddress bindpoint) throws IOException {
110        /*
111         * Bind to this socket
112         */
113        if (self == this) {
114            super.bind(bindpoint);
115        } else {
116            // If we're binding on a layered socket...
117            throw new IOException(
118                "Underlying socket should already be connected");
119        }
120    }
121
122    /**
123     * Returns the address of the endpoint this socket is connected to
124     * @see java.net.Socket#getLocalSocketAddress
125     */
126    public SocketAddress getLocalSocketAddress() {
127        if (self == this) {
128            return super.getLocalSocketAddress();
129        } else {
130            return self.getLocalSocketAddress();
131        }
132    }
133
134    /**
135     * Returns the address of the endpoint this socket is connected to
136     * @see java.net.Socket#getRemoteSocketAddress
137     */
138    public SocketAddress getRemoteSocketAddress() {
139        if (self == this) {
140            return super.getRemoteSocketAddress();
141        } else {
142            return self.getRemoteSocketAddress();
143        }
144    }
145
146    /**
147     * Connects this socket to the server.
148     *
149     * This method is either called on an unconnected SSLSocketImpl by the
150     * application, or it is called in the constructor of a regular
151     * SSLSocketImpl. If we are layering on top on another socket, then
152     * this method should not be called, because we assume that the
153     * underlying socket is already connected by the time it is passed to
154     * us.
155     *
156     * @param   endpoint the <code>SocketAddress</code>
157     * @throws  IOException if an error occurs during the connection
158     */
159    public final void connect(SocketAddress endpoint) throws IOException {
160        connect(endpoint, 0);
161    }
162
163    /**
164     * Returns the connection state of the socket.
165     * @see java.net.Socket#isConnected
166     */
167    public final boolean isConnected() {
168        if (self == this) {
169            return super.isConnected();
170        } else {
171            return self.isConnected();
172        }
173    }
174
175    /**
176     * Returns the binding state of the socket.
177     * @see java.net.Socket#isBound
178     */
179    public final boolean isBound() {
180        if (self == this) {
181            return super.isBound();
182        } else {
183            return self.isBound();
184        }
185    }
186
187    //
188    // CLOSE RELATED METHODS
189    //
190
191    /**
192     * The semantics of shutdownInput is not supported in TLS 1.0
193     * spec. Thus when the method is called on an SSL socket, an
194     * UnsupportedOperationException will be thrown.
195     *
196     * @throws UnsupportedOperationException
197     */
198    public final void shutdownInput() throws IOException {
199        throw new UnsupportedOperationException("The method shutdownInput()" +
200                   " is not supported in SSLSocket");
201    }
202
203    /**
204     * The semantics of shutdownOutput is not supported in TLS 1.0
205     * spec. Thus when the method is called on an SSL socket, an
206     * UnsupportedOperationException will be thrown.
207     *
208     * @throws UnsupportedOperationException
209     */
210    public final void shutdownOutput() throws IOException {
211        throw new UnsupportedOperationException("The method shutdownOutput()" +
212                   " is not supported in SSLSocket");
213
214    }
215
216    /**
217     * Returns the input state of the socket
218     * @see java.net.Socket#isInputShutdown
219     */
220    public final boolean isInputShutdown() {
221        if (self == this) {
222            return super.isInputShutdown();
223        } else {
224            return self.isInputShutdown();
225        }
226    }
227
228    /**
229     * Returns the output state of the socket
230     * @see java.net.Socket#isOutputShutdown
231     */
232    public final boolean isOutputShutdown() {
233        if (self == this) {
234            return super.isOutputShutdown();
235        } else {
236            return self.isOutputShutdown();
237        }
238    }
239
240    /**
241     * Ensures that the SSL connection is closed down as cleanly
242     * as possible, in case the application forgets to do so.
243     * This allows SSL connections to be implicitly reclaimed,
244     * rather than forcing them to be explicitly reclaimed at
245     * the penalty of prematurly killing SSL sessions.
246     */
247    protected final void finalize() throws Throwable {
248        try {
249            close();
250        } catch (IOException e1) {
251            try {
252                if (self == this) {
253                    super.close();
254                }
255            } catch (IOException e2) {
256                // ignore
257            }
258        } finally {
259            // We called close on the underlying socket above to
260            // make doubly sure all resources got released.  We
261            // don't finalize self in the case of overlain sockets,
262            // that's a different object which the GC will finalize
263            // separately.
264
265            super.finalize();
266        }
267    }
268
269    //
270    // GET ADDRESS METHODS
271    //
272
273    /**
274     * Returns the address of the remote peer for this connection.
275     */
276    public final InetAddress getInetAddress() {
277        if (self == this) {
278            return super.getInetAddress();
279        } else {
280            return self.getInetAddress();
281        }
282    }
283
284    /**
285     * Gets the local address to which the socket is bound.
286     *
287     * @return the local address to which the socket is bound.
288     * @since   JDK1.1
289     */
290    public final InetAddress getLocalAddress() {
291        if (self == this) {
292            return super.getLocalAddress();
293        } else {
294            return self.getLocalAddress();
295        }
296    }
297
298    /**
299     * Returns the number of the remote port that this connection uses.
300     */
301    public final int getPort() {
302        if (self == this) {
303            return super.getPort();
304        } else {
305            return self.getPort();
306        }
307    }
308
309    /**
310     * Returns the number of the local port that this connection uses.
311     */
312    public final int getLocalPort() {
313        if (self == this) {
314            return super.getLocalPort();
315        } else {
316            return self.getLocalPort();
317        }
318    }
319
320    //
321    // SOCKET OPTION METHODS
322    //
323
324    /**
325     * Enables or disables the Nagle optimization.
326     * @see java.net.Socket#setTcpNoDelay
327     */
328    public final void setTcpNoDelay(boolean value) throws SocketException {
329        if (self == this) {
330            super.setTcpNoDelay(value);
331        } else {
332            self.setTcpNoDelay(value);
333        }
334    }
335
336    /**
337     * Returns true if the Nagle optimization is disabled.  This
338     * relates to low-level buffering of TCP traffic, delaying the
339     * traffic to promote better throughput.
340     *
341     * @see java.net.Socket#getTcpNoDelay
342     */
343    public final boolean getTcpNoDelay() throws SocketException {
344        if (self == this) {
345            return super.getTcpNoDelay();
346        } else {
347            return self.getTcpNoDelay();
348        }
349    }
350
351    /**
352     * Assigns the socket's linger timeout.
353     * @see java.net.Socket#setSoLinger
354     */
355    public final void setSoLinger(boolean flag, int linger)
356            throws SocketException {
357        if (self == this) {
358            super.setSoLinger(flag, linger);
359        } else {
360            self.setSoLinger(flag, linger);
361        }
362    }
363
364    /**
365     * Returns the socket's linger timeout.
366     * @see java.net.Socket#getSoLinger
367     */
368    public final int getSoLinger() throws SocketException {
369        if (self == this) {
370            return super.getSoLinger();
371        } else {
372            return self.getSoLinger();
373        }
374    }
375
376    /**
377     * Send one byte of urgent data on the socket.
378     * @see java.net.Socket#sendUrgentData
379     * At this point, there seems to be no specific requirement to support
380     * this for an SSLSocket. An implementation can be provided if a need
381     * arises in future.
382     */
383    public final void sendUrgentData(int data) throws SocketException {
384        throw new SocketException("This method is not supported "
385                        + "by SSLSockets");
386    }
387
388    /**
389     * Enable/disable OOBINLINE (receipt of TCP urgent data) By default, this
390     * option is disabled and TCP urgent data received on a socket is silently
391     * discarded.
392     * @see java.net.Socket#setOOBInline
393     * Setting OOBInline does not have any effect on SSLSocket,
394     * since currently we don't support sending urgent data.
395     */
396    public final void setOOBInline(boolean on) throws SocketException {
397        throw new SocketException("This method is ineffective, since"
398                + " sending urgent data is not supported by SSLSockets");
399    }
400
401    /**
402     * Tests if OOBINLINE is enabled.
403     * @see java.net.Socket#getOOBInline
404     */
405    public final boolean getOOBInline() throws SocketException {
406        throw new SocketException("This method is ineffective, since"
407                + " sending urgent data is not supported by SSLSockets");
408    }
409
410    /**
411     * Returns the socket timeout.
412     * @see java.net.Socket#getSoTimeout
413     */
414    public final int getSoTimeout() throws SocketException {
415        if (self == this) {
416            return super.getSoTimeout();
417        } else {
418            return self.getSoTimeout();
419        }
420    }
421
422    public final void setSendBufferSize(int size) throws SocketException {
423        if (self == this) {
424            super.setSendBufferSize(size);
425        } else {
426            self.setSendBufferSize(size);
427        }
428    }
429
430    public final int getSendBufferSize() throws SocketException {
431        if (self == this) {
432            return super.getSendBufferSize();
433        } else {
434            return self.getSendBufferSize();
435        }
436    }
437
438    public final void setReceiveBufferSize(int size) throws SocketException {
439        if (self == this) {
440            super.setReceiveBufferSize(size);
441        } else {
442            self.setReceiveBufferSize(size);
443        }
444    }
445
446    public final int getReceiveBufferSize() throws SocketException {
447        if (self == this) {
448            return super.getReceiveBufferSize();
449        } else {
450            return self.getReceiveBufferSize();
451        }
452    }
453
454    /**
455     * Enable/disable SO_KEEPALIVE.
456     * @see java.net.Socket#setKeepAlive
457     */
458    public final void setKeepAlive(boolean on) throws SocketException {
459        if (self == this) {
460            super.setKeepAlive(on);
461        } else {
462            self.setKeepAlive(on);
463        }
464    }
465
466    /**
467     * Tests if SO_KEEPALIVE is enabled.
468     * @see java.net.Socket#getKeepAlive
469     */
470    public final boolean getKeepAlive() throws SocketException {
471        if (self == this) {
472            return super.getKeepAlive();
473        } else {
474            return self.getKeepAlive();
475        }
476    }
477
478    /**
479     * Sets traffic class or type-of-service octet in the IP header for
480     * packets sent from this Socket.
481     * @see java.net.Socket#setTrafficClass
482     */
483    public final void setTrafficClass(int tc) throws SocketException {
484        if (self == this) {
485            super.setTrafficClass(tc);
486        } else {
487            self.setTrafficClass(tc);
488        }
489    }
490
491    /**
492     * Gets traffic class or type-of-service in the IP header for packets
493     * sent from this Socket.
494     * @see java.net.Socket#getTrafficClass
495     */
496    public final int getTrafficClass() throws SocketException {
497        if (self == this) {
498            return super.getTrafficClass();
499        } else {
500            return self.getTrafficClass();
501        }
502    }
503
504    /**
505     * Enable/disable SO_REUSEADDR.
506     * @see java.net.Socket#setReuseAddress
507     */
508    public final void setReuseAddress(boolean on) throws SocketException {
509        if (self == this) {
510            super.setReuseAddress(on);
511        } else {
512            self.setReuseAddress(on);
513        }
514    }
515
516    /**
517     * Tests if SO_REUSEADDR is enabled.
518     * @see java.net.Socket#getReuseAddress
519     */
520    public final boolean getReuseAddress() throws SocketException {
521        if (self == this) {
522            return super.getReuseAddress();
523        } else {
524            return self.getReuseAddress();
525        }
526    }
527
528    /**
529     * Sets performance preferences for this socket.
530     *
531     * @see java.net.Socket#setPerformancePreferences(int, int, int)
532     */
533    public void setPerformancePreferences(int connectionTime,
534            int latency, int bandwidth) {
535        if (self == this) {
536            super.setPerformancePreferences(
537                connectionTime, latency, bandwidth);
538        } else {
539            self.setPerformancePreferences(
540                connectionTime, latency, bandwidth);
541        }
542    }
543
544}
545