Preliminary RFR JDK-8159053: Improve onPing/onClose behavior

Roger Riggs Roger.Riggs at Oracle.com
Wed Jun 22 17:03:28 UTC 2016


Hi Pavel,

in general, this treatment is fine, some comments below,


On 6/22/2016 8:39 AM, Pavel Rappo wrote:
> Hi,
>
> Here's the updated wording. Could you please have a look at it once again so we
> fully agree on it?
>
> What has changed?
>
> 1. "WebSocket implementation"/"WebSocket connection" -> {@code WebSocket}
> 2. "Automatically" added to make it clear no user actions needed
I think I would have attributed the action to the implementation instead 
of 'automatically'
> 3. Fixed typos mentioned by Chris.
> 4. Added "@see" cross-references between both versions of sendClose()
>
> *. Please notice the difference between range of status codes accepted in
> `sendClose` and passed to `onClose`.
> So basically WebSocket will allow to receive status codes up to 65535
> (inclusive), but will not allow to send them if they are greater than 4999.
>
> The reason I'm proposing this is that (in contrast to [0, 999]) RFC 6455 does
> not actually contain explicit prohibition for using codes from the range [5000, 65535]:
>
> https://tools.ietf.org/html/rfc6455#section-7.4.2
>
> Some might say it's an undefined behaviour. For example, Autobahn|Testsuite sees
> it as such:
>
> http://autobahn.ws/testsuite/reports_20131013/clients/ie11_preview_case_7_13_1.html
> http://autobahn.ws/testsuite/reports_20131013/clients/ie11_preview_case_7_13_2.html
>
> I think in this case it would be fine to rely on famous "Robustness principle"
> an allow such an asymmetry:
>
>      ...be conservative in what you do, be liberal in what you accept from others
>      
> And since RFC 6455 says WebSocket SHOULD echo back the received close code:
>
>     If an endpoint receives a Close frame and did not previously send a
>     Close frame, the endpoint MUST send a Close frame in response.  (When
>     sending a Close frame in response, the endpoint typically echos the
>     status code it received.)  It SHOULD do so as soon as practical.
>
> WebSocket should normally send back the same code it received. Even if it's
> outside the "normal range": [1000, 4999]
>
> What would you say? Thanks.
>
> --------------------------------------------------------------------------------
>
> /**
>   * Receives a Close message.
>   *
>   * <p> Once a Close message is received, the server will not send any
>   * more messages.
>   *
>   * <p> When a Close message has been received, the WebSocket Protocol
>   * mandates it is handled in a certain way.
'a certain way' seems odd in a specification.  Instead, perhaps refer to 
the RFC as you have cited below,
perhaps just move the reference up.

  <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1">Close</a>
  * and
  * <a href="https://tools.ietf.org/html/rfc6455#section-7.4">Status Codes</a>.

>   *
>   * <p> After a Close message has been received, the {@code WebSocket}
>   * will close automatically.However, the client may finish sending the
"will be closed at the earliest of..."
>   * current sequence of message parts, if any. To facilitate this, the * 
> {@code WebSocket} will only attempt to close at the earliest of,
>   * either the completion of the returned {@code CompletionStage} or the
>   * last part of the current message has been sent.
>   *
>   * <p> A Close message consists of a status code and a reason for
>   * closing. The status code is an integer in the range {@code 1000 <=
>   * code <= 65535}. The {@code reason} is a short string that has an
>   * UTF-8 representation not longer than {@code 123} bytes.For more * details on Close message, status codes and reason see * <a 
> href="https://tools.ietf.org/html/rfc6455#section-5.5.1">Close</a> * 
> and * <a href="https://tools.ietf.org/html/rfc6455#section-7.4">Status 
> Codes</a>.
>   *
>   * <p> {@code onClose} is the last invocation on the {@code Listener}.
>   * It is invoked at most once, but after {@code onOpen}. If an exception
>   * is thrown from this method, it is ignored.
>   *
>   * @implSpec The default implementation behaves as if:
>   *
>   * <pre>{@code
>   **return CompletableFuture.completedStage(null);*
Should this match the default code below?
>   * }</pre>
>   *
>   * @param webSocket
>   *         the WebSocket
>   * @param statusCode
>   *         the status code
>   * @param reason
>   *         the reason
>   *
>   * @return a CompletionStage that when completed will trigger closing of
>   * the WebSocket
>   */
> default CompletionStage<?> onClose(WebSocket webSocket,
>                                     int statusCode,
>                                     String reason) {
>      return null;
> }
>
> /**
>   * Sends a Close message with the given status code and the reason.
>   *
>   * <p> Returns a {@code CompletableFuture<WebSocket>} which completes
>   * normally when the message has been sent or completes exceptionally if an
>   * error occurs.
>   *
>   * <p> The {@code statusCode} is an integer in the range {@code 1000 <= code
>   * <= 4999}, except for {@code 1004}, {@code 1005}, {@code 1006} and {@code
>   * 1015}*and some others *that can be only set by the {@code WebSocket}.
"and some others" is too vague for a specification.  It should be 
possible to test every possible value
as being allowed, indeterminate, or illegal.
>   * The {@code reason} is a short string that must have an UTF-8
>   * representation not longer than {@code 123} bytes. For more details on
>   * Close message, status codes and reason see
>   * <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1">Close</a>
>   * and
>   * <a href="https://tools.ietf.org/html/rfc6455#section-7.4">Status Codes</a>.
>   *
>   * <p> If a Close message has been already sent or the {@code WebSocket} is
>   * closed, then invoking this method has no effect and returned {@code
>   * CompletableFuture} completes normally.
>   *
>   * <p> The returned {@code CompletableFuture} can complete exceptionally
>   * with:
>   * <ul>
>   * <li> {@link IOException}
>   *          if an I/O error occurs during this operation
>   * </ul>
>   *
>   * @param statusCode
>   *         the status code
>   * @param reason
>   *         the reason
>   *
>   * @return a CompletableFuture with this WebSocket
>   *
>   * @throws IllegalArgumentException
>   *         if the {@code statusCode} has an illegal value, or
>   *         {@code reason} doesn't have an UTF-8 representation not longer
>   *         than {@code 123} bytes
>   *
>   * @see #sendClose()
>   */
> CompletableFuture<WebSocket> sendClose(int statusCode, String reason);
>
> /**
>   * Receives a Ping message.
>   *
>   * <p> A Ping message may be sent or received by either client or
>   * server. It may serve either as a keepalive or as a means to verify
>   * that the remote endpoint is still responsive.
>   *
>   * <p> When a Ping message has been received, the WebSocket Protocol
>   * mandates it is handled in a certain way.
'in a certain way' is vague... replace with a summary description and a 
reference to the RFC sections
as below.
>   *
>   * <p> {@code WebSocket} handles a Ping message automatically using a
>   * strategy of its choice, but within the boundaries of the WebSocket
>   * Protocol. It may call this method to notify the {@code Listener}
>   * after handling the Ping message or before doing so. In other words no
>   * particular ordering is guaranteed. If an error occurs while
>   * implementation handles this Ping message, then {@code onError} will
>   * be invoked with this error. For more details on handling Ping
>   * messages see
>   * <a href="https://tools.ietf.org/html/rfc6455#section-5.5.2">Ping</a>
>   * and
>   * <a href="https://tools.ietf.org/html/rfc6455#section-5.5.3">Pong</a>.
>   *
>   * <p> The message will consist of not more than {@code 125} bytes:
>   * {@code message.remaining() <= 125}.
>   *
>   * <p> The {@code onPing} is invoked zero or more times in between
>   * {@code onOpen} and ({@code onClose} or {@code onError}).
>   *
>   * <p> If an exception is thrown from this method or the returned {@code
>   * CompletionStage} completes exceptionally, then {@link
>   * #onError(WebSocket, Throwable) onError} will be invoked with this
>   * exception.
>   *
>   * @implSpec The default implementation behaves as if:
>   *
>   * <pre>{@code
>   *     webSocket.request(1);
> ** return CompletableFuture.completedStage(null);*
This differs from the code below that returns null.  Pick one.
>   * }</pre>
>   *
>   * @param webSocket
>   *         the WebSocket
>   * @param message
>   *         the message
>   *
>   * @return a CompletionStage that completes when the message processing
>   * is done; or {@code null} if already done
>   */
> default CompletionStage<?> onPing(WebSocket webSocket,
>                                    ByteBuffer message) {
>      webSocket.request(1);
>      return null;
> }
>
>
>



More information about the net-dev mailing list