curl / Mailing Lists / curl-library / Single Mail
Buy commercial curl support from WolfSSL. We help you work out your issues, debug your libcurl applications, use the API, port to new platforms, add new features and more. With a team lead by the curl founder himself.

Re: curl websockets

From: Weston Schmidt via curl-library <curl-library_at_cool.haxx.se>
Date: Fri, 2 Jul 2021 10:03:13 -0700

I took the bitmask path for my implementation similar to what Daniel
has proposed. I like the flexibility and clarity it offers.

Something like this might work (they need better names probably):

/* WS extension declarations as needed */
CURL_WS_COMPRESS (1 << 10)

/* WS frame flags */
CURL_WS_FRAME_END (1 << 9) /* An extension so that curl can inform the caller
                              * of curl_easy_ws_recv() that this is the end of
                              * the frame on the wire in case that is important
                              * to an extension. */
CURL_WS_FIN (1 << 8)
CURL_WS_RSV1 (1 << 7)
CURL_WS_RSV2 (1 << 6)
CURL_WS_RSV3 (1 << 5)

/* Opcodes */
CURL_WS_OPCODE_0 0
CURL_WS_CONTINUATION 0
CURL_WS_OPCODE_1 1
CURL_WS_TEXT 1
CURL_WS_OPCODE_2 2
CURL_WS_BINARY 2
CURL_WS_OPCODE_3 3
CURL_WS_OPCODE_4 4
CURL_WS_OPCODE_5 5
CURL_WS_OPCODE_6 6
CURL_WS_OPCODE_7 7
CURL_WS_OPCODE_8 8
CURL_WS_CLOSE 8
CURL_WS_OPCODE_9 9
CURL_WS_PING 9
CURL_WS_OPCODE_A 10
CURL_WS_PONG 10
CURL_WS_OPCODE_B 11
CURL_WS_OPCODE_C 12
CURL_WS_OPCODE_D 13
CURL_WS_OPCODE_E 14
CURL_WS_OPCODE_F 15


CURLcode curl_easy_ws_send(CURL *curl, int flags, const void *data, size_t len);
CURLcode curl_easy_ws_recv(CURL *curl, int *flags, void *data, size_t
buflen, size_t *n);

/* Send a binary stream */
curl_easy_ws_send(easy, CURL_WS_BINARY, data, len);
curl_easy_ws_send(easy, CURL_WS_CONTINUATION, data, len);
curl_easy_ws_send(easy, CURL_WS_FIN | CURL_WS_CONTINUATION, data, len);

/* Send a close */
curl_easy_ws_send(easy, CURL_WS_FIN | CURL_WS_CLOSE, data, len);

/* Optional way libcurl could support for OPCODEs 8+ & libcurl asserts
the frame is CURL_WS_FIN)
curl_easy_ws_send(easy, CURL_WS_CLOSE, data, len);

/* Send a ping */
curl_easy_ws_send(easy, CURL_WS_FIN | CURL_WS_PING, data, len);

/* Receiving a binary frame with a buffer that is too small */
curl_easy_ws_recv(easy, &flags, data, buflen, &n);
returns: CURLE_AGAIN
flags: CURL_WS_BINARY

curl_easy_ws_recv(easy, &flags, data, buflen, &n);
returns: CURLE_AGAIN
flags: CURL_WS_FRAME_END | CURL_WS_BINARY
... the frame is complete now

libcurl should be able to do a bit of state checking in case the
caller makes a mistake, but it should only focus on the fragmentation
continuity and validating that a control message is not too long. I
tend to think that libcurl should try to stay out of the business of
validating any of the payload formats because the rules for processing
are tied to frame type & extensions.

This extension concerns me as it renders the
curl_easy_ws_send()/recv() to not have value ... but as long as it
could be implemented using curl_easy_send()/recv() then I'm happy.
https://datatracker.ietf.org/doc/html/draft-ietf-hybi-websocket-multiplexing-11#section-8
tl;dr - they add a few bytes in front of the standard defined WS packet.

On Fri, Jul 2, 2021 at 6:42 AM Felipe Gasper <felipe_at_felipegasper.com> wrote:
>
>
>
> > On Jul 2, 2021, at 7:40 AM, Daniel Stenberg <daniel_at_haxx.se> wrote:
> >
> > On Fri, 2 Jul 2021, Felipe Gasper wrote:
> >
> > Thanks!
> >
> >> The send interface could look much like curl_easy_send():
> >>
> >> curl_ws_send( easy, buffer, buflen, &sent, enum curl_ws_message_type type, enum curl_ws_flags flags )
> >
> > Or perhaps with the type and flags just made as a single bitmask.
>
> This will make it impossible to specify a continuation frame rather than a data frame. (Context: when a message is fragmented, the message’s first frame is text/binary, and the latter ones are continuation.)
>
> That may be OK if curl will commit to abstracting that distinction away.
>
> Also, if WS were to add a 3rd data type -- e.g., via some extension -- then it would be possible to specify CURL_WS_TEXT | CURL_WS_FANCY_NEW_EXT_TYPE, which means curl would need to detect that.
>
> Alternatively, have separate curl_ws_send_text and curl_ws_send_binary functions?
>
> >
> >> Most WS libraries that I’ve seen implement reception as a callback, with a separate control to pause reception of incoming messages.
> >
> > I won't say that's wrong, but I don't see how a callback helps with this API.
> >
> > curl_ws_recv() could just be made to not return until the entire packet can be returned. Or with an option to return a partial one.
>
> I assume you mean something like EAGAIN rather than actually blocking?
>
> Having the caller call curl_ws_recv() directly would mean that that same caller would need to know when the socket has data to read. I don’t know if that’s always a safe assumption.
>
> Also, WS includes ping/pong, so even if the socket has data there might not be any application-level data incoming. (Ping/pong isn’t usually exposed to the application.)
>
> > An area for consideration is how to deal with the buffer (size). I mean, if it wants to wait for a full packet to arrive I suppose it can be large and it might not fit in the user-provided buffer, so the application would need to call it multiple times do drain the data.
>
> Would this argue in favour of a callback, then? Curl could just allocate as it knows it needs. The caller, then, could either memcpy or assume ownership of the buffer (by, e.g., returning CURL_WS_NOFREE from the callback).
>
> Alternatively, there is precedent here with SOCK_SEQPACKET sockets, though curl has the ability to deliver what IMO would be a smoother interface.
>
> >
> > I took the liberty of jotting down some of these API thoughts in the wiki page. Still incomplete and not really functional, but I figured it could help to stir up our collective minds..
> >
> > https://github.com/curl/curl/wiki/WebSockets#api
>
> I feel funny asking this, but is there a comment feature in this wiki system? I don’t see such, but it would seem useful.
>
> -FG

-------------------------------------------------------------------
Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library
Etiquette: https://curl.se/mail/etiquette.html
Received on 2021-07-02