quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

WEBSOCKET.md (4983B)


      1 <!--
      2 Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
      3 
      4 SPDX-License-Identifier: curl
      5 -->
      6 
      7 # WebSocket in curl
      8 
      9 ## URL
     10 
     11 WebSocket communication with libcurl is done by setting up a transfer to a URL
     12 using the `ws://` or `wss://` URL schemes. The latter one being the secure
     13 version done over HTTPS.
     14 
     15 When using `wss://` to do WebSocket over HTTPS, the standard TLS and HTTPS
     16 options are acknowledged for the CA, verification of server certificate etc.
     17 
     18 WebSocket communication is done by upgrading a connection from either HTTP or
     19 HTTPS. When given a WebSocket URL to work with, libcurl considers it a
     20 transfer failure if the upgrade procedure fails. This means that a plain HTTP
     21 200 response code is considered an error for this work.
     22 
     23 ## API
     24 
     25 The WebSocket API is described in the individual man pages for the new API.
     26 
     27 WebSocket with libcurl can be done two ways.
     28 
     29 1. Get the WebSocket frames from the server sent to the write callback. You
     30    can then respond with `curl_ws_send()` from within the callback (or outside
     31    of it).
     32 
     33 2. Set `CURLOPT_CONNECT_ONLY` to 2L (new for WebSocket), which makes libcurl
     34    do an HTTP GET + `Upgrade:` request plus response in the
     35    `curl_easy_perform()` call before it returns and then you can use
     36    `curl_ws_recv()` and `curl_ws_send()` to receive and send WebSocket frames
     37    from and to the server.
     38 
     39 The new options to `curl_easy_setopt()`:
     40 
     41  `CURLOPT_WS_OPTIONS` - to control specific behavior. `CURLWS_RAW_MODE` makes
     42  libcurl provide all WebSocket traffic raw in the callback. `CURLWS_NOAUTOPONG`
     43  disables automatic `PONG` replies.
     44 
     45 The new function calls:
     46 
     47  `curl_ws_recv()` - receive a WebSocket frame
     48 
     49  `curl_ws_send()` - send a WebSocket frame
     50 
     51  `curl_ws_meta()` - return WebSocket metadata within a write callback
     52 
     53 ## Max frame size
     54 
     55 The current implementation only supports frame sizes up to a max (64K right
     56 now). This is because the API delivers full frames and it then cannot manage
     57 the full 2^63 bytes size.
     58 
     59 If we decide we need to support (much) larger frames than 64K, we need to
     60 adjust the API accordingly to be able to deliver partial frames in both
     61 directions.
     62 
     63 ## Errors
     64 
     65 If the given WebSocket URL (using `ws://` or `wss://`) fails to get upgraded
     66 via a 101 response code and instead gets another response code back from the
     67 HTTP server - the transfer returns `CURLE_HTTP_RETURNED_ERROR` for that
     68 transfer. Note then that even 2xx response codes are then considered error
     69 since it failed to provide a WebSocket transfer.
     70 
     71 ## Test suite
     72 
     73 I looked for an existing small WebSocket server implementation with maximum
     74 flexibility to dissect and cram into the test suite but I ended up deciding
     75 that extending the existing test suite server sws to deal with WebSocket
     76 might be the better way.
     77 
     78 - This server is already integrated and working in the test suite
     79 
     80 - We want maximum control and ability to generate broken protocol and negative
     81   tests as well. A dumber and simpler TCP server could then be easier to
     82   massage into this than a "proper" WebSocket server.
     83 
     84 ## Command line tool WebSocket
     85 
     86 The plan is to make curl do WebSocket similar to telnet/nc. That part of the
     87 work has not been started.
     88 
     89 Ideas:
     90 
     91  - Read stdin and send off as messages. Consider newline as end of fragment.
     92    (default to text? offer option to set binary)
     93  - Respond to PINGs automatically
     94  - Issue PINGs at some default interval (option to switch off/change interval?)
     95  - Allow `-d` to specify (initial) data to send (should the format allow for
     96    multiple separate frames?)
     97  - Exit after N messages received, where N can be zero.
     98 
     99 ## Future work
    100 
    101 - Verify the Sec-WebSocket-Accept response. It requires a sha-1 function.
    102 - Verify Sec-WebSocket-Extensions and Sec-WebSocket-Protocol in the response
    103 - Consider a `curl_ws_poll()`
    104 - Make sure WebSocket code paths are fuzzed
    105 - Add client-side PING interval
    106 - Provide option to disable PING-PONG automation
    107 - Support compression (`CURLWS_COMPRESS`)
    108 
    109 ## Why not libWebSocket
    110 
    111 libWebSocket is said to be a solid, fast and efficient WebSocket library with
    112 a vast amount of users. My plan was originally to build upon it to skip having
    113 to implement the low level parts of WebSocket myself.
    114 
    115 Here are the reasons why I have decided to move forward with WebSocket in
    116 curl **without using libWebSocket**:
    117 
    118 - doxygen generated docs only makes them hard to navigate. No tutorial, no
    119   clearly written explanatory pages for specific functions.
    120 
    121 - seems (too) tightly integrated with a specific TLS library, while we want to
    122   support WebSocket with whatever TLS library libcurl was already made to
    123   work with.
    124 
    125 - seems (too) tightly integrated with event libraries
    126 
    127 - the references to threads and thread-pools in code and APIs indicate too
    128   much logic for our purposes
    129 
    130 - "bloated" - it is a *huge* library that is actually more lines of code than
    131   libcurl itself
    132 
    133 - WebSocket is a fairly simple protocol on the network/framing layer so
    134   making a homegrown handling of it should be fine