> could libcurl wait for all the fragmented messages to arrive, then concat 
> them and serve the completed message to the calling application?

I don't think it is possible in all the cases. WebSocket text/data messages can 
have 64-bit length, so it is just not possible to assemble large messages.
I implemented WebSocket protocol in some C++ curl-based client and I used the 
following approach:

1. Notify client that some WS not control message (i.e. text/data) has arrived.
2. In the notification callback, Client either provides a buffer to store the 
message (can be useful for short messages) or data writing callback to store 
large messages (where data concatenation is not feasible).
     - If provided buffer is too small to hold the message, then we need to 
handle it as WebSocket protocol prescribes - close WS connection with 1009 
'Buffer too small' error code.

3. I also provided a special callback for incoming control messages (i.e. Ping) 
while large data messages are being received, so client can handle multiple 
messages (one large data and multiple control messages at the same time) at the 
same time.

> Alternatively, a curl_ws_send_ping and curl_ws_send_pong would be useful.
> Also, considering sending a pong response when a ping request is sent 
> automatically, unless it's specified by the calling program somehow.

Yes, I agree that automatic reply on Ping is part of a good WS client.

> Using a callback function may be a solution, when a message is received, 
> libcurl calls a function specified by the application, something like
> cur_ws_on_message_received()

I used two callbacks in my WS client implementation: 
- onMessageArrived() (indicating arrival of the first frame of the message and 
asking client code to specify a way where/how to write the incoming message 
data)
- onMessageReceived() (indicating that the message was successfully received).

To simplify client's life, I allowed to specify the WS receive buffer as 
WebSocket option, so in most of the use cases, my client code used just 
onMessageReceived().

Talking about some WS implementation difficulties,  I would say that message 
multiplexing (sending/receiving large data/text message intermixed with control 
messages - control messages should be sent/received as high-priority interrupts 
for data messages), proper protocol error handling and protocol extensions 
(like compressing) gave me some headaches.

WebSocket protocol is very specific about how and when WS connection should 
handle certain errors, and which status codes should be used in different 
connection closure cases, so sometimes some specific transport errors (like Tls 
handshake errors) should be explicitly handled and reported as WS connection 
closures with specific status codes (i.e. 1015 'TLS handshake failure').

Thanks,
Dmitry Karpov


-----Original Message-----
From: curl-library <curl-library-boun...@cool.haxx.se> On Behalf Of Nicolas 
Mora via curl-library
Sent: Friday, July 2, 2021 4:48 PM
To: libcurl development <curl-library@cool.haxx.se>
Cc: Nicolas Mora <nico...@babelouest.org>; Daniel Stenberg <dan...@haxx.se>
Subject: Re: curl websockets

Le 2021-07-02 à 17 h 53, Daniel Stenberg via curl-library a écrit :
>>
>> 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.)
> 
> "CURL_WS_MORE" is my currently suggested flag to say to libcurl that 
> there's more data coming that belongs to the same data packet. Doesn't 
> that work?
> 
could libcurl wait for all the fragmented messages to arrive, then concat them 
and serve the completed message to the calling application?

>> Alternatively, have separate curl_ws_send_text and 
>> curl_ws_send_binary functions?
> 
> That could certainly work and would save users sending text from 
> having to set a "this is text" bit. My personal preference is to 
> rather keep it to one function with the bits for type, but I'm here to 
> listen in what peeps want and I will not push my own preferences if I'm in a 
> minority.
> 
Alternatively, a curl_ws_send_ping and curl_ws_send_pong would be useful.
Also, considering sending a pong response when a ping request is sent 
automatically, unless it's specified by the calling program somehow.

> 
> Yes, sorry I didn't even think about that. I'm positive users will 
> immediately come up with use cases where they want 22 parallel 
> websocket connections going on so they cannot block. Or perhaps we can 
> offer some kind of blocking abilitites, but non-blocking is a must-support 
> feature.
> 
> Another thing that struck me is that we probably want to offer a 
> decent way to do non-blocking ws-connects as well for the 
> 22-connections user who won't accept that the application will block once for 
> each setup...
> 
Couldn't libcurl have both? a blocking and a non-blocking curl_ws_recv() 
function?

>> 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.
> 
> Yeah, that's one of my outstanding questions. How do we do that?
> 
Using a callback function may be a solution, when a message is received, 
libcurl calls a function specified by the application, something like
cur_ws_on_message_received()

/Nicolas
-------------------------------------------------------------------
Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library
Etiquette:   https://curl.se/mail/etiquette.html

-------------------------------------------------------------------
Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library
Etiquette:   https://curl.se/mail/etiquette.html

Reply via email to