1 /*
   2  * Copyright (c) 1996, 2020, 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 package sun.security.ssl;
  27 
  28 import java.io.EOFException;
  29 import java.io.IOException;
  30 import java.io.InputStream;
  31 import java.io.InterruptedIOException;
  32 import java.io.OutputStream;
  33 import java.net.InetAddress;
  34 import java.net.InetSocketAddress;
  35 import java.net.Socket;
  36 import java.net.SocketAddress;
  37 import java.net.SocketException;
  38 import java.net.UnknownHostException;
  39 import java.nio.ByteBuffer;
  40 import java.util.List;
  41 import java.util.function.BiFunction;
  42 import javax.net.ssl.HandshakeCompletedListener;
  43 import javax.net.ssl.SSLException;
  44 import javax.net.ssl.SSLHandshakeException;
  45 import javax.net.ssl.SSLParameters;
  46 import javax.net.ssl.SSLProtocolException;
  47 import javax.net.ssl.SSLServerSocket;
  48 import javax.net.ssl.SSLSession;
  49 import javax.net.ssl.SSLSocket;
  50 import sun.misc.SharedSecrets;
  51 
  52 /**
  53  * Implementation of an SSL socket.
  54  * <P>
  55  * This is a normal connection type socket, implementing SSL over some lower
  56  * level socket, such as TCP.  Because it is layered over some lower level
  57  * socket, it MUST override all default socket methods.
  58  * <P>
  59  * This API offers a non-traditional option for establishing SSL
  60  * connections.  You may first establish the connection directly, then pass
  61  * that connection to the SSL socket constructor with a flag saying which
  62  * role should be taken in the handshake protocol.  (The two ends of the
  63  * connection must not choose the same role!)  This allows setup of SSL
  64  * proxying or tunneling, and also allows the kind of "role reversal"
  65  * that is required for most FTP data transfers.
  66  *
  67  * @see javax.net.ssl.SSLSocket
  68  * @see SSLServerSocket
  69  *
  70  * @author David Brownell
  71  */
  72 public final class SSLSocketImpl
  73         extends BaseSSLSocketImpl implements SSLTransport {
  74 
  75     final SSLContextImpl            sslContext;
  76     final TransportContext          conContext;
  77 
  78     private final AppInputStream    appInput = new AppInputStream();
  79     private final AppOutputStream   appOutput = new AppOutputStream();
  80 
  81     private String                  peerHost;
  82     private boolean                 autoClose;
  83     private boolean                 isConnected = false;
  84     private volatile boolean        tlsIsClosed = false;
  85 
  86     /*
  87      * Is the local name service trustworthy?
  88      *
  89      * If the local name service is not trustworthy, reverse host name
  90      * resolution should not be performed for endpoint identification.
  91      */
  92     private static final boolean trustNameService =
  93             Utilities.getBooleanProperty("jdk.tls.trustNameService", false);
  94 
  95     /**
  96      * Package-private constructor used to instantiate an unconnected
  97      * socket.
  98      *
  99      * This instance is meant to set handshake state to use "client mode".
 100      */
 101     SSLSocketImpl(SSLContextImpl sslContext) {
 102         super();
 103         this.sslContext = sslContext;
 104         HandshakeHash handshakeHash = new HandshakeHash();
 105         this.conContext = new TransportContext(sslContext, this,
 106                 new SSLSocketInputRecord(handshakeHash),
 107                 new SSLSocketOutputRecord(handshakeHash), true);
 108     }
 109 
 110     /**
 111      * Package-private constructor used to instantiate a server socket.
 112      *
 113      * This instance is meant to set handshake state to use "server mode".
 114      */
 115     SSLSocketImpl(SSLContextImpl sslContext, SSLConfiguration sslConfig) {
 116         super();
 117         this.sslContext = sslContext;
 118         HandshakeHash handshakeHash = new HandshakeHash();
 119         this.conContext = new TransportContext(sslContext, this, sslConfig,
 120                 new SSLSocketInputRecord(handshakeHash),
 121                 new SSLSocketOutputRecord(handshakeHash));
 122     }
 123 
 124     /**
 125      * Constructs an SSL connection to a named host at a specified
 126      * port, using the authentication context provided.
 127      *
 128      * This endpoint acts as the client, and may rejoin an existing SSL session
 129      * if appropriate.
 130      */
 131     SSLSocketImpl(SSLContextImpl sslContext, String peerHost,
 132             int peerPort) throws IOException, UnknownHostException {
 133         super();
 134         this.sslContext = sslContext;
 135         HandshakeHash handshakeHash = new HandshakeHash();
 136         this.conContext = new TransportContext(sslContext, this,
 137                 new SSLSocketInputRecord(handshakeHash),
 138                 new SSLSocketOutputRecord(handshakeHash), true);
 139         this.peerHost = peerHost;
 140         SocketAddress socketAddress =
 141                peerHost != null ? new InetSocketAddress(peerHost, peerPort) :
 142                new InetSocketAddress(InetAddress.getByName(null), peerPort);
 143         connect(socketAddress, 0);
 144     }
 145 
 146     /**
 147      * Constructs an SSL connection to a server at a specified
 148      * address, and TCP port, using the authentication context
 149      * provided.
 150      *
 151      * This endpoint acts as the client, and may rejoin an existing SSL
 152      * session if appropriate.
 153      */
 154     SSLSocketImpl(SSLContextImpl sslContext,
 155             InetAddress address, int peerPort) throws IOException {
 156         super();
 157         this.sslContext = sslContext;
 158         HandshakeHash handshakeHash = new HandshakeHash();
 159         this.conContext = new TransportContext(sslContext, this,
 160                 new SSLSocketInputRecord(handshakeHash),
 161                 new SSLSocketOutputRecord(handshakeHash), true);
 162 
 163         SocketAddress socketAddress = new InetSocketAddress(address, peerPort);
 164         connect(socketAddress, 0);
 165     }
 166 
 167     /**
 168      * Constructs an SSL connection to a named host at a specified
 169      * port, using the authentication context provided.
 170      *
 171      * This endpoint acts as the client, and may rejoin an existing SSL
 172      * session if appropriate.
 173      */
 174     SSLSocketImpl(SSLContextImpl sslContext,
 175             String peerHost, int peerPort, InetAddress localAddr,
 176             int localPort) throws IOException, UnknownHostException {
 177         super();
 178         this.sslContext = sslContext;
 179         HandshakeHash handshakeHash = new HandshakeHash();
 180         this.conContext = new TransportContext(sslContext, this,
 181                 new SSLSocketInputRecord(handshakeHash),
 182                 new SSLSocketOutputRecord(handshakeHash), true);
 183         this.peerHost = peerHost;
 184 
 185         bind(new InetSocketAddress(localAddr, localPort));
 186         SocketAddress socketAddress =
 187                peerHost != null ? new InetSocketAddress(peerHost, peerPort) :
 188                new InetSocketAddress(InetAddress.getByName(null), peerPort);
 189         connect(socketAddress, 0);
 190     }
 191 
 192     /**
 193      * Constructs an SSL connection to a server at a specified
 194      * address, and TCP port, using the authentication context
 195      * provided.
 196      *
 197      * This endpoint acts as the client, and may rejoin an existing SSL
 198      * session if appropriate.
 199      */
 200     SSLSocketImpl(SSLContextImpl sslContext,
 201             InetAddress peerAddr, int peerPort,
 202             InetAddress localAddr, int localPort) throws IOException {
 203         super();
 204         this.sslContext = sslContext;
 205         HandshakeHash handshakeHash = new HandshakeHash();
 206         this.conContext = new TransportContext(sslContext, this,
 207                 new SSLSocketInputRecord(handshakeHash),
 208                 new SSLSocketOutputRecord(handshakeHash), true);
 209 
 210         bind(new InetSocketAddress(localAddr, localPort));
 211         SocketAddress socketAddress = new InetSocketAddress(peerAddr, peerPort);
 212         connect(socketAddress, 0);
 213     }
 214 
 215     /**
 216      * Creates a server mode {@link Socket} layered over an
 217      * existing connected socket, and is able to read data which has
 218      * already been consumed/removed from the {@link Socket}'s
 219      * underlying {@link InputStream}.
 220      */
 221     SSLSocketImpl(SSLContextImpl sslContext, Socket sock,
 222             InputStream consumed, boolean autoClose) throws IOException {
 223         super(sock, consumed);
 224         // We always layer over a connected socket
 225         if (!sock.isConnected()) {
 226             throw new SocketException("Underlying socket is not connected");
 227         }
 228 
 229         this.sslContext = sslContext;
 230         HandshakeHash handshakeHash = new HandshakeHash();
 231         this.conContext = new TransportContext(sslContext, this,
 232                 new SSLSocketInputRecord(handshakeHash),
 233                 new SSLSocketOutputRecord(handshakeHash), false);
 234         this.autoClose = autoClose;
 235         doneConnect();
 236     }
 237 
 238     /**
 239      * Layer SSL traffic over an existing connection, rather than
 240      * creating a new connection.
 241      *
 242      * The existing connection may be used only for SSL traffic (using this
 243      * SSLSocket) until the SSLSocket.close() call returns. However, if a
 244      * protocol error is detected, that existing connection is automatically
 245      * closed.
 246      * <p>
 247      * This particular constructor always uses the socket in the
 248      * role of an SSL client. It may be useful in cases which start
 249      * using SSL after some initial data transfers, for example in some
 250      * SSL tunneling applications or as part of some kinds of application
 251      * protocols which negotiate use of a SSL based security.
 252      */
 253     SSLSocketImpl(SSLContextImpl sslContext, Socket sock,
 254             String peerHost, int port, boolean autoClose) throws IOException {
 255         super(sock);
 256         // We always layer over a connected socket
 257         if (!sock.isConnected()) {
 258             throw new SocketException("Underlying socket is not connected");
 259         }
 260 
 261         this.sslContext = sslContext;
 262         HandshakeHash handshakeHash = new HandshakeHash();
 263         this.conContext = new TransportContext(sslContext, this,
 264                 new SSLSocketInputRecord(handshakeHash),
 265                 new SSLSocketOutputRecord(handshakeHash), true);
 266         this.peerHost = peerHost;
 267         this.autoClose = autoClose;
 268         doneConnect();
 269     }
 270 
 271     @Override
 272     public void connect(SocketAddress endpoint,
 273             int timeout) throws IOException {
 274 
 275         if (isLayered()) {
 276             throw new SocketException("Already connected");
 277         }
 278 
 279         if (!(endpoint instanceof InetSocketAddress)) {
 280             throw new SocketException(
 281                     "Cannot handle non-Inet socket addresses.");
 282         }
 283 
 284         super.connect(endpoint, timeout);
 285         doneConnect();
 286     }
 287 
 288     @Override
 289     public String[] getSupportedCipherSuites() {
 290         return CipherSuite.namesOf(sslContext.getSupportedCipherSuites());
 291     }
 292 
 293     @Override
 294     public synchronized String[] getEnabledCipherSuites() {
 295         return CipherSuite.namesOf(conContext.sslConfig.enabledCipherSuites);
 296     }
 297 
 298     @Override
 299     public synchronized void setEnabledCipherSuites(String[] suites) {
 300         conContext.sslConfig.enabledCipherSuites =
 301                 CipherSuite.validValuesOf(suites);
 302     }
 303 
 304     @Override
 305     public String[] getSupportedProtocols() {
 306         return ProtocolVersion.toStringArray(
 307                 sslContext.getSupportedProtocolVersions());
 308     }
 309 
 310     @Override
 311     public synchronized String[] getEnabledProtocols() {
 312         return ProtocolVersion.toStringArray(
 313                 conContext.sslConfig.enabledProtocols);
 314     }
 315 
 316     @Override
 317     public synchronized void setEnabledProtocols(String[] protocols) {
 318         if (protocols == null) {
 319             throw new IllegalArgumentException("Protocols cannot be null");
 320         }
 321 
 322         conContext.sslConfig.enabledProtocols =
 323                 ProtocolVersion.namesOf(protocols);
 324     }
 325 
 326     @Override
 327     public SSLSession getSession() {
 328         try {
 329             // start handshaking, if failed, the connection will be closed.
 330             ensureNegotiated();
 331         } catch (IOException ioe) {
 332             if (SSLLogger.isOn && SSLLogger.isOn("handshake")) {
 333                 SSLLogger.severe("handshake failed", ioe);
 334             }
 335 
 336             return new SSLSessionImpl();
 337         }
 338 
 339         return conContext.conSession;
 340     }
 341 
 342     @Override
 343     public synchronized SSLSession getHandshakeSession() {
 344         return conContext.handshakeContext == null ?
 345                 null : conContext.handshakeContext.handshakeSession;
 346     }
 347 
 348     @Override
 349     public synchronized void addHandshakeCompletedListener(
 350             HandshakeCompletedListener listener) {
 351         if (listener == null) {
 352             throw new IllegalArgumentException("listener is null");
 353         }
 354 
 355         conContext.sslConfig.addHandshakeCompletedListener(listener);
 356     }
 357 
 358     @Override
 359     public synchronized void removeHandshakeCompletedListener(
 360             HandshakeCompletedListener listener) {
 361         if (listener == null) {
 362             throw new IllegalArgumentException("listener is null");
 363         }
 364 
 365         conContext.sslConfig.removeHandshakeCompletedListener(listener);
 366     }
 367 
 368     @Override
 369     public void startHandshake() throws IOException {
 370         if (!isConnected) {
 371             throw new SocketException("Socket is not connected");
 372         }
 373 
 374         if (conContext.isBroken || conContext.isInboundClosed() ||
 375                 conContext.isOutboundClosed()) {
 376             throw new SocketException("Socket has been closed or broken");
 377         }
 378 
 379         synchronized (conContext) {     // handshake lock
 380             // double check the context status
 381             if (conContext.isBroken || conContext.isInboundClosed() ||
 382                     conContext.isOutboundClosed()) {
 383                 throw new SocketException("Socket has been closed or broken");
 384             }
 385 
 386             try {
 387                 conContext.kickstart();
 388 
 389                 // All initial handshaking goes through this operation until we
 390                 // have a valid SSL connection.
 391                 //
 392                 // Handle handshake messages only, need no application data.
 393                 if (!conContext.isNegotiated) {
 394                     readHandshakeRecord();
 395                 }
 396             } catch (IOException ioe) {
 397                 throw conContext.fatal(Alert.HANDSHAKE_FAILURE,
 398                     "Couldn't kickstart handshaking", ioe);
 399             } catch (Exception oe) {    // including RuntimeException
 400                 handleException(oe);
 401             }
 402         }
 403     }
 404 
 405     @Override
 406     public synchronized void setUseClientMode(boolean mode) {
 407         conContext.setUseClientMode(mode);
 408     }
 409 
 410     @Override
 411     public synchronized boolean getUseClientMode() {
 412         return conContext.sslConfig.isClientMode;
 413     }
 414 
 415     @Override
 416     public synchronized void setNeedClientAuth(boolean need) {
 417         conContext.sslConfig.clientAuthType =
 418                 (need ? ClientAuthType.CLIENT_AUTH_REQUIRED :
 419                         ClientAuthType.CLIENT_AUTH_NONE);
 420     }
 421 
 422     @Override
 423     public synchronized boolean getNeedClientAuth() {
 424         return (conContext.sslConfig.clientAuthType ==
 425                         ClientAuthType.CLIENT_AUTH_REQUIRED);
 426     }
 427 
 428     @Override
 429     public synchronized void setWantClientAuth(boolean want) {
 430         conContext.sslConfig.clientAuthType =
 431                 (want ? ClientAuthType.CLIENT_AUTH_REQUESTED :
 432                         ClientAuthType.CLIENT_AUTH_NONE);
 433     }
 434 
 435     @Override
 436     public synchronized boolean getWantClientAuth() {
 437         return (conContext.sslConfig.clientAuthType ==
 438                         ClientAuthType.CLIENT_AUTH_REQUESTED);
 439     }
 440 
 441     @Override
 442     public synchronized void setEnableSessionCreation(boolean flag) {
 443         conContext.sslConfig.enableSessionCreation = flag;
 444     }
 445 
 446     @Override
 447     public synchronized boolean getEnableSessionCreation() {
 448         return conContext.sslConfig.enableSessionCreation;
 449     }
 450 
 451     @Override
 452     public boolean isClosed() {
 453         return tlsIsClosed;
 454     }
 455 
 456     // Please don't synchronized this method.  Otherwise, the read and close
 457     // locks may be deadlocked.
 458     @Override
 459     public void close() throws IOException {
 460         if (isClosed()) {
 461             return;
 462         }
 463 
 464         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 465             SSLLogger.fine("duplex close of SSLSocket");
 466         }
 467 
 468         try {
 469             if (isConnected()) {
 470                 // shutdown output bound, which may have been closed previously.
 471                 if (!isOutputShutdown()) {
 472                     duplexCloseOutput();
 473                 }
 474 
 475                 // shutdown input bound, which may have been closed previously.
 476                 if (!isInputShutdown()) {
 477                     duplexCloseInput();
 478                 }
 479             }
 480         } catch (IOException ioe) {
 481             // ignore the exception
 482             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 483                 SSLLogger.warning("SSLSocket duplex close failed", ioe);
 484             }
 485         } finally {
 486             if (!isClosed()) {
 487                 // close the connection directly
 488                 try {
 489                     closeSocket(false);
 490                 } catch (IOException ioe) {
 491                     // ignore the exception
 492                     if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 493                         SSLLogger.warning("SSLSocket close failed", ioe);
 494                     }
 495                 } finally {
 496                     tlsIsClosed = true;
 497                 }
 498             }
 499         }
 500     }
 501 
 502     /**
 503      * Duplex close, start from closing outbound.
 504      *
 505      * For TLS 1.2 [RFC 5246], unless some other fatal alert has been
 506      * transmitted, each party is required to send a close_notify alert
 507      * before closing the write side of the connection.  The other party
 508      * MUST respond with a close_notify alert of its own and close down
 509      * the connection immediately, discarding any pending writes.  It is
 510      * not required for the initiator of the close to wait for the responding
 511      * close_notify alert before closing the read side of the connection.
 512      *
 513      * For TLS 1.3, Each party MUST send a close_notify alert before
 514      * closing its write side of the connection, unless it has already sent
 515      * some error alert.  This does not have any effect on its read side of
 516      * the connection.  Both parties need not wait to receive a close_notify
 517      * alert before closing their read side of the connection, though doing
 518      * so would introduce the possibility of truncation.
 519      *
 520      * In order to support user initiated duplex-close for TLS 1.3 connections,
 521      * the user_canceled alert is used together with the close_notify alert.
 522      */
 523     private void duplexCloseOutput() throws IOException {
 524         boolean useUserCanceled = false;
 525         boolean hasCloseReceipt = false;
 526         if (conContext.isNegotiated) {
 527             if (!conContext.protocolVersion.useTLS13PlusSpec()) {
 528                 hasCloseReceipt = true;
 529             } else {
 530                 // Use a user_canceled alert for TLS 1.3 duplex close.
 531                 useUserCanceled = true;
 532             }
 533         } else if (conContext.handshakeContext != null) {   // initial handshake
 534             // Use user_canceled alert regardless the protocol versions.
 535             useUserCanceled = true;
 536 
 537             // The protocol version may have been negotiated.
 538             ProtocolVersion pv = conContext.handshakeContext.negotiatedProtocol;
 539             if (pv == null || (!pv.useTLS13PlusSpec())) {
 540                 hasCloseReceipt = true;
 541             }
 542         }
 543 
 544         // Need a lock here so that the user_canceled alert and the
 545         // close_notify alert can be delivered together.
 546         try {
 547             synchronized (conContext.outputRecord) {
 548                 // send a user_canceled alert if needed.
 549                 if (useUserCanceled) {
 550                     conContext.warning(Alert.USER_CANCELED);
 551                 }
 552 
 553                 // send a close_notify alert
 554                 conContext.warning(Alert.CLOSE_NOTIFY);
 555             }
 556         } finally {
 557             if (!conContext.isOutboundClosed()) {
 558                 conContext.outputRecord.close();
 559             }
 560 
 561             if ((autoClose || !isLayered()) && !super.isOutputShutdown()) {
 562                 super.shutdownOutput();
 563             }
 564         }
 565 
 566         if (!isInputShutdown()) {
 567             bruteForceCloseInput(hasCloseReceipt);
 568         }
 569     }
 570 
 571     /**
 572      * Duplex close, start from closing inbound.
 573      *
 574      * This method should only be called when the outbound has been closed,
 575      * but the inbound is still open.
 576      */
 577     private void duplexCloseInput() throws IOException {
 578         boolean hasCloseReceipt = false;
 579         if (conContext.isNegotiated &&
 580                 !conContext.protocolVersion.useTLS13PlusSpec()) {
 581             hasCloseReceipt = true;
 582         }   // No close receipt if handshake has no completed.
 583 
 584         bruteForceCloseInput(hasCloseReceipt);
 585     }
 586 
 587     /**
 588      * Brute force close the input bound.
 589      *
 590      * This method should only be called when the outbound has been closed,
 591      * but the inbound is still open.
 592      */
 593     private void bruteForceCloseInput(
 594             boolean hasCloseReceipt) throws IOException {
 595         if (hasCloseReceipt) {
 596             // It is not required for the initiator of the close to wait for
 597             // the responding close_notify alert before closing the read side
 598             // of the connection.  However, if the application protocol using
 599             // TLS provides that any data may be carried over the underlying
 600             // transport after the TLS connection is closed, the TLS
 601             // implementation MUST receive a "close_notify" alert before
 602             // indicating end-of-data to the application-layer.
 603             try {
 604                 this.shutdown();
 605             } finally {
 606                 if (!isInputShutdown()) {
 607                     shutdownInput(false);
 608                 }
 609             }
 610         } else {
 611             if (!conContext.isInboundClosed()) {
 612                 conContext.inputRecord.close();
 613             }
 614 
 615             if ((autoClose || !isLayered()) && !super.isInputShutdown()) {
 616                 super.shutdownInput();
 617             }
 618         }
 619     }
 620 
 621     // Please don't synchronized this method.  Otherwise, the read and close
 622     // locks may be deadlocked.
 623     @Override
 624     public void shutdownInput() throws IOException {
 625         shutdownInput(true);
 626     }
 627 
 628     // It is not required to check the close_notify receipt unless an
 629     // application call shutdownInput() explicitly.
 630     private void shutdownInput(
 631             boolean checkCloseNotify) throws IOException {
 632         if (isInputShutdown()) {
 633             return;
 634         }
 635 
 636         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 637             SSLLogger.fine("close inbound of SSLSocket");
 638         }
 639 
 640         // Is it ready to close inbound?
 641         //
 642         // No need to throw exception if the initial handshake is not started.
 643         if (checkCloseNotify && !conContext.isInputCloseNotified &&
 644             (conContext.isNegotiated || conContext.handshakeContext != null)) {
 645 
 646             throw conContext.fatal(Alert.INTERNAL_ERROR,
 647                     "closing inbound before receiving peer's close_notify");
 648         }
 649 
 650         conContext.closeInbound();
 651         if ((autoClose || !isLayered()) && !super.isInputShutdown()) {
 652             super.shutdownInput();
 653         }
 654     }
 655 
 656     @Override
 657     public boolean isInputShutdown() {
 658         return conContext.isInboundClosed() &&
 659                 ((autoClose || !isLayered()) ? super.isInputShutdown(): true);
 660     }
 661 
 662     // Please don't synchronized this method.  Otherwise, the read and close
 663     // locks may be deadlocked.
 664     @Override
 665     public void shutdownOutput() throws IOException {
 666         if (isOutputShutdown()) {
 667             return;
 668         }
 669 
 670         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 671             SSLLogger.fine("close outbound of SSLSocket");
 672         }
 673         conContext.closeOutbound();
 674 
 675         if ((autoClose || !isLayered()) && !super.isOutputShutdown()) {
 676             super.shutdownOutput();
 677         }
 678     }
 679 
 680     @Override
 681     public boolean isOutputShutdown() {
 682         return conContext.isOutboundClosed() &&
 683                 ((autoClose || !isLayered()) ? super.isOutputShutdown(): true);
 684     }
 685 
 686     @Override
 687     public synchronized InputStream getInputStream() throws IOException {
 688         if (isClosed()) {
 689             throw new SocketException("Socket is closed");
 690         }
 691 
 692         if (!isConnected) {
 693             throw new SocketException("Socket is not connected");
 694         }
 695 
 696         if (conContext.isInboundClosed() || isInputShutdown()) {
 697             throw new SocketException("Socket input is already shutdown");
 698         }
 699 
 700         return appInput;
 701     }
 702 
 703     private void ensureNegotiated() throws IOException {
 704         if (conContext.isNegotiated || conContext.isBroken ||
 705                 conContext.isInboundClosed() || conContext.isOutboundClosed()) {
 706             return;
 707         }
 708 
 709         synchronized (conContext) {     // handshake lock
 710             // double check the context status
 711             if (conContext.isNegotiated || conContext.isBroken ||
 712                     conContext.isInboundClosed() ||
 713                     conContext.isOutboundClosed()) {
 714                 return;
 715             }
 716 
 717             startHandshake();
 718         }
 719     }
 720 
 721     /**
 722      * InputStream for application data as returned by
 723      * SSLSocket.getInputStream().
 724      */
 725     private class AppInputStream extends InputStream {
 726         // One element array used to implement the single byte read() method
 727         private final byte[] oneByte = new byte[1];
 728 
 729         // the temporary buffer used to read network
 730         private ByteBuffer buffer;
 731 
 732         // Is application data available in the stream?
 733         private volatile boolean appDataIsAvailable;
 734 
 735         AppInputStream() {
 736             this.appDataIsAvailable = false;
 737             this.buffer = ByteBuffer.allocate(4096);
 738         }
 739 
 740         /**
 741          * Return the minimum number of bytes that can be read
 742          * without blocking.
 743          */
 744         @Override
 745         public int available() throws IOException {
 746             // Currently not synchronized.
 747             if ((!appDataIsAvailable) || checkEOF()) {
 748                 return 0;
 749             }
 750 
 751             return buffer.remaining();
 752         }
 753 
 754         /**
 755          * Read a single byte, returning -1 on non-fault EOF status.
 756          */
 757         @Override
 758         public int read() throws IOException {
 759             int n = read(oneByte, 0, 1);
 760             if (n <= 0) {   // EOF
 761                 return -1;
 762             }
 763 
 764             return oneByte[0] & 0xFF;
 765         }
 766 
 767         /**
 768          * Reads up to {@code len} bytes of data from the input stream
 769          * into an array of bytes.
 770          *
 771          * An attempt is made to read as many as {@code len} bytes, but a
 772          * smaller number may be read. The number of bytes actually read
 773          * is returned as an integer.
 774          *
 775          * If the layer above needs more data, it asks for more, so we
 776          * are responsible only for blocking to fill at most one buffer,
 777          * and returning "-1" on non-fault EOF status.
 778          */
 779         @Override
 780         public int read(byte[] b, int off, int len)
 781                 throws IOException {
 782             if (b == null) {
 783                 throw new NullPointerException("the target buffer is null");
 784             } else if (off < 0 || len < 0 || len > b.length - off) {
 785                 throw new IndexOutOfBoundsException(
 786                         "buffer length: " + b.length + ", offset; " + off +
 787                         ", bytes to read:" + len);
 788             } else if (len == 0) {
 789                 return 0;
 790             }
 791 
 792             if (checkEOF()) {
 793                 return -1;
 794             }
 795 
 796             // start handshaking if the connection has not been negotiated.
 797             if (!conContext.isNegotiated && !conContext.isBroken &&
 798                     !conContext.isInboundClosed() &&
 799                     !conContext.isOutboundClosed()) {
 800                 ensureNegotiated();
 801             }
 802 
 803             // Check if the Socket is invalid (error or closed).
 804             if (!conContext.isNegotiated ||
 805                     conContext.isBroken || conContext.isInboundClosed()) {
 806                 throw new SocketException("Connection or inbound has closed");
 807             }
 808 
 809             // Read the available bytes at first.
 810             //
 811             // Note that the receiving and processing of post-handshake message
 812             // are also synchronized with the read lock.
 813             synchronized (this) {
 814                 int remains = available();
 815                 if (remains > 0) {
 816                     int howmany = Math.min(remains, len);
 817                     buffer.get(b, off, howmany);
 818 
 819                     return howmany;
 820                 }
 821 
 822                 appDataIsAvailable = false;
 823                 try {
 824                     ByteBuffer bb = readApplicationRecord(buffer);
 825                     if (bb == null) {   // EOF
 826                         return -1;
 827                     } else {
 828                         // The buffer may be reallocated for bigger capacity.
 829                         buffer = bb;
 830                     }
 831 
 832                     bb.flip();
 833                     int volume = Math.min(len, bb.remaining());
 834                     buffer.get(b, off, volume);
 835                     appDataIsAvailable = true;
 836 
 837                     return volume;
 838                 } catch (Exception e) {   // including RuntimeException
 839                     // shutdown and rethrow (wrapped) exception as appropriate
 840                     handleException(e);
 841 
 842                     // dummy for compiler
 843                     return -1;
 844                 }
 845             }
 846         }
 847 
 848         /**
 849          * Skip n bytes.
 850          *
 851          * This implementation is somewhat less efficient than possible, but
 852          * not badly so (redundant copy).  We reuse the read() code to keep
 853          * things simpler.
 854          */
 855         @Override
 856         public synchronized long skip(long n) throws IOException {
 857             // dummy array used to implement skip()
 858             byte[] skipArray = new byte[256];
 859 
 860             long skipped = 0;
 861             while (n > 0) {
 862                 int len = (int)Math.min(n, skipArray.length);
 863                 int r = read(skipArray, 0, len);
 864                 if (r <= 0) {
 865                     break;
 866                 }
 867                 n -= r;
 868                 skipped += r;
 869             }
 870 
 871             return skipped;
 872         }
 873 
 874         @Override
 875         public void close() throws IOException {
 876             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 877                 SSLLogger.finest("Closing input stream");
 878             }
 879 
 880             try {
 881                 SSLSocketImpl.this.close();
 882             } catch (IOException ioe) {
 883                 // ignore the exception
 884                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 885                     SSLLogger.warning("input stream close failed", ioe);
 886                 }
 887             }
 888         }
 889 
 890         /**
 891          * Return whether we have reached end-of-file.
 892          *
 893          * If the socket is not connected, has been shutdown because of an error
 894          * or has been closed, throw an Exception.
 895          */
 896         private boolean checkEOF() throws IOException {
 897             if (conContext.isInboundClosed()) {
 898                 return true;
 899             } else if (conContext.isInputCloseNotified || conContext.isBroken) {
 900                 if (conContext.closeReason == null) {
 901                     return true;
 902                 } else {
 903                     throw new SSLException(
 904                         "Connection has closed: " + conContext.closeReason,
 905                         conContext.closeReason);
 906                 }
 907             }
 908 
 909             return false;
 910         }
 911     }
 912 
 913     @Override
 914     public synchronized OutputStream getOutputStream() throws IOException {
 915         if (isClosed()) {
 916             throw new SocketException("Socket is closed");
 917         }
 918 
 919         if (!isConnected) {
 920             throw new SocketException("Socket is not connected");
 921         }
 922 
 923         if (conContext.isOutboundDone() || isOutputShutdown()) {
 924             throw new SocketException("Socket output is already shutdown");
 925         }
 926 
 927         return appOutput;
 928     }
 929 
 930 
 931     /**
 932      * OutputStream for application data as returned by
 933      * SSLSocket.getOutputStream().
 934      */
 935     private class AppOutputStream extends OutputStream {
 936         // One element array used to implement the write(byte) method
 937         private final byte[] oneByte = new byte[1];
 938 
 939         @Override
 940         public void write(int i) throws IOException {
 941             oneByte[0] = (byte)i;
 942             write(oneByte, 0, 1);
 943         }
 944 
 945         @Override
 946         public void write(byte[] b,
 947                 int off, int len) throws IOException {
 948             if (b == null) {
 949                 throw new NullPointerException("the source buffer is null");
 950             } else if (off < 0 || len < 0 || len > b.length - off) {
 951                 throw new IndexOutOfBoundsException(
 952                         "buffer length: " + b.length + ", offset; " + off +
 953                         ", bytes to read:" + len);
 954             } else if (len == 0) {
 955                 //
 956                 // Don't bother to really write empty records.  We went this
 957                 // far to drive the handshake machinery, for correctness; not
 958                 // writing empty records improves performance by cutting CPU
 959                 // time and network resource usage.  However, some protocol
 960                 // implementations are fragile and don't like to see empty
 961                 // records, so this also increases robustness.
 962                 //
 963                 return;
 964             }
 965 
 966             // Start handshaking if the connection has not been negotiated.
 967             if (!conContext.isNegotiated && !conContext.isBroken &&
 968                     !conContext.isInboundClosed() &&
 969                     !conContext.isOutboundClosed()) {
 970                 ensureNegotiated();
 971             }
 972 
 973             // Check if the Socket is invalid (error or closed).
 974             if (!conContext.isNegotiated ||
 975                     conContext.isBroken || conContext.isOutboundClosed()) {
 976                 throw new SocketException("Connection or outbound has closed");
 977             }
 978 
 979             //
 980 
 981             // Delegate the writing to the underlying socket.
 982             try {
 983                 conContext.outputRecord.deliver(b, off, len);
 984             } catch (SSLHandshakeException she) {
 985                 // may be record sequence number overflow
 986                 throw conContext.fatal(Alert.HANDSHAKE_FAILURE, she);
 987             } catch (IOException e) {
 988                 throw conContext.fatal(Alert.UNEXPECTED_MESSAGE, e);
 989             }
 990 
 991             // Is the sequence number is nearly overflow, or has the key usage
 992             // limit been reached?
 993             if (conContext.outputRecord.seqNumIsHuge() ||
 994                     conContext.outputRecord.writeCipher.atKeyLimit()) {
 995                 tryKeyUpdate();
 996             }
 997         }
 998 
 999         @Override
1000         public void close() throws IOException {
1001             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1002                 SSLLogger.finest("Closing output stream");
1003             }
1004 
1005             try {
1006                 SSLSocketImpl.this.close();
1007             } catch (IOException ioe) {
1008                 // ignore the exception
1009                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1010                     SSLLogger.warning("output stream close failed", ioe);
1011                 }
1012             }
1013         }
1014     }
1015 
1016     @Override
1017     public synchronized SSLParameters getSSLParameters() {
1018         return conContext.sslConfig.getSSLParameters();
1019     }
1020 
1021     @Override
1022     public synchronized void setSSLParameters(SSLParameters params) {
1023         conContext.sslConfig.setSSLParameters(params);
1024 
1025         if (conContext.sslConfig.maximumPacketSize != 0) {
1026             conContext.outputRecord.changePacketSize(
1027                     conContext.sslConfig.maximumPacketSize);
1028         }
1029     }
1030 
1031     @Override
1032     public synchronized String getApplicationProtocol() {
1033         return conContext.applicationProtocol;
1034     }
1035 
1036     @Override
1037     public synchronized String getHandshakeApplicationProtocol() {
1038         if (conContext.handshakeContext != null) {
1039             return conContext.handshakeContext.applicationProtocol;
1040         }
1041 
1042         return null;
1043     }
1044 
1045     @Override
1046     public synchronized void setHandshakeApplicationProtocolSelector(
1047             BiFunction<SSLSocket, List<String>, String> selector) {
1048         conContext.sslConfig.socketAPSelector = selector;
1049     }
1050 
1051     @Override
1052     public synchronized BiFunction<SSLSocket, List<String>, String>
1053             getHandshakeApplicationProtocolSelector() {
1054         return conContext.sslConfig.socketAPSelector;
1055     }
1056 
1057     /**
1058      * Read the initial handshake records.
1059      */
1060     private int readHandshakeRecord() throws IOException {
1061         while (!conContext.isInboundClosed()) {
1062             try {
1063                 Plaintext plainText = decode(null);
1064                 if ((plainText.contentType == ContentType.HANDSHAKE.id) &&
1065                         conContext.isNegotiated) {
1066                     return 0;
1067                 }
1068             } catch (SSLException ssle) {
1069                 throw ssle;
1070             } catch (IOException ioe) {
1071                 if (!(ioe instanceof SSLException)) {
1072                     throw new SSLException("readHandshakeRecord", ioe);
1073                 } else {
1074                     throw ioe;
1075                 }
1076             }
1077         }
1078 
1079         return -1;
1080     }
1081 
1082     /**
1083      * Read application data record. Used by AppInputStream only, but defined
1084      * here so as to use the socket level synchronization.
1085      *
1086      * Note that the connection guarantees that handshake, alert, and change
1087      * cipher spec data streams are handled as they arrive, so we never see
1088      * them here.
1089      *
1090      * Note: Please be careful about the synchronization, and don't use this
1091      * method other than in the AppInputStream class!
1092      */
1093     private ByteBuffer readApplicationRecord(
1094             ByteBuffer buffer) throws IOException {
1095         while (!conContext.isInboundClosed()) {
1096             /*
1097              * clean the buffer and check if it is too small, e.g. because
1098              * the AppInputStream did not have the chance to see the
1099              * current packet length but rather something like that of the
1100              * handshake before. In that case we return 0 at this point to
1101              * give the caller the chance to adjust the buffer.
1102              */
1103             buffer.clear();
1104             int inLen = conContext.inputRecord.bytesInCompletePacket();
1105             if (inLen < 0) {    // EOF
1106                 handleEOF(null);
1107 
1108                 // if no exception thrown
1109                 return null;
1110             }
1111 
1112             // Is this packet bigger than SSL/TLS normally allows?
1113             if (inLen > SSLRecord.maxLargeRecordSize) {
1114                 throw new SSLProtocolException(
1115                         "Illegal packet size: " + inLen);
1116             }
1117 
1118             if (inLen > buffer.remaining()) {
1119                 buffer = ByteBuffer.allocate(inLen);
1120             }
1121 
1122             try {
1123                 Plaintext plainText;
1124                 synchronized (this) {
1125                     plainText = decode(buffer);
1126                 }
1127                 if (plainText.contentType == ContentType.APPLICATION_DATA.id &&
1128                         buffer.position() > 0) {
1129                     return buffer;
1130                 }
1131             } catch (SSLException ssle) {
1132                 throw ssle;
1133             } catch (IOException ioe) {
1134                 if (!(ioe instanceof SSLException)) {
1135                     throw new SSLException("readApplicationRecord", ioe);
1136                 } else {
1137                     throw ioe;
1138                 }
1139             }
1140         }
1141 
1142         //
1143         // couldn't read, due to some kind of error
1144         //
1145         return null;
1146     }
1147 
1148     private Plaintext decode(ByteBuffer destination) throws IOException {
1149         Plaintext plainText;
1150         try {
1151             if (destination == null) {
1152                 plainText = SSLTransport.decode(conContext,
1153                         null, 0, 0, null, 0, 0);
1154             } else {
1155                 plainText = SSLTransport.decode(conContext,
1156                         null, 0, 0, new ByteBuffer[]{destination}, 0, 1);
1157             }
1158         } catch (EOFException eofe) {
1159             // EOFException is special as it is related to close_notify.
1160             plainText = handleEOF(eofe);
1161         }
1162 
1163         // Is the sequence number is nearly overflow?
1164         if (plainText != Plaintext.PLAINTEXT_NULL &&
1165                 (conContext.inputRecord.seqNumIsHuge() ||
1166                 conContext.inputRecord.readCipher.atKeyLimit())) {
1167             tryKeyUpdate();
1168         }
1169 
1170         return plainText;
1171     }
1172 
1173     /**
1174      * Try key update for sequence number wrap or key usage limit.
1175      *
1176      * Note that in order to maintain the handshake status properly, we check
1177      * the sequence number and key usage limit after the last record
1178      * reading/writing process.
1179      *
1180      * As we request renegotiation or close the connection for wrapped sequence
1181      * number when there is enough sequence number space left to handle a few
1182      * more records, so the sequence number of the last record cannot be
1183      * wrapped.
1184      */
1185     private void tryKeyUpdate() throws IOException {
1186         // Don't bother to kickstart if handshaking is in progress, or if the
1187         // connection is not duplex-open.
1188         if ((conContext.handshakeContext == null) &&
1189                 !conContext.isOutboundClosed() &&
1190                 !conContext.isInboundClosed() &&
1191                 !conContext.isBroken) {
1192             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1193                 SSLLogger.finest("trigger key update");
1194             }
1195             startHandshake();
1196         }
1197     }
1198 
1199     /**
1200      * Initialize the handshaker and socket streams.
1201      *
1202      * Called by connect, the layered constructor, and SSLServerSocket.
1203      */
1204     synchronized void doneConnect() throws IOException {
1205         // In server mode, it is not necessary to set host and serverNames.
1206         // Otherwise, would require a reverse DNS lookup to get the hostname.
1207         if (peerHost == null || peerHost.isEmpty()) {
1208             boolean useNameService =
1209                     trustNameService && conContext.sslConfig.isClientMode;
1210             useImplicitHost(useNameService);
1211         } else {
1212             conContext.sslConfig.serverNames =
1213                     Utilities.addToSNIServerNameList(
1214                             conContext.sslConfig.serverNames, peerHost);
1215         }
1216 
1217         InputStream sockInput = super.getInputStream();
1218         conContext.inputRecord.setReceiverStream(sockInput);
1219 
1220         OutputStream sockOutput = super.getOutputStream();
1221         conContext.inputRecord.setDeliverStream(sockOutput);
1222         conContext.outputRecord.setDeliverStream(sockOutput);
1223 
1224         this.isConnected = true;
1225     }
1226 
1227     private void useImplicitHost(boolean useNameService) {
1228         // Note: If the local name service is not trustworthy, reverse
1229         // host name resolution should not be performed for endpoint
1230         // identification.  Use the application original specified
1231         // hostname or IP address instead.
1232 
1233         // Get the original hostname via jdk.internal.misc.SharedSecrets
1234         InetAddress inetAddress = getInetAddress();
1235         if (inetAddress == null) {      // not connected
1236             return;
1237         }
1238 
1239         String originalHostname = SharedSecrets.getJavaNetAccess().getOriginalHostName(inetAddress);
1240         if (originalHostname != null && !originalHostname.isEmpty()) {
1241 
1242             this.peerHost = originalHostname;
1243             if (conContext.sslConfig.serverNames.isEmpty() &&
1244                     !conContext.sslConfig.noSniExtension) {
1245                 conContext.sslConfig.serverNames =
1246                         Utilities.addToSNIServerNameList(
1247                                 conContext.sslConfig.serverNames, peerHost);
1248             }
1249 
1250             return;
1251         }
1252 
1253         // No explicitly specified hostname, no server name indication.
1254         if (!useNameService) {
1255             // The local name service is not trustworthy, use IP address.
1256             this.peerHost = inetAddress.getHostAddress();
1257         } else {
1258             // Use the underlying reverse host name resolution service.
1259             this.peerHost = getInetAddress().getHostName();
1260         }
1261     }
1262 
1263     // ONLY used by HttpsClient to setup the URI specified hostname
1264     //
1265     // Please NOTE that this method MUST be called before calling to
1266     // SSLSocket.setSSLParameters(). Otherwise, the {@code host} parameter
1267     // may override SNIHostName in the customized server name indication.
1268     public synchronized void setHost(String host) {
1269         this.peerHost = host;
1270         this.conContext.sslConfig.serverNames =
1271                 Utilities.addToSNIServerNameList(
1272                         conContext.sslConfig.serverNames, host);
1273     }
1274 
1275     /**
1276      * Handle an exception.
1277      *
1278      * This method is called by top level exception handlers (in read(),
1279      * write()) to make sure we always shutdown the connection correctly
1280      * and do not pass runtime exception to the application.
1281      *
1282      * This method never returns normally, it always throws an IOException.
1283      */
1284     private void handleException(Exception cause) throws IOException {
1285         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1286             SSLLogger.warning("handling exception", cause);
1287         }
1288 
1289         // Don't close the Socket in case of timeouts or interrupts.
1290         if (cause instanceof InterruptedIOException) {
1291             throw (IOException)cause;
1292         }
1293 
1294         // need to perform error shutdown
1295         boolean isSSLException = (cause instanceof SSLException);
1296         Alert alert;
1297         if (isSSLException) {
1298             if (cause instanceof SSLHandshakeException) {
1299                 alert = Alert.HANDSHAKE_FAILURE;
1300             } else {
1301                 alert = Alert.UNEXPECTED_MESSAGE;
1302             }
1303         } else {
1304             if (cause instanceof IOException) {
1305                 alert = Alert.UNEXPECTED_MESSAGE;
1306             } else {
1307                 // RuntimeException
1308                 alert = Alert.INTERNAL_ERROR;
1309             }
1310         }
1311 
1312         throw conContext.fatal(alert, cause);
1313     }
1314 
1315     private Plaintext handleEOF(EOFException eofe) throws IOException {
1316         if (requireCloseNotify || conContext.handshakeContext != null) {
1317             SSLException ssle;
1318             if (conContext.handshakeContext != null) {
1319                 ssle = new SSLHandshakeException(
1320                         "Remote host terminated the handshake");
1321             } else {
1322                 ssle = new SSLProtocolException(
1323                         "Remote host terminated the connection");
1324             }
1325 
1326             if (eofe != null) {
1327                 ssle.initCause(eofe);
1328             }
1329             throw ssle;
1330         } else {
1331             // treat as if we had received a close_notify
1332             conContext.isInputCloseNotified = true;
1333             shutdownInput();
1334 
1335             return Plaintext.PLAINTEXT_NULL;
1336         }
1337     }
1338 
1339 
1340     @Override
1341     public String getPeerHost() {
1342         return peerHost;
1343     }
1344 
1345     @Override
1346     public int getPeerPort() {
1347         return getPort();
1348     }
1349 
1350     @Override
1351     public boolean useDelegatedTask() {
1352         return false;
1353     }
1354 
1355     @Override
1356     public void shutdown() throws IOException {
1357         if (!isClosed()) {
1358             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1359                 SSLLogger.fine("close the underlying socket");
1360             }
1361 
1362             try {
1363                 if (conContext.isInputCloseNotified) {
1364                     // Close the connection, no wait for more peer response.
1365                     closeSocket(false);
1366                 } else {
1367                     // Close the connection, may wait for peer close_notify.
1368                     closeSocket(true);
1369                 }
1370             } finally {
1371                 tlsIsClosed = true;
1372             }
1373         }
1374     }
1375 
1376     private void closeSocket(boolean selfInitiated) throws IOException {
1377         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1378             SSLLogger.fine("close the SSL connection " +
1379                 (selfInitiated ? "(initiative)" : "(passive)"));
1380         }
1381 
1382         if (autoClose || !isLayered()) {
1383             super.close();
1384         } else if (selfInitiated) {
1385             if (!conContext.isInboundClosed() && !isInputShutdown()) {
1386                 // wait for close_notify alert to clear input stream.
1387                 waitForClose();
1388             }
1389         }
1390     }
1391 
1392    /**
1393     * Wait for close_notify alert for a graceful closure.
1394     *
1395     * [RFC 5246] If the application protocol using TLS provides that any
1396     * data may be carried over the underlying transport after the TLS
1397     * connection is closed, the TLS implementation must receive the responding
1398     * close_notify alert before indicating to the application layer that
1399     * the TLS connection has ended.  If the application protocol will not
1400     * transfer any additional data, but will only close the underlying
1401     * transport connection, then the implementation MAY choose to close the
1402     * transport without waiting for the responding close_notify.
1403     */
1404     private void waitForClose() throws IOException {
1405         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1406             SSLLogger.fine("wait for close_notify or alert");
1407         }
1408 
1409         while (!conContext.isInboundClosed()) {
1410             try {
1411                 Plaintext plainText = decode(null);
1412                 // discard and continue
1413                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1414                     SSLLogger.finest(
1415                         "discard plaintext while waiting for close", plainText);
1416                 }
1417             } catch (Exception e) {   // including RuntimeException
1418                 handleException(e);
1419             }
1420         }
1421     }
1422 }