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 (tlsIsClosed) {
 461             return;
 462         }
 463 
 464         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 465             SSLLogger.fine("duplex close of SSLSocket");
 466         }
 467 
 468         try {
 469             // shutdown output bound, which may have been closed previously.
 470             if (!isOutputShutdown()) {
 471                 duplexCloseOutput();
 472             }
 473 
 474             // shutdown input bound, which may have been closed previously.
 475             if (!isInputShutdown()) {
 476                 duplexCloseInput();
 477             }
 478 
 479             if (!isClosed()) {
 480                 // close the connection directly
 481                 closeSocket(false);
 482             }
 483         } catch (IOException ioe) {
 484             // ignore the exception
 485             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 486                 SSLLogger.warning("SSLSocket duplex close failed", ioe);
 487             }
 488         } finally {
 489             tlsIsClosed = true;
 490         }
 491     }
 492 
 493     /**
 494      * Duplex close, start from closing outbound.
 495      *
 496      * For TLS 1.2 [RFC 5246], unless some other fatal alert has been
 497      * transmitted, each party is required to send a close_notify alert
 498      * before closing the write side of the connection.  The other party
 499      * MUST respond with a close_notify alert of its own and close down
 500      * the connection immediately, discarding any pending writes.  It is
 501      * not required for the initiator of the close to wait for the responding
 502      * close_notify alert before closing the read side of the connection.
 503      *
 504      * For TLS 1.3, Each party MUST send a close_notify alert before
 505      * closing its write side of the connection, unless it has already sent
 506      * some error alert.  This does not have any effect on its read side of
 507      * the connection.  Both parties need not wait to receive a close_notify
 508      * alert before closing their read side of the connection, though doing
 509      * so would introduce the possibility of truncation.
 510      *
 511      * In order to support user initiated duplex-close for TLS 1.3 connections,
 512      * the user_canceled alert is used together with the close_notify alert.
 513      */
 514     private void duplexCloseOutput() throws IOException {
 515         boolean useUserCanceled = false;
 516         boolean hasCloseReceipt = false;
 517         if (conContext.isNegotiated) {
 518             if (!conContext.protocolVersion.useTLS13PlusSpec()) {
 519                 hasCloseReceipt = true;
 520             } else {
 521                 // Use a user_canceled alert for TLS 1.3 duplex close.
 522                 useUserCanceled = true;
 523             }
 524         } else if (conContext.handshakeContext != null) {   // initial handshake
 525             // Use user_canceled alert regardless the protocol versions.
 526             useUserCanceled = true;
 527 
 528             // The protocol version may have been negotiated.
 529             ProtocolVersion pv = conContext.handshakeContext.negotiatedProtocol;
 530             if (pv == null || (!pv.useTLS13PlusSpec())) {
 531                 hasCloseReceipt = true;
 532             }
 533         }
 534 
 535         // Need a lock here so that the user_canceled alert and the
 536         // close_notify alert can be delivered together.
 537         try {
 538             synchronized (conContext.outputRecord) {
 539                 // send a user_canceled alert if needed.
 540                 if (useUserCanceled) {
 541                     conContext.warning(Alert.USER_CANCELED);
 542                 }
 543 
 544                 // send a close_notify alert
 545                 conContext.warning(Alert.CLOSE_NOTIFY);
 546             }
 547         } finally {
 548             if (!conContext.isOutboundClosed()) {
 549                 conContext.outputRecord.close();
 550             }
 551 
 552             if ((autoClose || !isLayered()) && !super.isOutputShutdown()) {
 553                 super.shutdownOutput();
 554             }
 555         }
 556 
 557         if (!isInputShutdown()) {
 558             bruteForceCloseInput(hasCloseReceipt);
 559         }
 560     }
 561 
 562     /**
 563      * Duplex close, start from closing inbound.
 564      *
 565      * This method should only be called when the outbound has been closed,
 566      * but the inbound is still open.
 567      */
 568     private void duplexCloseInput() throws IOException {
 569         boolean hasCloseReceipt = false;
 570         if (conContext.isNegotiated &&
 571                 !conContext.protocolVersion.useTLS13PlusSpec()) {
 572             hasCloseReceipt = true;
 573         }   // No close receipt if handshake has no completed.
 574 
 575         bruteForceCloseInput(hasCloseReceipt);
 576     }
 577 
 578     /**
 579      * Brute force close the input bound.
 580      *
 581      * This method should only be called when the outbound has been closed,
 582      * but the inbound is still open.
 583      */
 584     private void bruteForceCloseInput(
 585             boolean hasCloseReceipt) throws IOException {
 586         if (hasCloseReceipt) {
 587             // It is not required for the initiator of the close to wait for
 588             // the responding close_notify alert before closing the read side
 589             // of the connection.  However, if the application protocol using
 590             // TLS provides that any data may be carried over the underlying
 591             // transport after the TLS connection is closed, the TLS
 592             // implementation MUST receive a "close_notify" alert before
 593             // indicating end-of-data to the application-layer.
 594             try {
 595                 this.shutdown();
 596             } finally {
 597                 if (!isInputShutdown()) {
 598                     shutdownInput(false);
 599                 }
 600             }
 601         } else {
 602             if (!conContext.isInboundClosed()) {
 603                 conContext.inputRecord.close();
 604             }
 605 
 606             if ((autoClose || !isLayered()) && !super.isInputShutdown()) {
 607                 super.shutdownInput();
 608             }
 609         }
 610     }
 611 
 612     // Please don't synchronized this method.  Otherwise, the read and close
 613     // locks may be deadlocked.
 614     @Override
 615     public void shutdownInput() throws IOException {
 616         shutdownInput(true);
 617     }
 618 
 619     // It is not required to check the close_notify receipt unless an
 620     // application call shutdownInput() explicitly.
 621     private void shutdownInput(
 622             boolean checkCloseNotify) throws IOException {
 623         if (isInputShutdown()) {
 624             return;
 625         }
 626 
 627         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 628             SSLLogger.fine("close inbound of SSLSocket");
 629         }
 630 
 631         // Is it ready to close inbound?
 632         //
 633         // No need to throw exception if the initial handshake is not started.
 634         if (checkCloseNotify && !conContext.isInputCloseNotified &&
 635             (conContext.isNegotiated || conContext.handshakeContext != null)) {
 636 
 637             throw conContext.fatal(Alert.INTERNAL_ERROR,
 638                     "closing inbound before receiving peer's close_notify");
 639         }
 640 
 641         conContext.closeInbound();
 642         if ((autoClose || !isLayered()) && !super.isInputShutdown()) {
 643             super.shutdownInput();
 644         }
 645     }
 646 
 647     @Override
 648     public boolean isInputShutdown() {
 649         return conContext.isInboundClosed() &&
 650                 ((autoClose || !isLayered()) ? super.isInputShutdown(): true);
 651     }
 652 
 653     // Please don't synchronized this method.  Otherwise, the read and close
 654     // locks may be deadlocked.
 655     @Override
 656     public void shutdownOutput() throws IOException {
 657         if (isOutputShutdown()) {
 658             return;
 659         }
 660 
 661         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 662             SSLLogger.fine("close outbound of SSLSocket");
 663         }
 664         conContext.closeOutbound();
 665 
 666         if ((autoClose || !isLayered()) && !super.isOutputShutdown()) {
 667             super.shutdownOutput();
 668         }
 669     }
 670 
 671     @Override
 672     public boolean isOutputShutdown() {
 673         return conContext.isOutboundClosed() &&
 674                 ((autoClose || !isLayered()) ? super.isOutputShutdown(): true);
 675     }
 676 
 677     @Override
 678     public synchronized InputStream getInputStream() throws IOException {
 679         if (isClosed()) {
 680             throw new SocketException("Socket is closed");
 681         }
 682 
 683         if (!isConnected) {
 684             throw new SocketException("Socket is not connected");
 685         }
 686 
 687         if (conContext.isInboundClosed() || isInputShutdown()) {
 688             throw new SocketException("Socket input is already shutdown");
 689         }
 690 
 691         return appInput;
 692     }
 693 
 694     private void ensureNegotiated() throws IOException {
 695         if (conContext.isNegotiated || conContext.isBroken ||
 696                 conContext.isInboundClosed() || conContext.isOutboundClosed()) {
 697             return;
 698         }
 699 
 700         synchronized (conContext) {     // handshake lock
 701             // double check the context status
 702             if (conContext.isNegotiated || conContext.isBroken ||
 703                     conContext.isInboundClosed() ||
 704                     conContext.isOutboundClosed()) {
 705                 return;
 706             }
 707 
 708             startHandshake();
 709         }
 710     }
 711 
 712     /**
 713      * InputStream for application data as returned by
 714      * SSLSocket.getInputStream().
 715      */
 716     private class AppInputStream extends InputStream {
 717         // One element array used to implement the single byte read() method
 718         private final byte[] oneByte = new byte[1];
 719 
 720         // the temporary buffer used to read network
 721         private ByteBuffer buffer;
 722 
 723         // Is application data available in the stream?
 724         private volatile boolean appDataIsAvailable;
 725 
 726         AppInputStream() {
 727             this.appDataIsAvailable = false;
 728             this.buffer = ByteBuffer.allocate(4096);
 729         }
 730 
 731         /**
 732          * Return the minimum number of bytes that can be read
 733          * without blocking.
 734          */
 735         @Override
 736         public int available() throws IOException {
 737             // Currently not synchronized.
 738             if ((!appDataIsAvailable) || checkEOF()) {
 739                 return 0;
 740             }
 741 
 742             return buffer.remaining();
 743         }
 744 
 745         /**
 746          * Read a single byte, returning -1 on non-fault EOF status.
 747          */
 748         @Override
 749         public int read() throws IOException {
 750             int n = read(oneByte, 0, 1);
 751             if (n <= 0) {   // EOF
 752                 return -1;
 753             }
 754 
 755             return oneByte[0] & 0xFF;
 756         }
 757 
 758         /**
 759          * Reads up to {@code len} bytes of data from the input stream
 760          * into an array of bytes.
 761          *
 762          * An attempt is made to read as many as {@code len} bytes, but a
 763          * smaller number may be read. The number of bytes actually read
 764          * is returned as an integer.
 765          *
 766          * If the layer above needs more data, it asks for more, so we
 767          * are responsible only for blocking to fill at most one buffer,
 768          * and returning "-1" on non-fault EOF status.
 769          */
 770         @Override
 771         public int read(byte[] b, int off, int len)
 772                 throws IOException {
 773             if (b == null) {
 774                 throw new NullPointerException("the target buffer is null");
 775             } else if (off < 0 || len < 0 || len > b.length - off) {
 776                 throw new IndexOutOfBoundsException(
 777                         "buffer length: " + b.length + ", offset; " + off +
 778                         ", bytes to read:" + len);
 779             } else if (len == 0) {
 780                 return 0;
 781             }
 782 
 783             if (checkEOF()) {
 784                 return -1;
 785             }
 786 
 787             // start handshaking if the connection has not been negotiated.
 788             if (!conContext.isNegotiated && !conContext.isBroken &&
 789                     !conContext.isInboundClosed() &&
 790                     !conContext.isOutboundClosed()) {
 791                 ensureNegotiated();
 792             }
 793 
 794             // Check if the Socket is invalid (error or closed).
 795             if (!conContext.isNegotiated ||
 796                     conContext.isBroken || conContext.isInboundClosed()) {
 797                 throw new SocketException("Connection or inbound has closed");
 798             }
 799 
 800             // Read the available bytes at first.
 801             //
 802             // Note that the receiving and processing of post-handshake message
 803             // are also synchronized with the read lock.
 804             synchronized (this) {
 805                 int remains = available();
 806                 if (remains > 0) {
 807                     int howmany = Math.min(remains, len);
 808                     buffer.get(b, off, howmany);
 809 
 810                     return howmany;
 811                 }
 812 
 813                 appDataIsAvailable = false;
 814                 try {
 815                     ByteBuffer bb = readApplicationRecord(buffer);
 816                     if (bb == null) {   // EOF
 817                         return -1;
 818                     } else {
 819                         // The buffer may be reallocated for bigger capacity.
 820                         buffer = bb;
 821                     }
 822 
 823                     bb.flip();
 824                     int volume = Math.min(len, bb.remaining());
 825                     buffer.get(b, off, volume);
 826                     appDataIsAvailable = true;
 827 
 828                     return volume;
 829                 } catch (Exception e) {   // including RuntimeException
 830                     // shutdown and rethrow (wrapped) exception as appropriate
 831                     handleException(e);
 832 
 833                     // dummy for compiler
 834                     return -1;
 835                 }
 836             }
 837         }
 838 
 839         /**
 840          * Skip n bytes.
 841          *
 842          * This implementation is somewhat less efficient than possible, but
 843          * not badly so (redundant copy).  We reuse the read() code to keep
 844          * things simpler.
 845          */
 846         @Override
 847         public synchronized long skip(long n) throws IOException {
 848             // dummy array used to implement skip()
 849             byte[] skipArray = new byte[256];
 850 
 851             long skipped = 0;
 852             while (n > 0) {
 853                 int len = (int)Math.min(n, skipArray.length);
 854                 int r = read(skipArray, 0, len);
 855                 if (r <= 0) {
 856                     break;
 857                 }
 858                 n -= r;
 859                 skipped += r;
 860             }
 861 
 862             return skipped;
 863         }
 864 
 865         @Override
 866         public void close() throws IOException {
 867             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 868                 SSLLogger.finest("Closing input stream");
 869             }
 870 
 871             try {
 872                 SSLSocketImpl.this.close();
 873             } catch (IOException ioe) {
 874                 // ignore the exception
 875                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 876                     SSLLogger.warning("input stream close failed", ioe);
 877                 }
 878             }
 879         }
 880 
 881         /**
 882          * Return whether we have reached end-of-file.
 883          *
 884          * If the socket is not connected, has been shutdown because of an error
 885          * or has been closed, throw an Exception.
 886          */
 887         private boolean checkEOF() throws IOException {
 888             if (conContext.isInboundClosed()) {
 889                 return true;
 890             } else if (conContext.isInputCloseNotified || conContext.isBroken) {
 891                 if (conContext.closeReason == null) {
 892                     return true;
 893                 } else {
 894                     throw new SSLException(
 895                         "Connection has closed: " + conContext.closeReason,
 896                         conContext.closeReason);
 897                 }
 898             }
 899 
 900             return false;
 901         }
 902     }
 903 
 904     @Override
 905     public synchronized OutputStream getOutputStream() throws IOException {
 906         if (isClosed()) {
 907             throw new SocketException("Socket is closed");
 908         }
 909 
 910         if (!isConnected) {
 911             throw new SocketException("Socket is not connected");
 912         }
 913 
 914         if (conContext.isOutboundDone() || isOutputShutdown()) {
 915             throw new SocketException("Socket output is already shutdown");
 916         }
 917 
 918         return appOutput;
 919     }
 920 
 921 
 922     /**
 923      * OutputStream for application data as returned by
 924      * SSLSocket.getOutputStream().
 925      */
 926     private class AppOutputStream extends OutputStream {
 927         // One element array used to implement the write(byte) method
 928         private final byte[] oneByte = new byte[1];
 929 
 930         @Override
 931         public void write(int i) throws IOException {
 932             oneByte[0] = (byte)i;
 933             write(oneByte, 0, 1);
 934         }
 935 
 936         @Override
 937         public void write(byte[] b,
 938                 int off, int len) throws IOException {
 939             if (b == null) {
 940                 throw new NullPointerException("the source buffer is null");
 941             } else if (off < 0 || len < 0 || len > b.length - off) {
 942                 throw new IndexOutOfBoundsException(
 943                         "buffer length: " + b.length + ", offset; " + off +
 944                         ", bytes to read:" + len);
 945             } else if (len == 0) {
 946                 //
 947                 // Don't bother to really write empty records.  We went this
 948                 // far to drive the handshake machinery, for correctness; not
 949                 // writing empty records improves performance by cutting CPU
 950                 // time and network resource usage.  However, some protocol
 951                 // implementations are fragile and don't like to see empty
 952                 // records, so this also increases robustness.
 953                 //
 954                 return;
 955             }
 956 
 957             // Start handshaking if the connection has not been negotiated.
 958             if (!conContext.isNegotiated && !conContext.isBroken &&
 959                     !conContext.isInboundClosed() &&
 960                     !conContext.isOutboundClosed()) {
 961                 ensureNegotiated();
 962             }
 963 
 964             // Check if the Socket is invalid (error or closed).
 965             if (!conContext.isNegotiated ||
 966                     conContext.isBroken || conContext.isOutboundClosed()) {
 967                 throw new SocketException("Connection or outbound has closed");
 968             }
 969 
 970             //
 971 
 972             // Delegate the writing to the underlying socket.
 973             try {
 974                 conContext.outputRecord.deliver(b, off, len);
 975             } catch (SSLHandshakeException she) {
 976                 // may be record sequence number overflow
 977                 throw conContext.fatal(Alert.HANDSHAKE_FAILURE, she);
 978             } catch (IOException e) {
 979                 throw conContext.fatal(Alert.UNEXPECTED_MESSAGE, e);
 980             }
 981 
 982             // Is the sequence number is nearly overflow, or has the key usage
 983             // limit been reached?
 984             if (conContext.outputRecord.seqNumIsHuge() ||
 985                     conContext.outputRecord.writeCipher.atKeyLimit()) {
 986                 tryKeyUpdate();
 987             }
 988         }
 989 
 990         @Override
 991         public void close() throws IOException {
 992             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 993                 SSLLogger.finest("Closing output stream");
 994             }
 995 
 996             try {
 997                 SSLSocketImpl.this.close();
 998             } catch (IOException ioe) {
 999                 // ignore the exception
1000                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1001                     SSLLogger.warning("output stream close failed", ioe);
1002                 }
1003             }
1004         }
1005     }
1006 
1007     @Override
1008     public synchronized SSLParameters getSSLParameters() {
1009         return conContext.sslConfig.getSSLParameters();
1010     }
1011 
1012     @Override
1013     public synchronized void setSSLParameters(SSLParameters params) {
1014         conContext.sslConfig.setSSLParameters(params);
1015 
1016         if (conContext.sslConfig.maximumPacketSize != 0) {
1017             conContext.outputRecord.changePacketSize(
1018                     conContext.sslConfig.maximumPacketSize);
1019         }
1020     }
1021 
1022     @Override
1023     public synchronized String getApplicationProtocol() {
1024         return conContext.applicationProtocol;
1025     }
1026 
1027     @Override
1028     public synchronized String getHandshakeApplicationProtocol() {
1029         if (conContext.handshakeContext != null) {
1030             return conContext.handshakeContext.applicationProtocol;
1031         }
1032 
1033         return null;
1034     }
1035 
1036     @Override
1037     public synchronized void setHandshakeApplicationProtocolSelector(
1038             BiFunction<SSLSocket, List<String>, String> selector) {
1039         conContext.sslConfig.socketAPSelector = selector;
1040     }
1041 
1042     @Override
1043     public synchronized BiFunction<SSLSocket, List<String>, String>
1044             getHandshakeApplicationProtocolSelector() {
1045         return conContext.sslConfig.socketAPSelector;
1046     }
1047 
1048     /**
1049      * Read the initial handshake records.
1050      */
1051     private int readHandshakeRecord() throws IOException {
1052         while (!conContext.isInboundClosed()) {
1053             try {
1054                 Plaintext plainText = decode(null);
1055                 if ((plainText.contentType == ContentType.HANDSHAKE.id) &&
1056                         conContext.isNegotiated) {
1057                     return 0;
1058                 }
1059             } catch (SSLException ssle) {
1060                 throw ssle;
1061             } catch (IOException ioe) {
1062                 if (!(ioe instanceof SSLException)) {
1063                     throw new SSLException("readHandshakeRecord", ioe);
1064                 } else {
1065                     throw ioe;
1066                 }
1067             }
1068         }
1069 
1070         return -1;
1071     }
1072 
1073     /**
1074      * Read application data record. Used by AppInputStream only, but defined
1075      * here so as to use the socket level synchronization.
1076      *
1077      * Note that the connection guarantees that handshake, alert, and change
1078      * cipher spec data streams are handled as they arrive, so we never see
1079      * them here.
1080      *
1081      * Note: Please be careful about the synchronization, and don't use this
1082      * method other than in the AppInputStream class!
1083      */
1084     private ByteBuffer readApplicationRecord(
1085             ByteBuffer buffer) throws IOException {
1086         while (!conContext.isInboundClosed()) {
1087             /*
1088              * clean the buffer and check if it is too small, e.g. because
1089              * the AppInputStream did not have the chance to see the
1090              * current packet length but rather something like that of the
1091              * handshake before. In that case we return 0 at this point to
1092              * give the caller the chance to adjust the buffer.
1093              */
1094             buffer.clear();
1095             int inLen = conContext.inputRecord.bytesInCompletePacket();
1096             if (inLen < 0) {    // EOF
1097                 handleEOF(null);
1098 
1099                 // if no exception thrown
1100                 return null;
1101             }
1102 
1103             // Is this packet bigger than SSL/TLS normally allows?
1104             if (inLen > SSLRecord.maxLargeRecordSize) {
1105                 throw new SSLProtocolException(
1106                         "Illegal packet size: " + inLen);
1107             }
1108 
1109             if (inLen > buffer.remaining()) {
1110                 buffer = ByteBuffer.allocate(inLen);
1111             }
1112 
1113             try {
1114                 Plaintext plainText;
1115                 synchronized (this) {
1116                     plainText = decode(buffer);
1117                 }
1118                 if (plainText.contentType == ContentType.APPLICATION_DATA.id &&
1119                         buffer.position() > 0) {
1120                     return buffer;
1121                 }
1122             } catch (SSLException ssle) {
1123                 throw ssle;
1124             } catch (IOException ioe) {
1125                 if (!(ioe instanceof SSLException)) {
1126                     throw new SSLException("readApplicationRecord", ioe);
1127                 } else {
1128                     throw ioe;
1129                 }
1130             }
1131         }
1132 
1133         //
1134         // couldn't read, due to some kind of error
1135         //
1136         return null;
1137     }
1138 
1139     private Plaintext decode(ByteBuffer destination) throws IOException {
1140         Plaintext plainText;
1141         try {
1142             if (destination == null) {
1143                 plainText = SSLTransport.decode(conContext,
1144                         null, 0, 0, null, 0, 0);
1145             } else {
1146                 plainText = SSLTransport.decode(conContext,
1147                         null, 0, 0, new ByteBuffer[]{destination}, 0, 1);
1148             }
1149         } catch (EOFException eofe) {
1150             // EOFException is special as it is related to close_notify.
1151             plainText = handleEOF(eofe);
1152         }
1153 
1154         // Is the sequence number is nearly overflow?
1155         if (plainText != Plaintext.PLAINTEXT_NULL &&
1156                 (conContext.inputRecord.seqNumIsHuge() ||
1157                 conContext.inputRecord.readCipher.atKeyLimit())) {
1158             tryKeyUpdate();
1159         }
1160 
1161         return plainText;
1162     }
1163 
1164     /**
1165      * Try key update for sequence number wrap or key usage limit.
1166      *
1167      * Note that in order to maintain the handshake status properly, we check
1168      * the sequence number and key usage limit after the last record
1169      * reading/writing process.
1170      *
1171      * As we request renegotiation or close the connection for wrapped sequence
1172      * number when there is enough sequence number space left to handle a few
1173      * more records, so the sequence number of the last record cannot be
1174      * wrapped.
1175      */
1176     private void tryKeyUpdate() throws IOException {
1177         // Don't bother to kickstart if handshaking is in progress, or if the
1178         // connection is not duplex-open.
1179         if ((conContext.handshakeContext == null) &&
1180                 !conContext.isOutboundClosed() &&
1181                 !conContext.isInboundClosed() &&
1182                 !conContext.isBroken) {
1183             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1184                 SSLLogger.finest("trigger key update");
1185             }
1186             startHandshake();
1187         }
1188     }
1189 
1190     /**
1191      * Initialize the handshaker and socket streams.
1192      *
1193      * Called by connect, the layered constructor, and SSLServerSocket.
1194      */
1195     synchronized void doneConnect() throws IOException {
1196         // In server mode, it is not necessary to set host and serverNames.
1197         // Otherwise, would require a reverse DNS lookup to get the hostname.
1198         if (peerHost == null || peerHost.isEmpty()) {
1199             boolean useNameService =
1200                     trustNameService && conContext.sslConfig.isClientMode;
1201             useImplicitHost(useNameService);
1202         } else {
1203             conContext.sslConfig.serverNames =
1204                     Utilities.addToSNIServerNameList(
1205                             conContext.sslConfig.serverNames, peerHost);
1206         }
1207 
1208         InputStream sockInput = super.getInputStream();
1209         conContext.inputRecord.setReceiverStream(sockInput);
1210 
1211         OutputStream sockOutput = super.getOutputStream();
1212         conContext.inputRecord.setDeliverStream(sockOutput);
1213         conContext.outputRecord.setDeliverStream(sockOutput);
1214 
1215         this.isConnected = true;
1216     }
1217 
1218     private void useImplicitHost(boolean useNameService) {
1219         // Note: If the local name service is not trustworthy, reverse
1220         // host name resolution should not be performed for endpoint
1221         // identification.  Use the application original specified
1222         // hostname or IP address instead.
1223 
1224         // Get the original hostname via jdk.internal.misc.SharedSecrets
1225         InetAddress inetAddress = getInetAddress();
1226         if (inetAddress == null) {      // not connected
1227             return;
1228         }
1229 
1230         String originalHostname = SharedSecrets.getJavaNetAccess().getOriginalHostName(inetAddress);
1231         if (originalHostname != null && !originalHostname.isEmpty()) {
1232 
1233             this.peerHost = originalHostname;
1234             if (conContext.sslConfig.serverNames.isEmpty() &&
1235                     !conContext.sslConfig.noSniExtension) {
1236                 conContext.sslConfig.serverNames =
1237                         Utilities.addToSNIServerNameList(
1238                                 conContext.sslConfig.serverNames, peerHost);
1239             }
1240 
1241             return;
1242         }
1243 
1244         // No explicitly specified hostname, no server name indication.
1245         if (!useNameService) {
1246             // The local name service is not trustworthy, use IP address.
1247             this.peerHost = inetAddress.getHostAddress();
1248         } else {
1249             // Use the underlying reverse host name resolution service.
1250             this.peerHost = getInetAddress().getHostName();
1251         }
1252     }
1253 
1254     // ONLY used by HttpsClient to setup the URI specified hostname
1255     //
1256     // Please NOTE that this method MUST be called before calling to
1257     // SSLSocket.setSSLParameters(). Otherwise, the {@code host} parameter
1258     // may override SNIHostName in the customized server name indication.
1259     public synchronized void setHost(String host) {
1260         this.peerHost = host;
1261         this.conContext.sslConfig.serverNames =
1262                 Utilities.addToSNIServerNameList(
1263                         conContext.sslConfig.serverNames, host);
1264     }
1265 
1266     /**
1267      * Handle an exception.
1268      *
1269      * This method is called by top level exception handlers (in read(),
1270      * write()) to make sure we always shutdown the connection correctly
1271      * and do not pass runtime exception to the application.
1272      *
1273      * This method never returns normally, it always throws an IOException.
1274      */
1275     private void handleException(Exception cause) throws IOException {
1276         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1277             SSLLogger.warning("handling exception", cause);
1278         }
1279 
1280         // Don't close the Socket in case of timeouts or interrupts.
1281         if (cause instanceof InterruptedIOException) {
1282             throw (IOException)cause;
1283         }
1284 
1285         // need to perform error shutdown
1286         boolean isSSLException = (cause instanceof SSLException);
1287         Alert alert;
1288         if (isSSLException) {
1289             if (cause instanceof SSLHandshakeException) {
1290                 alert = Alert.HANDSHAKE_FAILURE;
1291             } else {
1292                 alert = Alert.UNEXPECTED_MESSAGE;
1293             }
1294         } else {
1295             if (cause instanceof IOException) {
1296                 alert = Alert.UNEXPECTED_MESSAGE;
1297             } else {
1298                 // RuntimeException
1299                 alert = Alert.INTERNAL_ERROR;
1300             }
1301         }
1302 
1303         throw conContext.fatal(alert, cause);
1304     }
1305 
1306     private Plaintext handleEOF(EOFException eofe) throws IOException {
1307         if (requireCloseNotify || conContext.handshakeContext != null) {
1308             SSLException ssle;
1309             if (conContext.handshakeContext != null) {
1310                 ssle = new SSLHandshakeException(
1311                         "Remote host terminated the handshake");
1312             } else {
1313                 ssle = new SSLProtocolException(
1314                         "Remote host terminated the connection");
1315             }
1316 
1317             if (eofe != null) {
1318                 ssle.initCause(eofe);
1319             }
1320             throw ssle;
1321         } else {
1322             // treat as if we had received a close_notify
1323             conContext.isInputCloseNotified = true;
1324             shutdownInput();
1325 
1326             return Plaintext.PLAINTEXT_NULL;
1327         }
1328     }
1329 
1330 
1331     @Override
1332     public String getPeerHost() {
1333         return peerHost;
1334     }
1335 
1336     @Override
1337     public int getPeerPort() {
1338         return getPort();
1339     }
1340 
1341     @Override
1342     public boolean useDelegatedTask() {
1343         return false;
1344     }
1345 
1346     @Override
1347     public void shutdown() throws IOException {
1348         if (!isClosed()) {
1349             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1350                 SSLLogger.fine("close the underlying socket");
1351             }
1352 
1353             try {
1354                 if (conContext.isInputCloseNotified) {
1355                     // Close the connection, no wait for more peer response.
1356                     closeSocket(false);
1357                 } else {
1358                     // Close the connection, may wait for peer close_notify.
1359                     closeSocket(true);
1360                 }
1361             } finally {
1362                 tlsIsClosed = true;
1363             }
1364         }
1365     }
1366 
1367     private void closeSocket(boolean selfInitiated) throws IOException {
1368         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1369             SSLLogger.fine("close the SSL connection " +
1370                 (selfInitiated ? "(initiative)" : "(passive)"));
1371         }
1372 
1373         if (autoClose || !isLayered()) {
1374             super.close();
1375         } else if (selfInitiated) {
1376             if (!conContext.isInboundClosed() && !isInputShutdown()) {
1377                 // wait for close_notify alert to clear input stream.
1378                 waitForClose();
1379             }
1380         }
1381     }
1382 
1383    /**
1384     * Wait for close_notify alert for a graceful closure.
1385     *
1386     * [RFC 5246] If the application protocol using TLS provides that any
1387     * data may be carried over the underlying transport after the TLS
1388     * connection is closed, the TLS implementation must receive the responding
1389     * close_notify alert before indicating to the application layer that
1390     * the TLS connection has ended.  If the application protocol will not
1391     * transfer any additional data, but will only close the underlying
1392     * transport connection, then the implementation MAY choose to close the
1393     * transport without waiting for the responding close_notify.
1394     */
1395     private void waitForClose() throws IOException {
1396         if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1397             SSLLogger.fine("wait for close_notify or alert");
1398         }
1399 
1400         while (!conContext.isInboundClosed()) {
1401             try {
1402                 Plaintext plainText = decode(null);
1403                 // discard and continue
1404                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1405                     SSLLogger.finest(
1406                         "discard plaintext while waiting for close", plainText);
1407                 }
1408             } catch (Exception e) {   // including RuntimeException
1409                 handleException(e);
1410             }
1411         }
1412     }
1413 }