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