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