1 /*
   2  * Copyright (c) 2015, 2017, 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 jdk.incubator.http;
  27 
  28 import java.io.IOException;
  29 import java.net.ProtocolException;
  30 import java.net.URI;
  31 import java.nio.ByteBuffer;
  32 import java.time.Duration;
  33 import java.util.concurrent.CompletableFuture;
  34 import java.util.concurrent.CompletionStage;
  35 
  36 /**
  37  * A WebSocket client conforming to RFC 6455.
  38  * {@Incubating}
  39  *
  40  * <p> A {@code WebSocket} provides full-duplex communication over a TCP
  41  * connection.
  42  *
  43  * <p> To create a {@code WebSocket} use a {@linkplain HttpClient#newWebSocketBuilder(
  44  * URI, Listener) builder}. Once a {@code WebSocket} is built, it's ready
  45  * to send and receive messages. When the {@code WebSocket} is no longer needed
  46  * it must be closed: a Close message must both be {@linkplain #sendClose
  47  * sent} and {@linkplain Listener#onClose(WebSocket, int, String) received}.
  48  * The {@code WebSocket} may be also closed {@linkplain #abort() abruptly}.
  49  *
  50  * <p> Once closed the {@code WebSocket} remains {@linkplain #isClosed() closed}
  51  * and cannot be reopened.
  52  *
  53  * <p> Messages of type {@code X} (where {@code X} is one of: Text, Binary,
  54  * Ping, Pong or Close) are sent and received asynchronously through the {@code
  55  * WebSocket.send{X}} and {@link WebSocket.Listener}{@code .on{X}} methods
  56  * respectively. Each method returns a {@link CompletionStage} which completes
  57  * when the operation has completed.
  58  *
  59  * <p> Note that messages (of any type) are received only if {@linkplain
  60  * #request(long) requested}.
  61  *
  62  * <p> One outstanding send operation is permitted. No further send operation
  63  * can be initiated before the previous one has completed. When sending, a
  64  * message must not be modified until the returned {@link CompletableFuture}
  65  * completes (either normally or exceptionally).
  66  *
  67  * <p> Text and Binary messages can be sent and received as a whole or in parts.
  68  * A whole message is transferred as a sequence of one or more invocations of a
  69  * corresponding method where the last invocation is identified via an
  70  * additional method argument.
  71  *
  72  * <p> If the message is contained in a {@link ByteBuffer}, bytes are considered
  73  * arranged from the {@code buffer}'s {@link ByteBuffer#position() position} to
  74  * the {@code buffer}'s {@link ByteBuffer#limit() limit}.
  75  *
  76  * <p> Unless otherwise stated, {@code null} parameter values will cause methods
  77  * and constructors to throw {@link NullPointerException}.
  78  *
  79  * @implNote This implementation's methods do not block before returning
  80  * a {@code CompletableFuture}.
  81  *
  82  * @since 9
  83  */
  84 public interface WebSocket {
  85 
  86     /**
  87      * The WebSocket Close message status code (<code>{@value}</code>),
  88      * indicating normal closure, meaning that the purpose for which the
  89      * connection was established has been fulfilled.
  90      *
  91      * @see #sendClose(int, String)
  92      * @see Listener#onClose(WebSocket, int, String)
  93      */
  94     int NORMAL_CLOSURE = 1000;
  95 
  96     /**
  97      * A builder for creating {@code WebSocket} instances.
  98      * {@Incubating}
  99      *
 100      * <p> To build a {@code WebSocket}, {@linkplain HttpClient#newWebSocketBuilder(
 101      * URI, Listener) create} a builder, configure it as required by
 102      * calling intermediate methods (the ones that return the builder itself),
 103      * then finally call {@link #buildAsync()} to get a {@link
 104      * CompletableFuture} with resulting {@code WebSocket}.
 105      *
 106      * <p> If an intermediate method has not been called, an appropriate
 107      * default value (or behavior) will be used. Unless otherwise noted, a
 108      * repeated call to an intermediate method overwrites the previous value (or
 109      * overrides the previous behaviour).
 110      *
 111      * <p> Instances of {@code Builder} are not safe for use by multiple threads
 112      * without external synchronization.
 113      *
 114      * @since 9
 115      */
 116     interface Builder {
 117 
 118         /**
 119          * Adds the given name-value pair to the list of additional headers for
 120          * the opening handshake.
 121          *
 122          * <p> Headers defined in WebSocket Protocol are not allowed to be added.
 123          *
 124          * @param name
 125          *         the header name
 126          * @param value
 127          *         the header value
 128          *
 129          * @return this builder
 130          */
 131         Builder header(String name, String value);
 132 
 133         /**
 134          * Includes a request for the given subprotocols during the opening
 135          * handshake.
 136          *
 137          * <p> Among the requested subprotocols at most one will be chosen by
 138          * the server. This subprotocol will be available from {@link
 139          * WebSocket#getSubprotocol}. Subprotocols are specified in the order of
 140          * preference.
 141          *
 142          * <p> Each of the given subprotocols must conform to the relevant
 143          * rules defined in the WebSocket Protocol.
 144          *
 145          * <p> If this method is not invoked then no subprotocols are requested.
 146          *
 147          * @param mostPreferred
 148          *         the most preferred subprotocol
 149          * @param lesserPreferred
 150          *         the lesser preferred subprotocols, with the least preferred
 151          *         at the end
 152          *
 153          * @return this builder
 154          */
 155         Builder subprotocols(String mostPreferred, String... lesserPreferred);
 156 
 157         /**
 158          * Sets a timeout for the opening handshake.
 159          *
 160          * <p> If the opening handshake does not complete within the specified
 161          * duration then the {@code CompletableFuture} returned from {@link
 162          * #buildAsync()} completes exceptionally with a {@link
 163          * HttpTimeoutException}.
 164          *
 165          * <p> If this method is not invoked then the timeout is deemed infinite.
 166          *
 167          * @param timeout
 168          *         the timeout, non-{@linkplain Duration#isNegative() negative},
 169          *         non-{@linkplain Duration#ZERO ZERO}
 170          *
 171          * @return this builder
 172          */
 173         Builder connectTimeout(Duration timeout);
 174 
 175         /**
 176          * Builds a {@code WebSocket}.
 177          *
 178          * <p> Returns a {@code CompletableFuture<WebSocket>} which completes
 179          * normally with the {@code WebSocket} when it is connected or completes
 180          * exceptionally if an error occurs.
 181          *
 182          * <p> {@code CompletableFuture} may complete exceptionally with the
 183          * following errors:
 184          * <ul>
 185          * <li> {@link IOException} -
 186          *          if an I/O error occurs
 187          * <li> {@link WebSocketHandshakeException} -
 188          *          if the opening handshake fails
 189          * <li> {@link HttpTimeoutException} -
 190          *          if the opening handshake does not complete within
 191          *          the specified {@linkplain #connectTimeout(Duration) duration}
 192          * <li> {@link InterruptedException} -
 193          *          if the operation was interrupted
 194          * <li> {@link SecurityException} -
 195          *          if a security manager is set, and the caller does not
 196          *          have a {@link java.net.URLPermission} for the WebSocket URI
 197          * <li> {@link IllegalArgumentException} -
 198          *          if any of the additional {@link #header(String, String)
 199          *          headers} are illegal;
 200          *          or if any of the WebSocket Protocol rules relevant to {@link
 201          *          #subprotocols(String, String...) subprotocols} are violated;
 202          *          or if the {@link #connectTimeout(Duration) connect timeout}
 203          *          is invalid;
 204          * </ul>
 205          *
 206          * @return a {@code CompletableFuture} with the {@code WebSocket}
 207          */
 208         CompletableFuture<WebSocket> buildAsync();
 209     }
 210 
 211     /**
 212      * A listener for events and messages on a {@code WebSocket}.
 213      * {@Incubating}
 214      *
 215      * <p> Each method of {@code Listener} corresponds to a type of event or a
 216      * type of message. The {@code WebSocket} argument of the method is the
 217      * {@code WebSocket} the event has occurred (the message has been received)
 218      * on. All methods with the same {@code WebSocket} argument are invoked in a
 219      * sequential
 220      * (and <a href="../../../java/util/concurrent/package-summary.html#MemoryVisibility">happens-before</a>)
 221      * order, one after another, possibly by different threads.
 222      *
 223      * <ul>
 224      * <li> {@link #onOpen(WebSocket) onOpen} <br>
 225      * This method is invoked first.
 226      * <li> {@link #onText(WebSocket, CharSequence, WebSocket.MessagePart)
 227      * onText}, {@link #onBinary(WebSocket, ByteBuffer, WebSocket.MessagePart)
 228      * onBinary}, {@link #onPing(WebSocket, ByteBuffer) onPing} and {@link
 229      * #onPong(WebSocket, ByteBuffer) onPong} <br>
 230      * These methods are invoked zero or more times after {@code onOpen}.
 231      * <li> {@link #onClose(WebSocket, int, String) onClose}, {@link
 232      * #onError(WebSocket, Throwable) onError} <br>
 233      * Only one of these methods is invoked, and that method is invoked last.
 234      * </ul>
 235      *
 236      * <p> Messages received by the {@code Listener} conform to the WebSocket
 237      * Protocol, otherwise {@code onError} with a {@link ProtocolException} is
 238      * invoked.
 239      *
 240      * <p> If a whole message is received, then the corresponding method
 241      * ({@code onText} or {@code onBinary}) will be invoked with {@link
 242      * WebSocket.MessagePart#WHOLE WHOLE} marker. Otherwise the method will be
 243      * invoked with {@link WebSocket.MessagePart#FIRST FIRST}, zero or more
 244      * times with {@link WebSocket.MessagePart#PART PART} and, finally, with
 245      * {@link WebSocket.MessagePart#LAST LAST} markers.
 246      *
 247      * If any of the methods above throws an exception, {@code onError} is then
 248      * invoked with the same {@code WebSocket} and this exception. Exceptions
 249      * thrown from {@code onError} or {@code onClose} are ignored.
 250      *
 251      * <p> When the method returns, the message is deemed received (in
 252      * particular, if contained in a {@code ByteBuffer buffer}, the data is
 253      * deemed received completely regardless of the result {@code
 254      * buffer.hasRemaining()} upon the method's return. After this further
 255      * messages may be received.
 256      *
 257      * <p> These invocations begin asynchronous processing which might not end
 258      * with the invocation. To provide coordination, methods of {@code Listener}
 259      * return a {@link CompletionStage CompletionStage}.
 260      * The {@code CompletionStage} signals the {@code WebSocket} that the
 261      * processing of a message has ended. For convenience, methods may return
 262      * {@code null}, which (by convention) means the same as returning an
 263      * already completed (normally) {@code CompletionStage}.
 264      * If the returned {@code CompletionStage} completes exceptionally, then
 265      * {@link #onError(WebSocket, Throwable) onError} will be invoked with the
 266      * same {@code WebSocket} and this exception.
 267      *
 268      * <p> Control of the message passes to the {@code Listener} with the
 269      * invocation of the method. Control of the message returns to the {@code
 270      * WebSocket} at the earliest of, either returning {@code null} from the
 271      * method, or the completion of the {@code CompletionStage} returned from
 272      * the method. The {@code WebSocket} does not access the message while it's
 273      * not in its control. The {@code Listener} must not access the message
 274      * after its control has been returned to the {@code WebSocket}.
 275      *
 276      * <p> A {@code WebSocket} implementation never invokes {@code Listener}'s
 277      * methods with {@code null}s as their arguments.
 278      *
 279      * @since 9
 280      */
 281     interface Listener {
 282 
 283         /**
 284          * Notifies the {@code Listener} that it is connected to the provided
 285          * {@code WebSocket}.
 286          *
 287          * <p> The {@code onOpen} method does not correspond to any message from
 288          * the WebSocket Protocol. It is a synthetic event and the first {@code
 289          * Listener}'s method to be invoked.
 290          *
 291          * <p> This method is usually used to make an initial {@linkplain
 292          * WebSocket#request(long) request} for messages.
 293          *
 294          * <p> If an exception is thrown from this method then {@link
 295          * #onError(WebSocket, Throwable) onError} will be invoked with the same
 296          * {@code WebSocket} and this exception.
 297          *
 298          * @implSpec The default implementation of this method behaves as if:
 299          *
 300          * <pre>{@code
 301          *     webSocket.request(1);
 302          * }</pre>
 303          *
 304          * @param webSocket
 305          *         the WebSocket
 306          */
 307         default void onOpen(WebSocket webSocket) { webSocket.request(1); }
 308 
 309         /**
 310          * Receives a Text message.
 311          *
 312          * <p> The {@code onText} method is invoked zero or more times between
 313          * {@code onOpen} and ({@code onClose} or {@code onError}).
 314          *
 315          * <p> This message may be a partial UTF-16 sequence. However, the
 316          * concatenation of all messages through the last will be a whole UTF-16
 317          * sequence.
 318          *
 319          * <p> If an exception is thrown from this method or the returned {@code
 320          * CompletionStage} completes exceptionally, then {@link
 321          * #onError(WebSocket, Throwable) onError} will be invoked with the same
 322          * {@code WebSocket} and this exception.
 323          *
 324          * @implSpec The default implementation of this method behaves as if:
 325          *
 326          * <pre>{@code
 327          *     webSocket.request(1);
 328          *     return null;
 329          * }</pre>
 330          *
 331          * @implNote This implementation passes only complete UTF-16 sequences
 332          * to the {@code onText} method.
 333          *
 334          * @param webSocket
 335          *         the WebSocket
 336          * @param message
 337          *         the message
 338          * @param part
 339          *         the part
 340          *
 341          * @return a {@code CompletionStage} which completes when the message
 342          * processing is done; or {@code null} if already done
 343          */
 344         default CompletionStage<?> onText(WebSocket webSocket,
 345                                           CharSequence message,
 346                                           MessagePart part) {
 347             webSocket.request(1);
 348             return null;
 349         }
 350 
 351         /**
 352          * Receives a Binary message.
 353          *
 354          * <p> The {@code onBinary} method is invoked zero or more times
 355          * between {@code onOpen} and ({@code onClose} or {@code onError}).
 356          *
 357          * <p> If an exception is thrown from this method or the returned {@code
 358          * CompletionStage} completes exceptionally, then {@link
 359          * #onError(WebSocket, Throwable) onError} will be invoked with the same
 360          * {@code WebSocket} and this exception.
 361          *
 362          * @implSpec The default implementation of this method behaves as if:
 363          *
 364          * <pre>{@code
 365          *     webSocket.request(1);
 366          *     return null;
 367          * }</pre>
 368          *
 369          * @param webSocket
 370          *         the WebSocket
 371          * @param message
 372          *         the message
 373          * @param part
 374          *         the part
 375          *
 376          * @return a {@code CompletionStage} which completes when the message
 377          * processing is done; or {@code null} if already done
 378          */
 379         default CompletionStage<?> onBinary(WebSocket webSocket,
 380                                             ByteBuffer message,
 381                                             MessagePart part) {
 382             webSocket.request(1);
 383             return null;
 384         }
 385 
 386         /**
 387          * Receives a Ping message.
 388          *
 389          * <p> A Ping message may be sent or received by either client or
 390          * server. It may serve either as a keepalive or as a means to verify
 391          * that the remote endpoint is still responsive.
 392          *
 393          * <p> The {@code WebSocket} handles Ping messages by replying with
 394          * appropriate Pong messages using a strategy of its choice, but within
 395          * the boundaries of the WebSocket Protocol. The {@code WebSocket} may
 396          * invoke {@code onPing} after handling a Ping message, before doing so
 397          * or in parallel with it. In other words no particular ordering is
 398          * guaranteed. If an error occurs while implementation handles this Ping
 399          * message, then {@code onError} will be invoked with this error. For
 400          * more details on handling Ping messages see RFC 6455 sections
 401          * <a href="https://tools.ietf.org/html/rfc6455#section-5.5.2">5.5.2. Ping</a>
 402          * and
 403          * <a href="https://tools.ietf.org/html/rfc6455#section-5.5.3">5.5.3. Pong</a>.
 404          *
 405          * <p> The message will consist of not more than {@code 125} bytes:
 406          * {@code message.remaining() <= 125}.
 407          *
 408          * <p> The {@code onPing} is invoked zero or more times in between
 409          * {@code onOpen} and ({@code onClose} or {@code onError}).
 410          *
 411          * <p> If an exception is thrown from this method or the returned {@code
 412          * CompletionStage} completes exceptionally, then {@link
 413          * #onError(WebSocket, Throwable) onError} will be invoked with this
 414          * exception.
 415          *
 416          * @implSpec The default implementation of this method behaves as if:
 417          *
 418          * <pre>{@code
 419          *     webSocket.request(1);
 420          *     return null;
 421          * }</pre>
 422          *
 423          * @param webSocket
 424          *         the WebSocket
 425          * @param message
 426          *         the message
 427          *
 428          * @return a {@code CompletionStage} which completes when the message
 429          * processing is done; or {@code null} if already done
 430          */
 431         default CompletionStage<?> onPing(WebSocket webSocket,
 432                                           ByteBuffer message) {
 433             webSocket.request(1);
 434             return null;
 435         }
 436 
 437         /**
 438          * Receives a Pong message.
 439          *
 440          * <p> A Pong message may be unsolicited or may be received in response
 441          * to a previously sent Ping. In the latter case, the contents of the
 442          * Pong is identical to the originating Ping.
 443          *
 444          * <p> The message will consist of not more than {@code 125} bytes:
 445          * {@code message.remaining() <= 125}.
 446          *
 447          * <p> The {@code onPong} method is invoked zero or more times in
 448          * between {@code onOpen} and ({@code onClose} or {@code onError}).
 449          *
 450          * <p> If an exception is thrown from this method or the returned {@code
 451          * CompletionStage} completes exceptionally, then {@link
 452          * #onError(WebSocket, Throwable) onError} will be invoked with this
 453          * exception.
 454          *
 455          * @implSpec The default implementation of this method behaves as if:
 456          *
 457          * <pre>{@code
 458          *     webSocket.request(1);
 459          *     return null;
 460          * }</pre>
 461          *
 462          * @param webSocket
 463          *         the WebSocket
 464          * @param message
 465          *         the message
 466          *
 467          * @return a {@code CompletionStage} which completes when the message
 468          * processing is done; or {@code null} if already done
 469          */
 470         default CompletionStage<?> onPong(WebSocket webSocket,
 471                                           ByteBuffer message) {
 472             webSocket.request(1);
 473             return null;
 474         }
 475 
 476         /**
 477          * Receives a Close message.
 478          *
 479          * <p> A Close message consists of a status code and a reason for
 480          * closing. The status code is an integer in the range {@code 1000 <=
 481          * code <= 65535}. The {@code reason} is a short string that has an
 482          * UTF-8 representation not longer than {@code 123} bytes. For more
 483          * details on Close message, status codes and reason see RFC 6455 sections
 484          * <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1">5.5.1. Close</a>
 485          * and
 486          * <a href="https://tools.ietf.org/html/rfc6455#section-7.4">7.4. Status Codes</a>.
 487          *
 488          * <p> After the returned {@code CompletionStage} has completed
 489          * (normally or exceptionally), the {@code WebSocket} completes the
 490          * closing handshake by replying with an appropriate Close message.
 491          *
 492          * <p> This implementation replies with a Close message that has the
 493          * same code this message has and an empty reason.
 494          *
 495          * <p> {@code onClose} is the last invocation on the {@code Listener}.
 496          * It is invoked at most once, but after {@code onOpen}. If an exception
 497          * is thrown from this method, it is ignored.
 498          *
 499          * <p> The {@code WebSocket} will close at the earliest of completion of
 500          * the returned {@code CompletionStage} or sending a Close message. In
 501          * particular, if a Close message has been {@linkplain WebSocket#sendClose
 502          * sent} before, then this invocation completes the closing handshake
 503          * and by the time this method is invoked, the {@code WebSocket} will
 504          * have been closed.
 505          *
 506          * @implSpec The default implementation of this method behaves as if:
 507          *
 508          * <pre>{@code
 509          *     return null;
 510          * }</pre>
 511          *
 512          * @param webSocket
 513          *         the WebSocket
 514          * @param statusCode
 515          *         the status code
 516          * @param reason
 517          *         the reason
 518          *
 519          * @return a {@code CompletionStage} which completes when the {@code
 520          * WebSocket} can be closed; or {@code null} if it can be closed immediately
 521          *
 522          * @see #NORMAL_CLOSURE
 523          */
 524         default CompletionStage<?> onClose(WebSocket webSocket,
 525                                            int statusCode,
 526                                            String reason) {
 527             return null;
 528         }
 529 
 530         /**
 531          * Notifies an I/O or protocol error has occurred.
 532          *
 533          * <p> The {@code onError} method does not correspond to any message
 534          * from the WebSocket Protocol. It is a synthetic event and the last
 535          * {@code Listener}'s method to be invoked. It is invoked at most once
 536          * but after {@code onOpen}. If an exception is thrown from this method,
 537          * it is ignored.
 538          *
 539          * <p> Note that the WebSocket Protocol requires <i>some</i> errors
 540          * occur in the incoming destination must be fatal to the connection. In
 541          * such cases the implementation takes care of <i>Failing the WebSocket
 542          * Connection</i>: by the time {@code onError} is invoked, the {@code
 543          * WebSocket} will have been closed. Any outstanding or subsequent send
 544          * operation will complete exceptionally with an {@code IOException}.
 545          * For more details on Failing the WebSocket Connection see RFC 6455
 546          * section <a href="https://tools.ietf.org/html/rfc6455#section-7.1.7">7.1.7. Fail the WebSocket Connection</a>.
 547          *
 548          * @apiNote Errors associated with sending messages are reported to the
 549          * {@code CompletableFuture}s {@code sendX} methods return, rather than
 550          * to this this method.
 551          *
 552          * @implSpec The default implementation of this method does nothing.
 553          *
 554          * @param webSocket
 555          *         the WebSocket
 556          * @param error
 557          *         the error
 558          */
 559         default void onError(WebSocket webSocket, Throwable error) { }
 560     }
 561 
 562     /**
 563      * A marker used by {@link WebSocket.Listener} in cases where a partial
 564      * message may be received.
 565      * {@Incubating}
 566      *
 567      * @see Listener#onText(WebSocket, CharSequence, MessagePart)
 568      * @see Listener#onBinary(WebSocket, ByteBuffer, MessagePart)
 569      *
 570      * @since 9
 571      */
 572     enum MessagePart {
 573 
 574         /**
 575          * The first part of a message in a sequence.
 576          */
 577         FIRST,
 578 
 579         /**
 580          * A middle part of a message in a sequence.
 581          */
 582         PART,
 583 
 584         /**
 585          * The last part of a message in a sequence.
 586          */
 587         LAST,
 588 
 589         /**
 590          * A whole message consisting of a single part.
 591          */
 592         WHOLE
 593     }
 594 
 595     /**
 596      * Sends a Text message with characters from the given {@code CharSequence}.
 597      *
 598      * <p> Returns a {@code CompletableFuture<WebSocket>} which completes
 599      * normally when the message has been sent or completes exceptionally if an
 600      * error occurs.
 601      *
 602      * <p> The {@code CharSequence} must not be modified until the returned
 603      * {@code CompletableFuture} completes (either normally or exceptionally).
 604      *
 605      * <p> The returned {@code CompletableFuture} can complete exceptionally
 606      * with:
 607      * <ul>
 608      * <li> {@link IllegalArgumentException} -
 609      *          if {@code message} is a malformed UTF-16 sequence
 610      * <li> {@link IllegalStateException} -
 611      *          if the {@code WebSocket} is closed;
 612      *          or if a Close message has been sent;
 613      *          or if there is an outstanding send operation;
 614      *          or if a previous Binary message was sent with {@code isLast == false}
 615      * <li> {@link IOException} -
 616      *          if an I/O error occurs during this operation;
 617      *          or if the {@code WebSocket} has been closed due to an error;
 618      * </ul>
 619      *
 620      * @implNote This implementation does not accept partial UTF-16 sequences.
 621      * In case such a sequence is passed, a returned {@code CompletableFuture}
 622      * completes exceptionally with {@code IOException}.
 623      *
 624      * @param message
 625      *         the message
 626      * @param isLast
 627      *         {@code true} if this is the last part of the message,
 628      *         {@code false} otherwise
 629      *
 630      * @return a {@code CompletableFuture} with this {@code WebSocket}
 631      */
 632     CompletableFuture<WebSocket> sendText(CharSequence message, boolean isLast);
 633 
 634     /**
 635      * Sends a Binary message with bytes from the given {@code ByteBuffer}.
 636      *
 637      * <p> Returns a {@code CompletableFuture<WebSocket>} which completes
 638      * normally when the message has been sent or completes exceptionally if an
 639      * error occurs.
 640      *
 641      * <p> The returned {@code CompletableFuture} can complete exceptionally
 642      * with:
 643      * <ul>
 644      * <li> {@link IllegalStateException} -
 645      *          if the {@code WebSocket} is closed;
 646      *          or if a Close message has been sent;
 647      *          or if there is an outstanding send operation;
 648      *          or if a previous Text message was sent with {@code isLast == false}
 649      * <li> {@link IOException} -
 650      *          if an I/O error occurs during this operation;
 651      *          or if the {@code WebSocket} has been closed due to an error
 652      * </ul>
 653      *
 654      * @param message
 655      *         the message
 656      * @param isLast
 657      *         {@code true} if this is the last part of the message,
 658      *         {@code false} otherwise
 659      *
 660      * @return a {@code CompletableFuture} with this {@code WebSocket}
 661      */
 662     CompletableFuture<WebSocket> sendBinary(ByteBuffer message, boolean isLast);
 663 
 664     /**
 665      * Sends a Ping message with bytes from the given ByteBuffer.
 666      *
 667      * <p> Returns a {@code CompletableFuture<WebSocket>} which completes
 668      * normally when the message has been sent or completes exceptionally if an
 669      * error occurs.
 670      *
 671      * <p> A Ping message may be sent or received by either client or server.
 672      * It may serve either as a keepalive or as a means to verify that the
 673      * remote endpoint is still responsive.
 674      *
 675      * <p> The message must consist of not more than {@code 125} bytes: {@code
 676      * message.remaining() <= 125}.
 677      *
 678      * <p> The returned {@code CompletableFuture} can complete exceptionally
 679      * with:
 680      * <ul>
 681      * <li> {@link IllegalArgumentException} -
 682      *          if {@code message.remaining() > 125}
 683      * <li> {@link IllegalStateException} -
 684      *          if the {@code WebSocket} is closed;
 685      *          or if a Close message has been sent;
 686      *          or if there is an outstanding send operation
 687      * <li> {@link IOException} -
 688      *          if an I/O error occurs during this operation;
 689      *          or if the {@code WebSocket} has been closed due to an error
 690      * </ul>
 691      *
 692      * @param message
 693      *         the message
 694      *
 695      * @return a {@code CompletableFuture} with this {@code WebSocket}
 696      */
 697     CompletableFuture<WebSocket> sendPing(ByteBuffer message);
 698 
 699     /**
 700      * Sends a Pong message with bytes from the given ByteBuffer.
 701      *
 702      * <p> Returns a {@code CompletableFuture<WebSocket>} which completes
 703      * normally when the message has been sent or completes exceptionally if an
 704      * error occurs.
 705      *
 706      * <p> A Pong message may be unsolicited or may be sent in response to a
 707      * previously received Ping. In latter case the contents of the Pong must be
 708      * identical to the originating Ping.
 709      *
 710      * <p> The message must consist of not more than {@code 125} bytes: {@code
 711      * message.remaining() <= 125}.
 712      *
 713      * <p> The returned {@code CompletableFuture} can complete exceptionally
 714      * with:
 715      * <ul>
 716      * <li> {@link IllegalArgumentException} -
 717      *          if {@code message.remaining() > 125}
 718      * <li> {@link IllegalStateException} -
 719      *          if the {@code WebSocket} is closed;
 720      *          or if a Close message has been sent;
 721      *          or if there is an outstanding send operation
 722      * <li> {@link IOException} -
 723      *          if an I/O error occurs during this operation;
 724      *          or if the {@code WebSocket} has been closed due to an error
 725      * </ul>
 726      *
 727      * @param message
 728      *         the message
 729      *
 730      * @return a {@code CompletableFuture} with this {@code WebSocket}
 731      */
 732     CompletableFuture<WebSocket> sendPong(ByteBuffer message);
 733 
 734     /**
 735      * Sends a Close message with the given status code and the reason.
 736      *
 737      * <p> When this method has been invoked, no further messages can be sent.
 738      *
 739      * <p> The {@code statusCode} is an integer in the range {@code 1000 <= code
 740      * <= 4999}. However, not all status codes may be legal in some
 741      * implementations. Regardless of an implementation,
 742      * <code>{@value jdk.incubator.http.WebSocket#NORMAL_CLOSURE}</code>
 743      * is always legal and {@code 1002}, {@code 1003}, {@code 1005}, {@code
 744      * 1006}, {@code 1007}, {@code 1009}, {@code 1010}, {@code 1012}, {@code
 745      * 1013} and {@code 1015} are always illegal codes.
 746      *
 747      * <p> The {@code reason} is a short string that must have an UTF-8
 748      * representation not longer than {@code 123} bytes. For more details on
 749      * Close message, status codes and reason see RFC 6455 sections
 750      * <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1">5.5.1. Close</a>
 751      * and
 752      * <a href="https://tools.ietf.org/html/rfc6455#section-7.4">7.4. Status Codes</a>.
 753      *
 754      * <p> The method returns a {@code CompletableFuture<WebSocket>} which
 755      * completes normally when the message has been sent or completes
 756      * exceptionally if an error occurs.
 757      *
 758      * <p> The returned {@code CompletableFuture} can complete exceptionally
 759      * with:
 760      * <ul>
 761      * <li> {@link IllegalArgumentException} -
 762      *          if the {@code statusCode} has an illegal value;
 763      *          or if {@code reason} doesn't have an UTF-8 representation of
 764      *          length {@code <= 123}
 765      * <li> {@link IOException} -
 766      *          if an I/O error occurs during this operation;
 767      *          or the {@code WebSocket} has been closed due to an error
 768      * </ul>
 769      *
 770      * <p> If this method has already been invoked or the {@code WebSocket} is
 771      * closed, then subsequent invocations of this method have no effect and the
 772      * returned {@code CompletableFuture} completes normally.
 773      *
 774      * <p> If a Close message has been {@linkplain Listener#onClose(WebSocket,
 775      * int, String) received} before, then this invocation completes the closing
 776      * handshake and by the time the returned {@code CompletableFuture}
 777      * completes, the {@code WebSocket} will have been closed.
 778      *
 779      * @param statusCode
 780      *         the status code
 781      * @param reason
 782      *         the reason
 783      *
 784      * @return a {@code CompletableFuture} with this {@code WebSocket}
 785      */
 786     CompletableFuture<WebSocket> sendClose(int statusCode, String reason);
 787 
 788     /**
 789      * Allows {@code n} more messages to be received by the {@link Listener
 790      * Listener}.
 791      *
 792      * <p> The actual number of received messages might be fewer if a Close
 793      * message is received, the {@code WebSocket} closes or an error occurs.
 794      *
 795      * <p> A {@code WebSocket} that has just been built, hasn't requested
 796      * anything yet. Usually the initial request for messages is made in {@link
 797      * Listener#onOpen(jdk.incubator.http.WebSocket) Listener.onOpen}.
 798      *
 799      * <p> If the {@code WebSocket} is closed then invoking this method has no
 800      * effect.
 801      *
 802      * @implNote This implementation does not distinguish between partial and
 803      * whole messages, because it's not known beforehand how a message will be
 804      * received.
 805      *
 806      * <p> If a server sends more messages than requested, this implementation
 807      * queues up these messages on the TCP connection and may eventually force
 808      * the sender to stop sending through TCP flow control.
 809      *
 810      * @param n
 811      *         the number of messages
 812      *
 813      * @throws IllegalArgumentException
 814      *         if {@code n < 0}
 815      */
 816     void request(long n);
 817 
 818     /**
 819      * Returns a {@linkplain Builder#subprotocols(String, String...) subprotocol}
 820      * which has been chosen for this {@code WebSocket}.
 821      *
 822      * @return a subprotocol, or an empty {@code String} if there is none
 823      */
 824     String getSubprotocol();
 825 
 826     /**
 827      * Tells whether the {@code WebSocket} is closed.
 828      *
 829      * <p> When a {@code WebSocket} is closed no further messages can be sent or
 830      * received.
 831      *
 832      * @return {@code true} if the {@code WebSocket} is closed,
 833      *         {@code false} otherwise
 834      */
 835     boolean isClosed();
 836 
 837     /**
 838      * Closes the {@code WebSocket} abruptly.
 839      *
 840      * <p> This method may be invoked at any time. This method closes the
 841      * underlying TCP connection and puts the {@code WebSocket} into a closed
 842      * state.
 843      *
 844      * <p> As the result {@link Listener#onClose(WebSocket, int, String)
 845      * Listener.onClose} will be invoked unless either {@code onClose} or {@link
 846      * Listener#onError(WebSocket, Throwable) onError} has been invoked before.
 847      * In which case no additional invocation will happen.
 848      *
 849      * <p> If the {@code WebSocket} is already closed then invoking this method
 850      * has no effect.
 851      *
 852      * @throws IOException
 853      *         if an I/O error occurs
 854      */
 855     void abort() throws IOException;
 856 }