Path: blob/master/src/java.base/share/classes/sun/security/ssl/BaseSSLSocketImpl.java
41159 views
/*1* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.ssl;2627import java.io.*;28import java.net.*;29import java.nio.channels.SocketChannel;30import java.util.Set;31import javax.net.ssl.*;3233/**34* Abstract base class for SSLSocketImpl.35*36* Its purpose is to house code with no SSL related logic (or no logic at all).37* This makes SSLSocketImpl shorter and easier to read. It contains a few38* constants and static methods plus overridden java.net.Socket methods.39*40* Methods are defined final to ensure that they are not accidentally41* overridden in SSLSocketImpl.42*43* @see javax.net.ssl.SSLSocket44* @see SSLSocketImpl45*/46abstract class BaseSSLSocketImpl extends SSLSocket {4748/*49* Normally "self" is "this" ... but not when this connection is50* layered over a preexisting socket. If we're using an existing51* socket, we delegate some actions to it. Else, we delegate52* instead to "super". This is important to ensure that we don't53* recurse infinitely ... e.g. close() calling itself, or doing54* I/O in terms of our own streams.55*/56private final Socket self;57private final InputStream consumedInput;5859BaseSSLSocketImpl() {60super();61this.self = this;62this.consumedInput = null;63}6465BaseSSLSocketImpl(Socket socket) {66super();67this.self = socket;68this.consumedInput = null;69}7071BaseSSLSocketImpl(Socket socket, InputStream consumed) {72super();73this.self = socket;74this.consumedInput = consumed;75}7677//78// CONSTANTS AND STATIC METHODS79//8081/**82* TLS requires that a close_notify warning alert is sent before the83* connection is closed in order to avoid truncation attacks. Some84* implementations (MS IIS and others) don't do that. The property85* below controls whether we accept that or treat it as an error.86*87* The default is "false", i.e. tolerate the broken behavior.88*/89private static final String PROP_NAME =90"com.sun.net.ssl.requireCloseNotify";9192static final boolean requireCloseNotify =93Utilities.getBooleanProperty(PROP_NAME, false);9495//96// MISC SOCKET METHODS97//9899/**100* Returns the unique {@link java.nio.channels.SocketChannel SocketChannel}101* object associated with this socket, if any.102*103* @see java.net.Socket#getChannel104*/105@Override106public final SocketChannel getChannel() {107if (self == this) {108return super.getChannel();109} else {110return self.getChannel();111}112}113114/**115* Binds the address to the socket.116* @see java.net.Socket#bind117*/118@Override119public void bind(SocketAddress bindpoint) throws IOException {120/*121* Bind to this socket122*/123if (self == this) {124super.bind(bindpoint);125} else {126// If we're binding on a layered socket...127throw new IOException(128"Underlying socket should already be connected");129}130}131132/**133* Returns the address of the endpoint this socket is connected to134* @see java.net.Socket#getLocalSocketAddress135*/136@Override137public SocketAddress getLocalSocketAddress() {138if (self == this) {139return super.getLocalSocketAddress();140} else {141return self.getLocalSocketAddress();142}143}144145/**146* Returns the address of the endpoint this socket is connected to147* @see java.net.Socket#getRemoteSocketAddress148*/149@Override150public SocketAddress getRemoteSocketAddress() {151if (self == this) {152return super.getRemoteSocketAddress();153} else {154return self.getRemoteSocketAddress();155}156}157158/**159* Connects this socket to the server.160*161* This method is either called on an unconnected SSLSocketImpl by the162* application, or it is called in the constructor of a regular163* SSLSocketImpl. If we are layering on top on another socket, then164* this method should not be called, because we assume that the165* underlying socket is already connected by the time it is passed to166* us.167*168* @param endpoint the <code>SocketAddress</code>169* @throws IOException if an error occurs during the connection170*/171@Override172public final void connect(SocketAddress endpoint) throws IOException {173connect(endpoint, 0);174}175176/**177* Returns the connection state of the socket.178* @see java.net.Socket#isConnected179*/180@Override181public final boolean isConnected() {182if (self == this) {183return super.isConnected();184} else {185return self.isConnected();186}187}188189/**190* Returns the binding state of the socket.191* @see java.net.Socket#isBound192*/193@Override194public final boolean isBound() {195if (self == this) {196return super.isBound();197} else {198return self.isBound();199}200}201202//203// CLOSE RELATED METHODS204//205206/**207* Places the input stream for this socket at "end of stream". Any data208* sent to the input stream side of the socket is acknowledged and then209* silently discarded.210*211* @see java.net.Socket#shutdownInput212*/213@Override214public void shutdownInput() throws IOException {215if (self == this) {216super.shutdownInput();217} else {218self.shutdownInput();219}220}221222/**223* Disables the output stream for this socket. For a TCP socket, any224* previously written data will be sent followed by TCP's normal225* connection termination sequence.226*227* @see java.net.Socket#shutdownOutput228*/229@Override230public void shutdownOutput() throws IOException {231if (self == this) {232super.shutdownOutput();233} else {234self.shutdownOutput();235}236}237238/**239* Returns the input state of the socket240* @see java.net.Socket#isInputShutdown241*/242@Override243public boolean isInputShutdown() {244if (self == this) {245return super.isInputShutdown();246} else {247return self.isInputShutdown();248}249}250251/**252* Returns the output state of the socket253* @see java.net.Socket#isOutputShutdown254*/255@Override256public boolean isOutputShutdown() {257if (self == this) {258return super.isOutputShutdown();259} else {260return self.isOutputShutdown();261}262}263264/**265* Ensures that the SSL connection is closed down as cleanly266* as possible, in case the application forgets to do so.267* This allows SSL connections to be implicitly reclaimed,268* rather than forcing them to be explicitly reclaimed at269* the penalty of prematurly killing SSL sessions.270*/271@Override272@SuppressWarnings("deprecation")273protected final void finalize() throws Throwable {274try {275close();276} catch (IOException e1) {277try {278if (self == this) {279super.close();280}281} catch (IOException e2) {282// ignore283}284} finally {285// We called close on the underlying socket above to286// make doubly sure all resources got released. We287// don't finalize self in the case of overlain sockets,288// that's a different object which the GC will finalize289// separately.290291super.finalize();292}293}294295//296// GET ADDRESS METHODS297//298299/**300* Returns the address of the remote peer for this connection.301*/302@Override303public final InetAddress getInetAddress() {304if (self == this) {305return super.getInetAddress();306} else {307return self.getInetAddress();308}309}310311/**312* Gets the local address to which the socket is bound.313*314* @return the local address to which the socket is bound.315* @since 1.1316*/317@Override318public final InetAddress getLocalAddress() {319if (self == this) {320return super.getLocalAddress();321} else {322return self.getLocalAddress();323}324}325326/**327* Returns the number of the remote port that this connection uses.328*/329@Override330public final int getPort() {331if (self == this) {332return super.getPort();333} else {334return self.getPort();335}336}337338/**339* Returns the number of the local port that this connection uses.340*/341@Override342public final int getLocalPort() {343if (self == this) {344return super.getLocalPort();345} else {346return self.getLocalPort();347}348}349350//351// SOCKET OPTION METHODS352//353354/**355* Enables or disables the Nagle optimization.356* @see java.net.Socket#setTcpNoDelay357*/358@Override359public final void setTcpNoDelay(boolean value) throws SocketException {360if (self == this) {361super.setTcpNoDelay(value);362} else {363self.setTcpNoDelay(value);364}365}366367/**368* Returns true if the Nagle optimization is disabled. This369* relates to low-level buffering of TCP traffic, delaying the370* traffic to promote better throughput.371*372* @see java.net.Socket#getTcpNoDelay373*/374@Override375public final boolean getTcpNoDelay() throws SocketException {376if (self == this) {377return super.getTcpNoDelay();378} else {379return self.getTcpNoDelay();380}381}382383/**384* Assigns the socket's linger timeout.385* @see java.net.Socket#setSoLinger386*/387@Override388public final void setSoLinger(boolean flag, int linger)389throws SocketException {390if (self == this) {391super.setSoLinger(flag, linger);392} else {393self.setSoLinger(flag, linger);394}395}396397/**398* Returns the socket's linger timeout.399* @see java.net.Socket#getSoLinger400*/401@Override402public final int getSoLinger() throws SocketException {403if (self == this) {404return super.getSoLinger();405} else {406return self.getSoLinger();407}408}409410/**411* Send one byte of urgent data on the socket.412* @see java.net.Socket#sendUrgentData413* At this point, there seems to be no specific requirement to support414* this for an SSLSocket. An implementation can be provided if a need415* arises in future.416*/417@Override418public final void sendUrgentData(int data) throws SocketException {419throw new SocketException("This method is not supported "420+ "by SSLSockets");421}422423/**424* Enable/disable OOBINLINE (receipt of TCP urgent data) By default, this425* option is disabled and TCP urgent data received on a socket is silently426* discarded.427* @see java.net.Socket#setOOBInline428* Setting OOBInline does not have any effect on SSLSocket,429* since currently we don't support sending urgent data.430*/431@Override432public final void setOOBInline(boolean on) throws SocketException {433throw new SocketException("This method is ineffective, since"434+ " sending urgent data is not supported by SSLSockets");435}436437/**438* Tests if OOBINLINE is enabled.439* @see java.net.Socket#getOOBInline440*/441@Override442public final boolean getOOBInline() throws SocketException {443throw new SocketException("This method is ineffective, since"444+ " sending urgent data is not supported by SSLSockets");445}446447/**448* Returns the socket timeout.449* @see java.net.Socket#getSoTimeout450*/451@Override452public final int getSoTimeout() throws SocketException {453if (self == this) {454return super.getSoTimeout();455} else {456return self.getSoTimeout();457}458}459460@Override461public final void setSendBufferSize(int size) throws SocketException {462if (self == this) {463super.setSendBufferSize(size);464} else {465self.setSendBufferSize(size);466}467}468469@Override470public final int getSendBufferSize() throws SocketException {471if (self == this) {472return super.getSendBufferSize();473} else {474return self.getSendBufferSize();475}476}477478@Override479public final void setReceiveBufferSize(int size) throws SocketException {480if (self == this) {481super.setReceiveBufferSize(size);482} else {483self.setReceiveBufferSize(size);484}485}486487@Override488public final int getReceiveBufferSize() throws SocketException {489if (self == this) {490return super.getReceiveBufferSize();491} else {492return self.getReceiveBufferSize();493}494}495496/**497* Enable/disable SO_KEEPALIVE.498* @see java.net.Socket#setKeepAlive499*/500@Override501public final void setKeepAlive(boolean on) throws SocketException {502if (self == this) {503super.setKeepAlive(on);504} else {505self.setKeepAlive(on);506}507}508509/**510* Tests if SO_KEEPALIVE is enabled.511* @see java.net.Socket#getKeepAlive512*/513@Override514public final boolean getKeepAlive() throws SocketException {515if (self == this) {516return super.getKeepAlive();517} else {518return self.getKeepAlive();519}520}521522/**523* Sets traffic class or type-of-service octet in the IP header for524* packets sent from this Socket.525* @see java.net.Socket#setTrafficClass526*/527@Override528public final void setTrafficClass(int tc) throws SocketException {529if (self == this) {530super.setTrafficClass(tc);531} else {532self.setTrafficClass(tc);533}534}535536/**537* Gets traffic class or type-of-service in the IP header for packets538* sent from this Socket.539* @see java.net.Socket#getTrafficClass540*/541@Override542public final int getTrafficClass() throws SocketException {543if (self == this) {544return super.getTrafficClass();545} else {546return self.getTrafficClass();547}548}549550/**551* Enable/disable SO_REUSEADDR.552* @see java.net.Socket#setReuseAddress553*/554@Override555public final void setReuseAddress(boolean on) throws SocketException {556if (self == this) {557super.setReuseAddress(on);558} else {559self.setReuseAddress(on);560}561}562563/**564* Tests if SO_REUSEADDR is enabled.565* @see java.net.Socket#getReuseAddress566*/567@Override568public final boolean getReuseAddress() throws SocketException {569if (self == this) {570return super.getReuseAddress();571} else {572return self.getReuseAddress();573}574}575576/**577* Sets performance preferences for this socket.578*579* @see java.net.Socket#setPerformancePreferences(int, int, int)580*/581@Override582public void setPerformancePreferences(int connectionTime,583int latency, int bandwidth) {584if (self == this) {585super.setPerformancePreferences(586connectionTime, latency, bandwidth);587} else {588self.setPerformancePreferences(589connectionTime, latency, bandwidth);590}591}592593@Override594public String toString() {595if (self == this) {596return super.toString();597}598599return self.toString();600}601602@Override603public InputStream getInputStream() throws IOException {604if (self == this) {605return super.getInputStream();606}607608if (consumedInput != null) {609return new SequenceInputStream(consumedInput,610self.getInputStream());611}612613return self.getInputStream();614}615616@Override617public OutputStream getOutputStream() throws IOException {618if (self == this) {619return super.getOutputStream();620}621622return self.getOutputStream();623}624625@Override626public void close() throws IOException {627if (self == this) {628super.close();629} else {630self.close();631}632}633634@Override635public void setSoTimeout(int timeout) throws SocketException {636if (self == this) {637super.setSoTimeout(timeout);638} else {639self.setSoTimeout(timeout);640}641}642643@Override644public <T> Socket setOption(SocketOption<T> name,645T value) throws IOException {646if (self == this) {647return super.setOption(name, value);648} else {649return self.setOption(name, value);650}651}652653@Override654public <T> T getOption(SocketOption<T> name) throws IOException {655if (self == this) {656return super.getOption(name);657} else {658return self.getOption(name);659}660}661662@Override663public Set<SocketOption<?>> supportedOptions() {664if (self == this) {665return super.supportedOptions();666} else {667return self.supportedOptions();668}669}670671boolean isLayered() {672return (self != this);673}674}675676677