Open dev31337 opened 6 years ago
I'm trying to get the peer IP
In version 1.1.0, it's done using environment variables:
$ websocat --oneshot -eE -b ws-l:127.0.0.1:1234 sh-c:'env'&
[1] 7420
$ websocat -E -b ws://127.0.0.1:1234/qwerty | grep WEBSOCAT
WEBSOCAT_URI=/qwerty
WEBSOCAT_CLIENT=127.0.0.1:36070
[1]+ Done websocat --oneshot -eE -b ws-l:127.0.0.1:1234 sh-c:'env'
I've just recently developed this, it's not yet in the pre-built version. If needed I can make a pre-build for you to play with. and it's available in the 1.1 preview prebuilded files.
Using signal instead of closing stdin
Interesting idea. Currently you can make it not close stdin, but without any notifications about client disconnecting.
Examples:
With parallel connections support:
$ websocat -t ws-l:127.0.0.1:1234 reuse:sh-c:'stdbuf -oL nl'&
[1] 11670
$ websocat -E ws://127.0.0.1:1234/
Q
1 Q
W
2 W
E
3 E
$ websocat -E ws://127.0.0.1:1234/
R
4 R
T
websocat: WebSocketError: I/O failure
5 T
Y
6 Y
$ kill %1
[1]+ Terminated websocat -t ws-l:127.0.0.1:1234 reuse:sh-c:'stdbuf -oL nl'
Without parallel connections support:
$ websocat -t autoreconnect:ws-l:127.0.0.1:1234 sh-c:'stdbuf -oL nl'&
[1] 12245
$ websocat -E ws://127.0.0.1:1234/
A
1 A
B
2 B
C
3 C
WARN 2018-07-13T12:30:17Z: websocat::reconnect_peer:
$ websocat -E ws://127.0.0.1:1234/
D
4 D
E
5 E
F
6 F
WARN 2018-07-13T12:30:24Z: websocat::reconnect_peer:
$ kill %1
[1]+ Terminated websocat -t autoreconnect:ws-l:127.0.0.1:1234 sh-c:'stdbuf -oL nl'
There are quirks in both methods, especially with abruptly disconnecting clients or parallel connections. If you are building a reliable service you should test it thorougly.
I also plan to make a "fancy reuser" overlay to make it just deliver explicit connection and disconnection messages as JSON snippets and allow replies to specific connected clients by ID. It's not implemented yet.
Oh thanks for the 1.1 it is exactly what I needed.
Regarding the SIGHUP request, I knew that you could disable the stdin closing but as you said there would be no other way to know about the disconnection.
Let me tell you why I prefer SIGHUP, the main reason is that I'm restoring/porting old unix applications that were running on serial ports (with modems) and when the call was hung-up it was producing a SIGHUP.
I was able to use the stdin closing instead but the only issue with that is that the binary only discovers the disconnection when it is asking for input, not when it is doing something else.
This is why if you have some spare time don't hesitate to offer this option if you can because I think other people (using exec:binary) would also benefit from it :)
What would SIGHUP mean if multiple clients are connected to a server websocket simultaneously?
Do you have Rust toolchain to build commits and test new things in websocat or you rely on prebuilded? If the latter, which platform do you use?
Implemented the SIGHUP
:
$ cat > huphup.pl << \EOF
> #!/usr/bin/perl
> sub huphup {
> print STDERR "HUP\n";
> }
> $SIG{'HUP'} = \&huphup;
>
> my $v = "";
> while(1) {
> my $r = sysread STDIN, $v, 65536;
> syswrite STDOUT,$v if $r > 0;
> #last if $r == 0;
> }
> EOF
$ chmod +x huphup.pl
$ websocat --exec-sighup-on-zero-msg --reuser-send-zero-msg-on-disconnect -t ws-l:127.0.0.1:1234 reuse-raw:exec:./huphup.pl&
[1] 30931
$ websocat -E ws://127.0.0.1:1234
A
A
BB
BB
HUP
$ websocat -E ws://127.0.0.1:1234
123
123
qwerty
qwerty
HUP
$
Re-uploaded websocat_amd64-linux-static file with these two new flags.
Note that reuse-raw:
means that if multiple clients are connected simultaneously then replies from the program are directed at random-ish client and SIGHUPs are generated for each disconnected client, not for the last one.
--reuser-send-zero-msg-on-disconnect
currently does not affect reuse-broadcast:
, but may be implemented for it as well (sending the zero message only when going from 1 connected client to 0 connected clients).
Sorry no I don't have the rust toolchain installed, I'm using ubuntu x64 and the static binary with nossl.
Thank you for doing it ! :)
I will try to answer your questions, but the idea was very simple, when websocat has its connection closed by one peer simply sends a SIGHUP to the binary that was running for that peer.
"What would SIGHUP mean if multiple clients are connected to a server websocket simultaneously?"
I think I just explained above, when a client disconnects, sends SIGUP to the binary that was running for that client.
Note that reuse-raw: means that if multiple clients are connected simultaneously then replies from the program are directed at random-ish client and SIGHUPs are generated for each disconnected client, not for the last one.
I'm not sure I understand this one, can you be more specific ? :)
There is one last thing I wanted to tell you, in my situation the binary changes during the connection (by using execl() to run others binaries) but the PID stays the same.
So if you send the signal to the PID (and not to the binary name) it will work right out of the box.
to the binary that was running for that peer
For that peer? Means no reuser? Why do you need SIGHUP then? What does your application do when both stdin and stdout are closed? Does SIGPIPE happen? Have you tried -E
(--exit-on-eof
) option?
Anyway, implemented --exec-sighup-on-stdin-close
. Is it what you need?
https://github.com/vi/websocat/releases/download/v1.1-pre/websocat_amd64-linux-static
MD5 (websocat_amd64-linux-static) = 613653021a056bbd263a54803bb503a4
Thanks I will try it ! :)
@dev31337,
websocat -e -t --no-fixups --no-line ws-l:0.0.0.0:port exec:/binary Invalid UTF-8 in --text mode.
Either your program ./binary
sends malformed UTF-8 to output, or read(2)-ful chunks of data read from your program happen to split an UTF-8 character apart (e.g. first byte in one chunk, second byte in the next chunk).
You opted out from line-to-message conversion ((--no-line
or --no-fixups
) + lack of line2msg:
overlay), so boundaries between messages are being set arbitrarily if data is flowing fast enough. That's OK for binary mode, but not so for text mode.
If you want to send multiline text messages, you can use zero byte as line separator with -0
option.
What about the SIGHUP. Does it work as you want?
Note that in current version unfortunately server mode ws-l:0.0.0.0:port
recommends usage of -E
option, especially if ./binary
is not periodically outputting some data on it's own.
There is (currently) no normal socket disconnection detection, so when client disconnects, it's socket may stay open and associated ./binary
still running. If your scenario works when you set --exit-on-eof
option then better leave it in.
Yes, I found the issue this is why I deleted the question, I was sending malformed UTF-8.
I don't understand -E, what does it do exactly ?
Currently I'm not using it but the stdin of my executed binary still gets closed (EOF) when the client disconnects.
It drops the task, closes the socket and maybe stops the program (haven't checked) when client sends EOF (a disconnected socket or WebSocket Close message).
If your program closes stdout in response then it should be OK even without -E
.
Are there any reasons for this issue to stay open?
Hi,
Thank you for this amazing tool.
I'm unfortunately not familiar with Rust (only C, C++, C#, PHP, JS) so my only option is to make a request to you (instead of coding/submitting it).
There are two features that I'm missing:
I'm trying to get the peer IP when using "exec:binary". Would it be possible when I use --exec-args to support a built-in variable (ie: $IP) which would contain the peer IP ?
Using signal instead of closing stdin when using "exec:binary". Would it be possible when I use "exec:binary" and the websocket is closed to send SIGHUP (for example) to the binary instead of closing its stdin ?
Regards.