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