Websocket protocol continuation frame - websocket

I am trying to understand the websocket protocol https://www.rfc-editor.org/rfc/rfc6455
but do not understand what the continuation frame is. If I am making a websocket client, when would I expect a server to send this? When would I want to send it?
The above reference has very little information about what the continuation frame is or does, or how a client (or a server) should handle it.
From the protocol spec:
Opcode: 4 bits
Defines the interpretation of the "Payload data". If an unknown
opcode is received, the receiving endpoint MUST _Fail the
WebSocket Connection_. The following values are defined.
* %x0 denotes a continuation frame
This is one of only three references to the continuation frame, and it is not giving me a lot to go on.
Should I just ignore any frames with this opcode?

No, you must not ignore continuation frames. If you don't implement them, your WebSocket implementation will not conform to RFC6455. Continuation frames are for fragmented WebSocket messages. All frames but the first are called continuation frames. All but the first and last are called non-final continuation frames.

Related

JMeter (An established connection was aborted by the software in your host machine)

I am testing JMeter on my site, I use debug and catch exception which close my socket, I don't understand the reason for that
error: Response code:Websocket I/O error
Response message:WebSocket I/O error: Программа на вашем хо�т-компьютере разорвала у�тановленное подключение
(it means "An established connection was aborted by the software in your host machine").
Screenshot
First of all it looks like you're getting multiple frames as the response to a single call, as per documentation:
Fragmentation
WebSocket messages may be fragmented into several frames. In such cases the first frame is an ordinary text or binary frame, but it will have the final bit cleared. The succeeding frames will be continuation frames (whether they are text or binary is inferred by the first frame) and the last continuation frame will have the final bit set. The plugin supports continuation frames, but as the plugin is frame-oriented, you'll have to read them yourself. In cases where the number of fragments is known beforehand, this is as easy as adding an extra WebSocketReadSampler for each continuation frame you expect. If the number of continuation frames is not known, you need to create a loop to read all the continuation frames. For this purpose, the plugin provides a new JMeter variable called websocket.last_frame_final that indicates whether the last frame read was final. This enables you to write a simple loop with a standard JMeter While Controller; use the expression ${__javaScript(! ${websocket.last_frame_final},)} as condition. With a JMeter If Controller, the condition can be simplified to ! ${websocket.last_frame_final} because that controller automatically interprets the condition as JavaScript. See the sample Read continuation frames.jmx test plan for examples of using the While or the If controller to read continuation frames.
If you are unsure whether continuation frames are sent by your server or how much, switch on debug logging: samplers reading a frame will log whether the received frame is a "normal" single frame, a non-final frame (i.e. 1st fragment), a continuation frame or a final continuation frame (last fragment).
If this is not the case, another possible reason I can think of is that something is terminating the websocket connection on your machine, I don't know what exactly, maybe a firewall or an antivirus or your corporate proxy server
Try opening inbound and outbound traffic for the java process, add it to your antivirus whitelist and ask around, maybe your network administrator can shed some light on it.
If you want to get some more troubleshooting information you can add the next line to JMeter's system.properties file:
javax.net.debug=all
and inspect JMeter's stdout to see if there is a clue there.
More information: Debugging SSL/TLS Connections

Jmeter - Websocket plugin - unable to find solution to constantly read incoming messages

Good afternoon.
I have implemented websockets in my project using the plugin "WebSocket Samplers by Peter Doornbosch" in Jmeter.
So far the requirements were simply to send and receive some payload, or simply send and forget.
However I got a new requirement where the server will constantly send back websocket message to client at every 5 second interval.
Ex: I send ABC , XYZ, ABD at every 3 second interval and I need to read XYC, YTZ at every 5 second interval both should happen simultaneously
I'm unable to use Parallel Controller as each item within the controller is a separate thread and thus I will loose web socket connection for the second one.
Is there any way I can achieve this using some listeners or something.
Thanks for your response in advance
As per documentation:
Fragmentation
WebSocket messages may be fragmented into several frames. In such cases the first frame is an ordinary text or binary frame, but it will have the final bit cleared. The succeeding frames will be continuation frames (whether they are text or binary is inferred by the first frame) and the last continuation frame will have the final bit set. The plugin supports continuation frames, but as the plugin is frame-oriented, you'll have to read them yourself. In cases where the number of fragments is known beforehand, this is as easy as adding an extra WebSocketReadSampler for each continuation frame you expect. If the number of continuation frames is not known, you need to create a loop to read all the continuation frames. For this purpose, the plugin provides a new JMeter variable called websocket.last_frame_final that indicates whether the last frame read was final. This enables you to write a simple loop with a standard JMeter While Controller; use the expression ${__javaScript(! ${websocket.last_frame_final},)} as condition. With a JMeter If Controller, the condition can be simplified to ! ${websocket.last_frame_final} because that controller automatically interprets the condition as JavaScript. See the sample Read continuation frames.jmx test plan for examples of using the While or the If controller to read continuation frames.
If you are unsure whether continuation frames are sent by your server or how much, switch on debug logging: samplers reading a frame will log whether the received frame is a "normal" single frame, a non-final frame (i.e. 1st fragment), a continuation frame or a final continuation frame (last fragment).

http2: PUSH_PROMISE client-side stream state

The http2 spec says:
A receiver MUST treat the receipt of a PUSH_PROMISE on a stream that
is neither "open" nor "half-closed (local)" as a connection error
(Section 5.4.1) of type PROTOCOL_ERROR. However, an endpoint that has
sent RST_STREAM on the associated stream MUST handle PUSH_PROMISE
frames that might have been created before the RST_STREAM frame is
received and processed.
The spec also has this lifecycle diagram.
My understanding is that in order for a client to receive a PUSH_PROMISE on a stream, the client must have all of these on that stream:
sent HEADERS frame (+ any CONTINUATIONs) to the server
not received END_STREAM flag from the server
not received RST_STREAM frame from the server
(Notably missing here is "not sent RST_STREAM frame to the server”, which would lead to the stream being "closed"; the quote above says this is not grounds for connection error.)
In any case where these criteria are not met, then the client must treat receiving a PUSH_PROMISE as a connection error.
Is this a correct understanding?
Your understanding is correct.
The HTTP/2 protocol associates PUSH_PROMISE streams to an existing stream, called the associated stream.
The associated stream must meet the conditions defined in the section of the specification quoted in the question; the bullet list in the question is another way of saying the same thing that the specification section says.

http2: PUSH_PROMISE reserved stream id validation

The spec says:
The identifier of a newly established stream MUST be numerically
greater than all streams that the initiating endpoint has opened or
reserved. This governs streams that are opened using a HEADERS frame
and streams that are reserved using PUSH_PROMISE. An endpoint that
receives an unexpected stream identifier MUST respond with a
connection error (Section 5.4.1) of type PROTOCOL_ERROR.
For the case of the server that sends PUSH_PROMISE it makes sense to me that conforming servers must send strictly increasing stream ids. But I don't understand how the client is supposed to detect this situation.
For example, on one connection, if the server sends:
PUSH_PROMISE promised stream 2
PUSH_PROMISE promised stream 4
because of concurrency the client might receive
PUSH_PROMISE promised stream 4
PUSH_PROMISE promised stream 2
the spec would have me think that client should error on this, but the server did nothing wrong.
What am I missing here?
If the server wrote PUSH_PROMISE[stream=2] and then PUSH_PROMISE[stream=4], then those frames will be delivered in the same order (this is guaranteed by TCP).
It is a task of a client to read from the socket in an ordered way.
For a HTTP/2 implementation the requirement is even stricter, in that not only it has to read from the socket in an ordered way, but it must also parse the frames in an ordered way.
This is required by the fact that PUSH_PROMISE frame carries a HPACK block and in order to keep the server and client HPACK context in sync, the frames (or at least the HPACK blocks of those frames) must be processed in order, so stream=2 before stream=4.
After that, the client is free to process the 2 frames concurrently.
For implementations, this is actually quite simple to achieve, since a thread allocated to perform I/O reads typically does:
loop
read bytes from socket
if no bytes or socket closed -> break loop
parse read bytes (with HPACK decoding) -> produce frame objects
pass frame objects to upper software layer
end loop
Since the read and parse are sequential and no other thread reads from the same socket, the ordering guarantee is met.

Websocket questions: framing, masking

Couple questions about websockets protocol sending BINARY data:
Why is the payload masked? doesn't TCP guarantee data integrity?
What exactly is fragmentation? does it mean that, if I send a single frame of 1000 byte payload, the other end (due to intermediate proxies) may receive four separate frames of 200, 300, 270, and 230 bytes each (with only the final frame having the FIN bit set?)
The payload sent from client to server (not server to client) is masked neither for reasons of data integrity nor authenticity, but to prevent rogue scripts from confusing (and potentially attacking) old intermediaries (Web proxies and the like).
Any WebSocket client that conforms to RFC6455 MUST mask client-to-server frames. Nevertheless, some libraries allow you to turn off masking for client, and turn off failing on non-masked client frames (e.g. AutobahnPython).
The latter can be useful to elimit the CPU overhead associated with masking. It may be acceptable when both endpoints are under your control and either the route between both are fully under your control (e.g. talking WebSocket over loopback or Unix domain sockets or LAN) or you are using TLS, and hence (in most situations) no intermediary will be able to look inside the traffic anyway.
Fragmentation works like this: a WebSocket message may be split into multiple WebSocket frames - and also coalesced any time not only by the sender, but also any intermedaries on the way to the receiver. And yes, only the last WebSocket frame of a sequence of frames for a given message will have the FIN bit set.

Resources