Skip to content

Websocket pain #17438

Open
Open
@DerAlbiG

Description

@DerAlbiG

I did this

I am trying to implement a websocket abstraction in C++ with CURL. The goal is to manage a lot of connection (>100), therefore I am using a multi-handle to manage many easy-handles. On my journey I found the following problems which are a mix of bugs / inconvenient behavior / missing features.

  1. Because I am using Multi-Handles, I need to be able receive an asynchronous onOpen-event in order to know when the websocket connection is established. CURL does not provide such an event.
    I am going for Model 1 using a WRITEFUNCTION to keep things asynchronous. Model 1 does not describe how I send data, therefore i am defaulting to curl_ws_send. I also cannot use CURLOPT_CONNECT_ONLY as this would be "Model 2". When connecting, I send my own header to let it connect and switch protocols; then parse the incoming protocol-switch response myself (using the HEADERFUNCTION). When receiving the empty-line (end of header), i can generate an onOpen() event myself. However, since my call-context is in the HEADERFUNCTION, i cant directly invoke the onOpen event handler from there, because onOpen could want to send data. For some reason curl_ws_send() does not work from within the HEADERFUNCTION-context. According to the documentation of curl_ws_send it should be possible to use curl_ws_send from within a callback. The error code is however consistently CURLE_SEND_ERROR.

  2. This leads to the next issue: there is no method to send a message to the main-loop / curl_multi_info_read() in order to trigger operations associated with a certain easy-handle that cant be directly executed from within a callback. This leads to state-management outside of the curl control flow which is always messy. It would be nice to be able to trigger a special message that is not CURLMSG_DONE. (with custom data in the message.data.whatever field)

  3. Within the WRITEFUNCTION, curl_ws_meta() never sets CURLWS_CONT for partial messages. When I receive a large response (>100kb) the WRITEFUNCTION trickles in the data in ~4kb chunks. According to the documentation of curl_ws_meta CURLWS_CONT should be set for all but the last data chunk. This is not the case.

  4. I am not sure about this one - it may be a CURL-problem or a me-problem, due to lack of references. But while my websocket implementation generally works, it fails to connect to a certain host which always responds with 502 (Bad Gateway) instead of 101 (Protocol switch). This particular host is only reachable if I connect via https://.... instead of wss://..... When using https, the protocol switch is accepted successfully by the host. However under this URL, curl_ws_send() fails consistently with CURLE_SEND_ERROR. I think this may be caused by a violation of Setup where the websocket-part of CURL is not activated because I cant use the wss://-prefix (??)
    IF that is the case, I find that design decision highly disturbing, because I can, at any point, assemble my own header that asks for a protocol switch - I therefore need an option for the easy-handle to turn on websocket features at will, independently of the URL I connect to. This is a decision between me and the server, not CURLs background state management. I hope that makes sense.
    Again, this could be my fault, so it would be nice if someone (who knows the internals) could confirm this behavior.

curl/libcurl version

curl 8.13.0

operating system

Linux 6.14.6-2-MANJARO

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions