Subject: [hybi] Testsuite update case 7.1.5

From: "Arman Djusupov" <[email-masked]>
Date: Wed, 2 Nov 2011 11:55:40 +0200

Hello list, hello Tobias,

I would like to discuss Autobahn's 7.1.5 test case:

Case Description
=================================================

Send message fragment1 followed by close then fragment

Case Expectation

Clean close with normal code.

Case Outcome

The close code should have been 1000 or empty

=================================================

Since the close frame is received prior to the final frame of the inbound message, our implementation considers that the partially received message is being interrupted and that this is an abnormal closure, so it sends close code 1006. I consider this as being the correct behavior since the message should be terminated with a final frame in order to consider the closure as being graceful. The WebSocket implementation should not send any frame after the close frame, so the sender behavior is also invalid (since in this test case sender does send a frame after the close frame).

Is there any reason why the close frame with status code 1000-OK must be echoed back in order to receive a "Pass" in this particular test? The specification states "(When sending a Close frame in response the endpoint  *typically* echos the status code it received.)". The term "typically" in this context, does not mean MUST or even SHOULD. In given circumstances when the receiver encounters an error condition due to a partially received message, I believe the receiver SHOULD send the status code 1006  to indicate that the connection wasn't closed gracefully on the receiving side.

With best regards,
Arman

---

From: Peter Thorson <[email-masked]>
Date: Wed, 2 Nov 2011 06:32:30 -0500

> I would like to discuss Autobahn's 7.1.5 test case:

Hi Arman,

I'll take this question as I wrote most of the 7.x tests. 

There is nothing in the websocket spec that indicates that closing the connection while a message has been partially sent should be considered a protocol violation. Question for the list: Should there be?

In my opinion... The sender of a close frame will know that it has a message in flight and can choose to finish sending that or close immediately. As such, I would interpret getting a close frame in the middle of a fragmented message as a deliberate act on the part of the sender (as opposed to an unrelated interruption) that closing now is more important than finishing the message. As such if that close frame offers a normal close I think the correct thing to do is to cancel the partial message and close normally.

Regarding the fact that and endpoint must not send frames after a close.. This test violates that rule in order to test the expected response behavior, which the spec says is to ignore all bytes after a close frame. I am interpreting that to mean that stray bytes after a close should be ignored and not considered a protocol error.

Regarding sending 1006. The spec specifically says that codes 1005 and 1006 are NOT to be used on the wire in any case. A 1006 is intended to be delivered to the end application in the case where the connection was terminated with no closing handshake at all. If there were language in the spec preventing closes in the middle of fragmented messages I would return a 1002/protocol error.

Best,

Peter

---

From: Iñaki Baz Castillo <[email-masked]>
Date: Wed, 2 Nov 2011 12:40:16 +0100

> There is nothing in the websocket spec that indicates that closing the connection while a message has been partially sent should be considered a protocol violation. Question for the list: Should th…

IMHO not. I see a use case:

- I'm sending to the server a ISO image (800MB) by splitting the file
into multiple WS frames. It would take 120 minutes to upload the
entire WS message.

- After 5 minutes I must go out and close the cmoputer, so I press
"logout" in the web and the WS connection is closed by me (because I
must go out right now).

This is not a protocol error at all. This is a valid use case. Upon
receipt of the close frame, the server must discard all the partial
frames received, of course. But that is not an error.

So IMHO test 7.1.5 is correct (and this is what I implement).

Regards.

-- 
Iñaki Baz Castillo
<[email-masked]>

---

From: "Arman Djusupov" <[email-masked]>
Date: Wed, 2 Nov 2011 15:25:34 +0200

> > There is nothing in the websocket spec that indicates that closing 
> > the
> connection while a message has been partially sent should be 
> considered a protocol violation. Question for the list: Should there be?
> 
 
Understood. However we are discussing a fragmented message, where the message might have already started being processed and the server might have allocated resources and threads for processing the message. This is the process that is getting interrupted by a close frame.

Imagine the content being sent to be an 800MB XML dataset which is getting committed to the database. If such a message gets interrupt then the server will have an error condition that requires it to roll back the entire transaction. The server should reply with a status code that clearly indicates that this connection closure was not graceful so that the client realizes that the connection closure caused problems to the server side. In my view you cannot refer to this as being a "graceful" closure when the server has to recover from the error state.

A graceful closure should be mutually graceful, otherwise it isn't graceful. If the connection closure causes small/big problems (e.g. messages discarded) to the server, the client needs to be informed accordingly.
 
> frames received, of course. But that is not an error.

The server cannot discard something easily, if processing of the message has already started, that's the difference between streamed and buffered processing.

> From: Peter Thorson [mailto:[email-masked]] Regarding sending 
> 1006. The spec specifically says that codes 1005 and 1006 are NOT to 
> be used on the wire in any case. A 1006 is intended to be delivered to 
> the end application in the case where the connection was terminated 
> with no closing handshake at all. If there were language in the spec 
> preventing closes in the middle of fragmented messages I would return 
> a 1002/protocol error.

You are correct, that's my mistake. I could change this to 1002 but this doesn't describe this error condition either, 1002 means that the server drops connection due to client protocol violation, but this is not the actual case during this test since the server closes the connection because the client requested it to do so, but at the same time it should inform the client that the closure was not graceful.

1000 -  states

      1000 indicates a normal closure, meaning whatever purpose the
      connection was established for has been fulfilled.

So in the case described above the connection was established in order to commit the 800MB dataset into the database. But due to some circumstances the connection is being closed down before the transfer is complete. I do believe that we do need to inform the client about what happened -- if the server had no problem then that's ok, but if the server does not consider the closure as being graceful then the client does need to be informed of this.

I don't have any technical problem changing my implementation to send code 1000 in this case or to send no error code at all. But it is my strong opinion that this would be wrong.

With best regards,
Arman

---

From: Iñaki Baz Castillo <[email-masked]>
Date: Wed, 2 Nov 2011 15:06:59 +0100

> A graceful closure should be mutually graceful, otherwise it isn't graceful. If the connection closure causes small/big problems (e.g. messages discarded) to the server, the client needs to be info…

The example you are describing it just up to the application on top of
WebSocket. WS frames are not (MUST not be) aware of the semantic of
the carried data. So from the point of view of WS there is no
difference when carrying a big ISO file or a big XML file.

In the case of the big XML which is getting committed to the database
by the server: if the client interrupts it the server must, indeed,
free allocated resources and so, but that is up to the server
application. This is not "anormal" so there should be no error
indication at transport level (and the transport level are the WS
frames).

This is the same as if you open a TCP connection with a server, send a
HTTP GET to download a very big file and interrupt it from client side
by sending a TCP disconnection. The TCP response of the server must be
the correct one, it does not matter whether the server was doing
something (or not) with the carried data.

> The server cannot discard something easily, if processing of the message has already started, that's the difference between streamed and buffered processing.

But that's a problem at application level, not a transport level, and
WebSocket close frames are part of the transport layer.

> So in the case described above the connection was established in order to commit the 800MB dataset into the database. But due to some circumstances the connection is being closed down before the tr…

The closure is graceful at WS level since the client sent a valid and
correct close frame.

> I don't have any technical problem changing my implementation to send code 1000 in this case or to send no error code at all. But it is my strong opinion that this would be wrong.

IMHO it's 100% correct as justified in this mail :)

---

From: Peter Thorson <[email-masked]>
Date: Wed, 2 Nov 2011 09:34:48 -0500

> I don't have any technical problem changing my implementation to send code 1000 in this case or to send no error code at all. But it is my strong opinion that this would be wrong.

The way the websocket spec is written today, from the point of view of the websocket layer the close is clean. The uncleanness that you are describing is from the application's point of view. If the client and server want more detailed application level closing they should negotiate (either implicitly or via a sub protocol) some 3xxx or 4xxx close codes for their needs. 

Ex: 
4000: please cancel the transaction and rollback the db
4001: I am leaving please save my partial transfer so we can resume later

In is case the server echoing back that code will confirm to the client that they agree on the reason and state of the connection close.

---

From: "Arman Djusupov" <[email-masked]>
Date: Thu, 3 Nov 2011 09:53:50 +0200

> From: Iñaki Baz Castillo [mailto:[email-masked]] This is the same as if 
> you open a TCP connection with a server, send a HTTP GET to download a 
> very big file and interrupt it from client side by sending a TCP 
> disconnection. The TCP response of the server must be the correct one, 
> it does not matter whether the server was doing something (or not) 
> with the carried data.

In the case above the TCP disconnection will not be graceful and a socket error will be reported (either on both or on one of the sides) and the connection will be closed -- but it won't be closed gracefully.

A better example would be when the client sends an HTTP POST request with chunked transfer encoding and drops the connection without sending a final chunk, that would definitely be an error and the HTTP server would log it. Similarly, having no final frame is an error with a WebSocket fragmented message. This is similar to a network error, it is an "unclean" situation which is abnormal and not covered by the spec.

The original idea behind the close frame was to ensure that the remote side has received the complete data before the closure of the TCP connection. But what is the point of sending the close frame when the client deliberately sends an incomplete message and what the point of replying with a close frame when the server knows that the data received is incomplete - may be terminating the connection would be more proper?

With best regards,
Arman

---

From: Iñaki Baz Castillo <[email-masked]>
Date: Thu, 3 Nov 2011 10:19:11 +0100

> In the case above the TCP disconnection will not be graceful and a socket error will be reported (either on both or on one of the sides) and the connection will be closed -- but it won't be closed…

Why is it not graceful? Tthe TCP layer is not aware of how much data
the HTTP application layer wants to send.

> The original idea behind the close frame was to ensure that the remote side has received the complete data before the closure of the TCP connection. But what is the point of sending the close frame…

I understand your point, and given your rationale I could agree.

-- 
Iñaki Baz Castillo
<[email-masked]>

---

From: "Arman Djusupov" <[email-masked]>
Date: Thu, 3 Nov 2011 15:21:09 +0200

> From: Iñaki Baz Castillo [mailto:[email-masked]] Why is it not 
> graceful? Tthe TCP layer is not aware of how much data the HTTP 
> application layer wants to send.

Yes, TCP is not aware about how much data an application plans to exchange. But an application is required to follow specific steps in order to ensure that a TCP connection is closed gracefully, without data loss or errors from the socket API. From the perspective of the socket API the closure is graceful when both sides stop writing, call shutdown(), then recv() returns 0 and finally the socket handles are closed. If there were no errors while performing those steps, then this is a reasonable indication that no data was discarded and both sides are closing the connection on mutual agreement. 

However, exactly because the TCP layer is not entirely reliable on that matter, and may fail to detect problems when closing a connection, there is the additional WebSocket closing handshake that we put into the protocol in order to provide an additional assurance that the connection is being closed with no data being discarded.

That's why I believe that exchanging code 1000-OK, when data is being deliberately left incomplete and knowingly discarded, is wrong.

> I understand your point, and given your rationale I could agree.

Thanks!

With best regards,
Arman

---

From: Tobias Oberstein <[email-masked]>
Date: Thu, 3 Nov 2011 13:44:43 -0700

> However, exactly because the TCP layer is not entirely reliable on that
> matter, and may fail to detect problems when closing a connection, there is
> the additional WebSocket closing handshake that we put into the protocol in
> order to provide an additional assurance that the connection is being closed
> with no data being discarded.
> 
> That's why I believe that exchanging code 1000-OK, when data is being
> deliberately left incomplete and knowingly discarded, is wrong.

I would argue: all frames have been fully received/processed, so no data
on the transport layer was lost or stuck in the TCP stack. The closing HS
was clean.

Thus, 1000 or no close code is appropriate from a WS transport point of view.

Any other 1xxx or a brutal drop TCP is not appropriate.

===

Now, interestingly, the spec says:

1000 indicates a normal closure, >> meaning whatever purpose the
      connection was established for has been fulfilled. <<

Was the "purpose fulfilled" when the connection was closed cleanly
in the middle of a fragmented message?

Hmm;)

But in any case I can't see a more appropriate one from the 1xxx.

===

I can see that data might be "incomplete" from an application point of view.

The question then is: if 3xxx/4xxx would be ok in this case also, and if so,
under what circumstances?

The spec says about 3xxx/4xxx: "The interpretation of these codes is undefined
by this protocol."

It does not make efforts to be more explicit, like i.e.

A close initator may use a 3xxx instead of 1000 anywhere where 1000 was allowed
if and only if a subprotocol was negotiated that defines the meaning of 3xxx.

Or: 1007 = invalid utf8/payload

Now, lets say a subprotocol A defines 3003 = "invalid utf8: surrogate pair"

On a connection with no subprotocol negotiated, is using 3003 illegal?

Or is 3003 equivalent to 1000, since it's "undefined by this protocol"?

And if A has been negotiated, is using 3003 then allowed, where normally 1007
would have been used?

Or is it not allowed to override base defined codes?

---

From: "Arman Djusupov" <[email-masked]>
Date: Fri, 4 Nov 2011 11:47:04 +0200

> From: Tobias Oberstein [mailto:[email-masked]]
> > That's why I believe that exchanging code 1000-OK, when data is 
> > being deliberately left incomplete and knowingly discarded, is wrong.
> 
> I would argue: all frames have been fully received/processed, so no 
> data on the transport layer was lost or stuck in the TCP stack. The 
> closing HS was clean.

Yes, "no data was lost in the TCP stack" and the TCP closure might be considered as clean at the TCP level.

But at the WS level the closure cannot be considered as clean since "frames have no semantic meaning" so a frame is just a fragment of data that cannot be interpreted outside of a message context; in other words it's like a TCP packet. When an unknown amount of frames are missing, including the final frame, both sides are aware that data is incomplete. This means that the connection was interrupted and the transfer was cancelled.

We don't have an appropriate close code for this... so IMO dropping the connection is one of the valid behaviors both from the client and from the server side. When interrupting the message the client does not need a reply from the server that it has received all data so far, otherwise the client could send a final fragment and wrap-up the message gracefully.

With best regards,
Arman

---

From: Iñaki Baz Castillo <[email-masked]>
Date: Fri, 4 Nov 2011 10:50:44 +0100

> But at the WS level the closure cannot be considered as clean since "frames have no semantic meaning" so a frame is just a fragment of data that cannot be interpreted outside of a message context;…

I must agree.

In case the data application is sent via different WS *messages* and
the client interrupts it after a full ws message has been sent, then
there is no problem at WS level.

But in case a WS message splited into multiple WS frames is
interrupted, then IMHO there is a WS framing layer error so the WS
closure is abrupt rather than clean.

-- 
Iñaki Baz Castillo
<[email-masked]>

---

From: Tobias Oberstein <[email-masked]>
Date: Fri, 4 Nov 2011 03:02:30 -0700

> > But at the WS level the closure cannot be considered as clean since "frames
> have no semantic meaning" so a frame is just a fragment of data that cannot
> be interpreted outside of a message context; in other words it's like a TCP
> packet. When an unknown amount of frames are missing, including the final
> frame, both sides are aware that data is incomplete. This means that the
> connection was interrupted and the transfer was cancelled.
> 
> I must agree.
> 
> In case the data application is sent via different WS *messages* and the
> client interrupts it after a full ws message has been sent, then there is no
> problem at WS level.
> 
> But in case a WS message splited into multiple WS frames is interrupted, then
> IMHO there is a WS framing layer error so the WS closure is abrupt rather
> than clean.

No, I would not agree. 

WS connection closed cleanly = full closing handshake was performed and
the TCP was dropped by the correct peer (server).

Whether the WS connection was closed in the middle of a fragmented
message or not does not affect "wasClean".

Which close code should be used in case of close in middle of fragmented
message is a different question, and I agree with Arman that a more
specific code is not available for that.

In other words: even if there was a code like i.e. 1015 = "closed in middle of message",
the close would still be clean.

---

From: Iñaki Baz Castillo <[email-masked]>
Date: Fri, 4 Nov 2011 11:25:30 +0100

Hi Tobias, please re-check the response of Arman:

> TCP is not aware about how much data an application plans to exchange. But an application is required to follow specific steps in order to ensure that a TCP connection is closed gracefully, without data loss or errors from the socket API. From the perspective of the socket API the closure is graceful when both sides stop writing, call shutdown(), then recv() returns 0 and finally the socket handles are closed. If there were no errors while performing those steps, then this is a reasonable indication that no data was discarded and both sides are closing the connection on mutual agreement.

Let me rephrase the same for WebSocket:

> WebSocket is not aware about how much data an application plans to exchange. But an application is required to follow specific steps in order to ensure that a WebSocket connection is closed gracefully, without data loss or errors from the socket API. From the perspective of the socket API the closure is graceful when both sides stop sending frames and send a close frame. If there were no errors while performing those steps, then this is a reasonable indication that no data was discarded and both sides are closing the connection on mutual agreement.

-- 
Iñaki Baz Castillo
<[email-masked]>

---

From: "Arman Djusupov" <[email-masked]>
Date: Fri, 4 Nov 2011 13:15:31 +0200

> In other words: even if there was a code like i.e. 1015 = "closed in 
> middle of message", the close would still be clean.

At least both sides would be in agreement that the connection was closed in the middle of fragmented message.

But the closure wouldn't be clean as there would still be the error condition on the receiving side and the WS implementation would have to make sure that the application code is notified that the message fragments received up to now are not considered as a complete message.

Otherwise it would be the responsibility of the application to keep track of the current message state and whether the final frame is received. But I believe that since message fragmentation is a feature of the protocol, rather than application logic, it's the responsibility of the protocol to flag and report such conditions, so we can't say this is not protocol error.

Let's simply imagine that the developer wrote the application using a push API implementation and so handles the OnFrame events. When the OnClose event would be triggered, it would not be evident (btw even spec doesn't make this clear) whether the OnClose event after the OnFrame event means that the message is interrupted or complete, especially if OnClose would not have any error code.

With best regards,
Arman

---

From: Tobias Oberstein <[email-masked]>
Date: Fri, 4 Nov 2011 10:27:20 -0700

> the middle of fragmented message.

If there is a chance during AUTH48 and support by the WG, then maybe add

close code 1015 = "closed in middle of message"

> But the closure wouldn't be clean as there would still be the error condition
> on the receiving side and the WS implementation would have to make sure
> that the application code is notified that the message fragments received up
> to now are not considered as a complete message.

A message based API would not fire onMessage(), but onClose() with
code 1000 or - better - 1015 as above, so application can take notice.

At least for Autobahn, onClose() also provides "wasClean" as the JS API.
And that definition of wasClean = closing HS performed + TCP dropped by
correct peer.

> Let's simply imagine that the developer wrote the application using a push
> API implementation and so handles the OnFrame events. When the OnClose
> event would be triggered, it would not be evident (btw even spec doesn't
> make this clear) whether the OnClose event after the OnFrame event means
> that the message is interrupted or complete, especially if OnClose would not
> have any error code.

The frame based API of Autobahn fires onFrame() per frame, and onMessageEnd()
after the last frame, so the app can track.

---

From: "Arman Djusupov" <[email-masked]>
Date: Mon, 7 Nov 2011 13:26:09 +0200

Hello Tobias

> > connection was closed in the middle of fragmented message.
> 

I would rather give this error code a more generic description such as "Aborted/Interrupted", because an endpoint may need to urgently close the connection while receiving a long inbound message. This way the endpoint can inform the remote side that, for whatever reason, it has to terminate all inbound and outbound transfers immediately.

But, in such cases, a much simpler option is to expect the sender to drop the connection without a close handshake. This is actually what the sender would also want, i.e. to stop sending and release all allocated resources immediately. The network error would make it clear to the remote side that the connection was aborted. This is what most implementations will have to do when requested to close in the middle of a transfer.

For example, when the application code requires the connection to be closed while WebSocket is in the process of sending a large non-fragmented message, there is no other option but to drop the connection (unless the sender is prepared to wait until the current message is sent to the remote side). Since the situation that we try to handle can also happen in the middle of a large fragment or in the middle of a single-fragment message, why should a fragmented message be treated any differently that a non-fragmented one? Fragmentation is just the way that permits us to send a message when its final length is unknown.

With best regards,
Arman