vi / websocat

Command-line client for WebSockets, like netcat (or curl) for ws:// with advanced socat-like functions
MIT License
6.73k stars 259 forks source link

When is websocat actually listening? #127

Open gerdstolpmann opened 2 years ago

gerdstolpmann commented 2 years ago

When you use websocat in programmatic context, it would be useful to be able to be notified when the listening socket is actually ready and accepting connections, so that the using process can start connecting. Currently, you don't know, and the only thing you can do is to wait for a little while (milliseconds) and then hope that everything is ready.

E.g. there could be an option --notify-listening and this outputs a line for each listening socket on stderr, like

$ websocat --notify-listening tcp-l:127.0.0.1:8000 ws://host
LISTEN tcp-listen:127.0.0.1:8000

This would also open the door to an additional little feature:

$ websocat --notify-listening tcp-l:127.0.0.1:0 ws://host
LISTEN tcp-listen:127.0.0.1:65345
vi commented 2 years ago

Indeed, there is currently no reliable message (even with increased verbosity) that happens after the listen(2) syscall.

I can implement this (and provide a prebuilt executable if needed).

As a workaround you can also move socket + listen away from Websocat by using --accept-from-fd option (like for integrating with systemd)

websocat --accept-from-fd -b -E ws-u:unix-listen:55 literal:$'Hello, world\n' 55<> something
vi commented 2 years ago

LISTEN tcp-listen:127.0.0.1:65345

Can you turn it into more a proper spec (or is there already some precedent for such lines)? How that would look for UDP sockets (including multicast), UNIX sockets (including Linux's abstract namespace)? Would it be just the square brackets for IPv6 (including link-local addresses with scope ids)?

gerdstolpmann commented 2 years ago

I don't have a spec - this is just an idea I had when writing the first issue. For me it would only be important that it can be easily parsed, i.e. split into words, and then run a regexp to check the details. In most cases you would just watch out for the presence of the LISTEN line.

Could also be something like LISTEN proto=tcp,ip=127.0.0.1,port=65345 (maybe the pcap format defines a number of these fields?)

vi commented 2 years ago

Implemented.

You haven't specified your preferred platform, so I built a static version for Linux: https://github.com/vi/websocat/releases/download/v1.8.0/websocat_announcelisten

$ strace -fe trace=network websocat_announcelisten --stdout-announce-listening-ports -s 1234
Listening on ws://127.0.0.1:1234/
socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 6
setsockopt(6, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
bind(6, {sa_family=AF_INET, sin_port=htons(1234), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
listen(6, 1024)                         = 0
LISTEN proto=tcp,ip=127.0.0.1,port=1234
gerdstolpmann commented 2 years ago

wow, that's quick... I'll give it a try tomorrow