Skip to content

Commit

Permalink
ws: adapt to the modified API
Browse files Browse the repository at this point in the history
The modification landed in curl's git master today - Oct 7, 2022

Closes curl#255
  • Loading branch information
bagder committed Oct 7, 2022
1 parent cd93726 commit 9c09f9d
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 28 deletions.
1 change: 1 addition & 0 deletions SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@
* [Concept](libcurl/ws/concept.md)
* [Options](libcurl/ws/options.md)
* [Read](libcurl/ws/read.md)
* [Meta](libcurl/ws/meta.md)
* [Write](libcurl/ws/write.md)
* [API compatibility](libcurl/api.md)
* [--libcurl](libcurl/--libcurl.md)
Expand Down
1 change: 1 addition & 0 deletions libcurl/ws.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ WebSocket over that connection until it is done and the connection is closed.
* [Concept](ws/concept.md)
* [Options](ws/options.md)
* [Read](ws/read.md)
* [Meta](ws/meta.md)
* [Write](ws/write.md)
57 changes: 57 additions & 0 deletions libcurl/ws/meta.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Meta

`curl_ws_recv()` and `curl_ws_meta()` both return a pointer to a
`curl_ws_frame` struct, which provides information about the incoming
WebSocket data. A WebSocket "frame" in this case is a part of a WebSocket
fragment. It *can* be a whole fragment, but it might only be a piece of
it. The `curl_ws_frame` contains information about the frame to tell you the
details.

~~~c
struct curl_ws_frame {
int age; /* zero */
int flags; /* See the CURLWS_* defines */
curl_off_t offset; /* the offset of this data into the frame */
curl_off_t bytesleft; /* number of pending bytes left of the payload */
};
~~~

## `age`

This is just a number that identifies the age of this struct. It is always 0
now, but might increase in a future and then the struct might grow.

## `flags`

The `flags' field is a bitmask describing details of data.

### `CURLWS_TEXT`
The buffer contains text data. Note that this makes a difference to WebSocket
but libcurl itself will not make any verification of the content or
precautions that you actually receive valid UTF-8 content.

### `CURLWS_BINARY`
This is binary data.

### `CURLWS_FINAL`
This is the final fragment of the message, if this is not set, it implies that
there will be another fragment coming as part of the same message.

### `CURLWS_CLOSE`
This transfer is now closed.

### `CURLWS_PING`
This as an incoming ping message, that expects a pong response.

## `offset`

When the data delivered is just a part of a larger fragment, this identifies
the offset in number of bytes into the larger fragment where this piece
belongs.

## `bytesleft`

Number of outstanding payload bytes after this frame, that is left to complete
this fragment.

The maximum size of a WebSocket fragment is 63 bits.
35 changes: 10 additions & 25 deletions libcurl/ws/read.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ these two methods:
When the `CURLOPT_CONNECT_ONLY` option is **not** set, WebSocket data will be
delivered to the write callback.

In the default "frame mode" (as opposed to "raw mode"), libcurl delivers
complete WebSocket frames to the callback one by one as they arrive. The
application can then call `curl_ws_meta()` to get information about the
specific frame that was passed to the callback.
In the default "frame mode" (as opposed to "raw mode"), libcurl delivers parts
of WebSocket fragments to the callback as data arrives. The application can
then call `curl_ws_meta()` to get information about the specific frame that
was passed to the callback.

libcurl can deliver full fragments or partial ones, depending one what comes
over the wire when. Each WebSocket fragment can be up to 63 bit in size.

## `curl_ws_recv`

Expand All @@ -22,7 +25,7 @@ call `curl_ws_recv()` to read WebSocket data and `curl_ws_send()` to send it.
The `curl_ws_recv` function has this prototype:

CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
size_t *recv, unsigned int *recvflags);
size_t *recv, struct curl_ws_frame **meta);

`curl` - the handle to the transfer

Expand All @@ -32,23 +35,5 @@ The `curl_ws_recv` function has this prototype:

`recv` - the size in bytes of the data stored in the **buffer* on return

`recvflags` - a bitmask of bits that describe the received frame. See the bit
descriptions below.

### `CURLWS_TEXT`
The buffer contains text data. Note that this makes a difference to WebSocket
but libcurl itself will not make any verification of the content or
precautions that you actually receive valid UTF-8 content.

### `CURLWS_BINARY`
This is binary data.

### `CURLWS_FINAL`
This is the final fragment of the message, if this is not set, it implies that
there will be another fragment coming as part of the same message.

### `CURLWS_CLOSE`
This transfer is now closed.

### `CURLWS_PING`
This as an incoming ping message, that expects a pong response.
`meta` - gets a pointer to a struct with [information about the received
frame](meta.md).
35 changes: 32 additions & 3 deletions libcurl/ws/write.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,41 @@
# Write

An application can receive WebSocket data two different ways, but there is
only one way for it to send off data over the connection. The `curl_ws_send()`
only one way for it to send data over the connection: the `curl_ws_send()`
function.

## `curl_ws_send()`

CURLcode curl_ws_send(CURL *curl, const void *buffer, size_t buflen,
size_t *sent, unsigned int sendflags);
size_t *sent, curl_off_t fragsize,
unsigned int sendflags);

`curl` - transfer handle

`buffer` - pointer to the frame data to send

`buflen` - length of the data (in bytes) in `buffer`

`fragsize` - the total size of the whole fragment, used when sending only a
part of a larger fragment.

`sent` - number of bytes that were sent

`sendflags` - bitmask describing the data. See bit descriptions below.
`flags` - bitmask describing the data. See bit descriptions below.

## Full fragment vs partial

To send a complete WebSocket fragment, set `fragsize` to zero and provide data
for all other arguments.

To send a fragment in smaller pieces: send the first part with `fragsize` set
to the *total* fragment size. You **must** know and provide the size of the
entire fragment before you can send it. In subsequent calls to
`curl_ws_send()` you send the next pieces of the fragment with `fragsize` set
to zero but with the `CURLWS_OFFSET` bit sets in the `flags` argument. Repeat
until all pieces have been sent that constitute the whole fragment.

## Flags

### `CURLWS_TEXT`
The buffer contains text data. Note that this makes a difference to WebSocket
Expand All @@ -40,3 +58,14 @@ This as a ping.

### `CURLWS_PONG`
This as a pong.

### `CURLWS_OFFSET`

The provided data is only a partial fragment and there will be more in a
following call to `curl_ws_send()`. When sending only a piece of the fragment
like this, the `fragsize` must be provided with the total expected frame size
in the first call and it needs to be zero in subsequent calls.

When `CURLWS_OFFSET` is set, no other flag bits should be set as this is a
continuation of a previous send and the bits describing the fragments were set
then.

0 comments on commit 9c09f9d

Please sign in to comment.