Hello, after reading about the experimental websocket in the release notes, I had to try it. I use curl to tunnel RDP (Windows Remote Desktop) over websockets. So I tried to adopt my existing code to use the new API. I noticed a few things:
- curl_ws_send returns the number payload bytes sent + websocket header. At least from my point of view, I'm not really interested in the websocket header bytes written but only in the number of payload bytes written so that I can handle 'short writes'. Anyway I can just subtract '6' (apparently the size of an outoing websocket header) from the number of bytes returned and go with that. - As server I used a small go websocket server that works with websocat[1]. When I send data using libcurl/websocket the go websocket server sends me a FIN BIT 1 but I requested for the connection to stay open. - If the remote websocket connection terminates by either sending a WS FIN Bit or I just kill it with ctrl-c, curl 'keeps the connection open' and lets me read using curl_ws_recv without reporting an error. When I press Ctrl-D in belows example applicagtion, it opens a new connection. In order to have some code to show, I wrote a little bit of code which demonstrates the issues I'm having. I'm probably doing also something stupid and using the API wrong, but here it goes anyway: - 'firepass' go server (can be build with 'make' as long as go is installed) listens on localhost Port 12345. If someone connects to http://127.0.0.1:12345/rdp with a websocket it bridges that websocket connection to 127.0.0.1 Port 22 aka local ssh server on the default port. - wsconnect (can be build on Linux with 'make' as long as curl-config of a websocket enabled curl is first in the path) connects stdin/stdoud to http://127.0.0.1:12345/rdp. Things I noticed: - With websocat I can conenct to the go server: (mini) [~/websocat] ssh -o ProxyCommand="target/release/websocat -b ws://127.0.0.1:12345/rdp" localhost Warning: Permanently added 'localhost' (ED25519) to the list of known hosts. Linux mini 6.1.0-rc2-asahi-ARCH+ #6 SMP PREEMPT_DYNAMIC Thu Oct 27 18:34:27 CEST 2022 aarch64 Last login: Sat Oct 29 08:52:47 2022 from 127.0.0.1 (mini) [~] who am i sithglan pts/8 Oct 29 08:53 (127.0.0.1) (mini) [~] exit logout Connection to localhost closed. - With libcurl, I get the Openssh prompt, but also receive a FIN BIT 1 immediately upon connect. But I also noticed if the remote does not send anything (like with RDP) I get a fin bit from the remote on the reply of the first message. Libcurl and/or my application does not pick up that the connection is closed and continues to use it: (mini) [~/curlwebsocketplayground] ./wsconnect * Trying 127.0.0.1:12345... * Connected to 127.0.0.1 (127.0.0.1) port 12345 (#0) > GET /rdp HTTP/1.1 Host: 127.0.0.1:12345 Accept: */* Upgrade: websocket Connection: Upgrade Sec-WebSocket-Version: 13 Sec-WebSocket-Key: Gq02qNqZUWv0Dl8PQ+6/qQ== * Mark bundle as not supporting multiuse < HTTP/1.1 101 Switching Protocols < Upgrade: websocket < Connection: Upgrade < Sec-WebSocket-Accept: SYTpjxLbBy6ptoB4ryB3jdHYEg8= * Received 101, switch to WebSocket; mask 7ea6ec62 < * Connection #0 to host 127.0.0.1 left intact FD_ZERO STDIN_FILENO: ready to receive remotefd: ready to receive remotefd: trying to read * WS: got 37 websocket bytes to decode * WS:237 received FIN bit 1 * WS: received OPCODE BINARY * WS: received 35 bytes payload (0 left) remotefd: 35 bytes read FD_ZERO STDIN_FILENO: ready to receive remotefd: ready to receive STDOUT_FILENO: ready to send STDOUT_FILENO: trying to send 35 bytes SSH-2.0-OpenSSH_9.0p1 Debian-1+b2 STDOUT_FILENO: 35 bytes (ALL) sent. from empty. FD_ZERO STDIN_FILENO: ready to receive remotefd: ready to receive test STDIN_FILENO: trying to read STDIN_FILENO: 5 bytes read FD_ZERO STDIN_FILENO: ready to receive remotefd: ready to receive remotefd: ready to send remotefd: trying to send 5 bytes * WS: send OPCODE BINARY * WS: send FIN bit 0 (byte 00) * WS: send payload len 5 * WS: wanted to send 11 bytes, sent 11 bytes remotefd: 5 bytes (ALL) sent. to empty. FD_ZERO STDIN_FILENO: ready to receive remotefd: ready to receive remotefd: trying to read * WS: got 26 websocket bytes to decode * WS:237 received FIN bit 1 * WS: received OPCODE CLOSE * WS: received 24 bytes payload (0 left) remotefd: 24 bytes read FD_ZERO STDIN_FILENO: ready to receive remotefd: ready to receive STDOUT_FILENO: ready to send STDOUT_FILENO: trying to send 24 bytes continuation after FINSTDOUT_FILENO: 24 bytes (ALL) sent. from empty. FD_ZERO STDIN_FILENO: ready to receive remotefd: ready to receive websocket: continuation after FIN - Using the libcurl/wsconnect I'm not able to get a ssh connection: (mini) [~/curlwebsocketplayground] ssh -o ProxyCommand="./wsconnect" localhost * Trying 127.0.0.1:12345... * Connected to 127.0.0.1 (127.0.0.1) port 12345 (#0) > GET /rdp HTTP/1.1 Host: 127.0.0.1:12345 Accept: */* Upgrade: websocket Connection: Upgrade Sec-WebSocket-Version: 13 Sec-WebSocket-Key: Nm/meDaQgcBWdyLfb5tRfw== * Mark bundle as not supporting multiuse < HTTP/1.1 101 Switching Protocols < Upgrade: websocket < Connection: Upgrade < Sec-WebSocket-Accept: pNv2JrXQJQqgJ97d/HVxJ3Eo6j8= * Received 101, switch to WebSocket; mask c713068f < * Connection #0 to host 127.0.0.1 left intact FD_ZERO STDIN_FILENO: ready to receive remotefd: ready to receive STDIN_FILENO: trying to read STDIN_FILENO: 35 bytes read FD_ZERO STDIN_FILENO: ready to receive remotefd: ready to receive remotefd: ready to send remotefd: trying to send 35 bytes * WS: send OPCODE BINARY * WS: send FIN bit 0 (byte 00) * WS: send payload len 35 * WS: wanted to send 41 bytes, sent 41 bytes remotefd: 35 bytes (ALL) sent. to empty. FD_ZERO STDIN_FILENO: ready to receive remotefd: ready to receive websocket: continuation after FIN remotefd: trying to read * WS: got 26 websocket bytes to decode * WS:237 received FIN bit 1 * WS: received OPCODE CLOSE * WS: received 24 bytes payload (0 left) remotefd: 24 bytes read FD_ZERO STDIN_FILENO: ready to receive remotefd: ready to receive STDOUT_FILENO: ready to send STDOUT_FILENO: trying to send 24 bytes STDOUT_FILENO: 24 bytes (ALL) sent. from empty. FD_ZERO STDIN_FILENO: ready to receive remotefd: ready to receive websocket: close sent My example code is here: https://tg.st/u/curlwebsocketplayground.tar.gz I would like to know if I'm using it wrong or there are still some rough edges that need to be worked on. It would also be nice to be able to use curl as a websocat replacement like that, I tried but it does not work at the moment. ssh -o ProxyCommand="curl ws://127.0.0.1:12345/rdp" localhost [1] https://github.com/vi/websocat Cheers, Thomas -- Unsubscribe: https://lists.haxx.se/listinfo/curl-library Etiquette: https://curl.se/mail/etiquette.html