[Solved] echo.pl (for mod_wstunnel) example
Added by andrey_filippov over 2 years ago
I was trying to implement the minimal example from mod_wstunnel page, but our system running lighttpd does not have Socket Perl module and I do not understand this powerful language. Can you help to "translate" this 7-liner echo.pl to PHP or Python so I can try mod_wstunnel in our camera?
Andrey Filippov
Elphel
Replies (15)
RE: echo.pl (for mod_wstunnel) in PHP or Python - Added by gstrauss over 2 years ago
Most minimal systems have Perl. And if your system has PHP, then your system is not minimal, IMO.
The sample echo script:- ignores SIGPIPE
- accept()s a connection on the listening socket (in this example, lighttpd provides listening socket on script stdin)
- reads line and write line (line-by-line for simplicity; could have been written fully unbuffered)
- writing line should be to output (stdout) with line-buffered discipline or non-blocking discipline.
If block-buffer discipline (often the default for stdout), write line and flush output.
If you try to write this in PHP or Python and show your effort, then I'll help you to finish it if you have trouble.
RE: echo.pl (for mod_wstunnel) in PHP or Python - Added by andrey_filippov over 2 years ago
I was referring to the mod_wstunnel minimal example, not the minimal system. The system does have Perl, just no Socket module. Yes, I understood that lighttpd communicates with the backend script over script's stdin/stdout, I just have problem - how to bind socket or accept connection from STDIN and send to STDOUT in either of these 2 languages (so far I only used sockets in C). Will look harder.
And, BTW, thanks for lighttpd - we are using it for almost as long as lighttpd exists (we first inherited it with Axis camera GNU/Linux distribution), it was powering cameras used in Google Books and first high-resolution GSV.
RE: echo.pl (for mod_wstunnel) in PHP or Python - Added by gstrauss over 2 years ago
Glad that lighttpd works well for you.
Delete the use Socket;
line and the Perl script should still work.
BTW, it would take me less time to write echo.pl in C than to look up how to do it in other languages.
...It would probably be a good exercise to do in Python (for you or for me).
RE: echo.pl (for mod_wstunnel) in PHP or Python - Added by andrey_filippov over 2 years ago
Thank you, the script does not complain w/o Socket (nothing bad in lighttpd.error.log, script is running), so the problem is somewhere else (same result that I was able to get with my Python and PHP attempts.
Andrey
root@elphel393:/tmp# lighttpd -v lighttpd/1.4.53 (ssl) - a light and fast webserver root@elphel393:/tmp# cat /var/log/lighttpd.error.log ... 2021-07-22 22:47:03: (../../lighttpd-1.4.53/src/server.c.1464) server started (lighttpd/1.4.53) root@elphel393:/tmp# ps -w PID USER VSZ STAT COMMAND ... 3619 root 4864 S /usr/sbin/lighttpd -D -f /etc/lighttpd.conf 3624 root 4040 S {echo.pl} /usr/bin/perl -Tw /www/pages/echo.pl ... /etc/lighttpd.conf : ... server.modules = ( "mod_access", "mod_fastcgi", "mod_cgi", "mod_wstunnel", "mod_accesslog" ) server.document-root = "/www/pages" server.errorlog = "/www/logs/lighttpd.error.log" server.port = 80 wstunnel.server = ( "" => ( ( "socket" => "/tmp/wstunnel.socket", "bin-path" => "/www/pages/echo.pl", "max-procs" => 1, "debug" => 5 ) ) ) ... http://192.168.0.41/wstunnel_count.html <!DOCTYPE html> <!-- modified from example in https://github.com/joewalnes/websocketd README.md --> <pre id="log"></pre> <script> // helper function: log message to screen var logelt = document.getElementById('log'); function log(msg) { logelt.textContent += msg + '\n'; } // helper function: send websocket msg with count (1 .. 5) var ll = 0; function send_msg() { if (++ll <= 5) { log('SEND: '+ll); ws.send(ll+'\n'); } } // setup websocket with callbacks log('STARTING\n'); var ws = new WebSocket('ws://localhost:80/'); log('CREATED\n'); ws.onopen = function() { log('CONNECT\n'); send_msg(); }; ws.onclose = function() { log('DISCONNECT'); }; ws.onmessage = function(event) { log('RECV: ' + event.data); send_msg(); }; </script> Output: STARTING CREATED DISCONNECT
RE: echo.pl (for mod_wstunnel) in PHP or Python - Added by gstrauss over 2 years ago
Are you sure that mod_wstunnel is handling the request and not somewhere else in your config with mod_fastcgi or mod_cgi?
I should probably carve out an exception for count.html in the lighttpd.conf in the example, and should probably make the URL in count.html more unique, as in "ws://localhost:80/wstunnel/"
RE: echo.pl (for mod_wstunnel) in PHP or Python - Added by gstrauss over 2 years ago
I updated the examples on mod_wstunnel
If you are having trouble with your config, then please try to use the minimalistic example *.conf
files (which I have tested) before trying to integrate it into your existing config.
RE: echo.pl (for mod_wstunnel) in PHP or Python - Added by andrey_filippov over 2 years ago
You are probably right. I'l check it. And put wstunnel.server = ( "wstunnel" => (..., correct?
RE: echo.pl (for mod_wstunnel) in PHP or Python - Added by gstrauss over 2 years ago
See the updated example.
If you use wstunnel.server = ( "/wstunnel/" => ( ...
, then you have to update count.html to match,
i.e. "var ws = new WebSocket('ws://localhost:80/wstunnel/');"
RE: echo.pl (for mod_wstunnel) in PHP or Python - Added by andrey_filippov over 2 years ago
Yes, i updated both conf and html, but so far no luck. It still may be some my stupid error. I'll try with minimal conf. BTW is it possible to bind to the socket specified in the lighttpd.conf instead of STDIN/STDOUT?
RE: echo.pl (for mod_wstunnel) in PHP or Python - Added by gstrauss over 2 years ago
BTW is it possible to bind to the socket specified in the lighttpd.conf instead of STDIN/STDOUT?
That is what happens in lighttpd. lighttpd bind()s to the socket specified in lighttpd.conf and sets that listening fd to STDIN_FILENO (0) for the process that lighttpd starts with "bin-path"
. If you do not want lighttpd to bind(), then do not set "bin-path"
. Then, you take responsibility for starting and stopping and running your backend application, including bind()
and listen()
to the address to which you tell lighttpd to connect()
, using "host"
and "port"
, or "socket"
. For example, when using PHP-FPM, you let the PHP-FPM service manage the backend application, and you tell lighttpd to where to connect()
, and you do not set "bin-path"
when using PHP-FPM.
RE: echo.pl (for mod_wstunnel) in PHP or Python - Added by andrey_filippov over 2 years ago
Trying to implement example exactly, I found I do not have mod_proxy compiled, so I'll do that.
Possibility to use wstunnel without bin-path can be ideal for me - I want two sockets for a single server application. One client will be a smartphone with a cardboard stereo adapter like (https://arvr.google.com/cardboard/), the other client - another smartphone held in hands to use as a remote control, and the system itself - our experimental prototype (https://blog.elphel.com/?video=lwir_calibration&time=270).
RE: echo.pl (for mod_wstunnel) in PHP or Python - Added by andrey_filippov over 2 years ago
#lighttpd-proxy.conf server.document-root = "/tmp" # not used in this example #server.bind = "127.0.0.1" # had to comment out as I used http server on a local computer, not in the camera server.port = 8080 server.modules += ("mod_proxy") proxy.server = ( "/" => (( "host" => "127.0.0.1", "port" => "8081" ))) proxy.header = ( "upgrade" => "enable" ) #lighttpd-wstunnel.conf server.document-root = "/tmp" # not used in this example server.bind = "127.0.0.1" server.port = 8081 mimetype.assign = (".txt" => "text/plain", ".html" => "text/html" ) server.modules += ("mod_wstunnel") wstunnel.server = ( "/ws/" => ( ( "socket" => "/tmp/wstunnel.socket", "bin-path" => "/www/pages/echo.pl", "max-procs" => 1 ) ) ) cat /www/pages/echo.pl #!/usr/bin/perl -Tw $SIG{PIPE} = 'IGNORE'; for (my $FH; accept($FH, STDIN); close $FH) { select($FH); $|=1; # $FH->autoflush; print $FH $_ while (<$FH>); } root@elphel393:/www/pages# ps -w | grep "echo\|light" 3964 root 4284 S lighttpd -D -f /etc/lighttpd-wstunnel.conf 3965 root 4040 S {echo.pl} /usr/bin/perl -Tw /www/pages/echo.pl 3967 root 4280 S lighttpd -D -f /etc/lighttpd-proxy.conf drwxrwxrwt 6 root root 120 Jul 21 22:09 .. -rw------- 1 root root 0 Jul 21 22:09 .python-history -rw-r--r-- 1 root root 14 Jul 23 01:37 core_temp -rw-r--r-- 1 root root 73 Jul 23 01:37 core_temp_params -rw-r--r-- 1 root root 170 Jul 22 18:21 ws.log -rw-r--r-- 1 root root 111 Jul 22 23:46 ws_php.log srwxr-xr-x 1 root root 0 Jul 23 01:37 wstunnel.socket-0 #count.html running on a local machine, lighttpd (only 2 instances) - on 192.168.0.41 <!DOCTYPE html> <!-- modified from example in https://github.com/joewalnes/websocketd README.md --> <pre id="log"></pre> <script> // helper function: log message to screen var logelt = document.getElementById('log'); function log(msg) { logelt.textContent += msg + '\n'; } // helper function: send websocket msg with count (1 .. 5) var ll = 0; function send_msg() { if (++ll <= 5) { log('SEND: '+ll); ws.send(ll+'\n'); } } // setup websocket with callbacks var ws = new WebSocket('ws://localhost:8080/ws/'); ws.onopen = function() { log('CONNECT\n'); send_msg(); }; ws.onclose = function() { log('DISCONNECT'); }; ws.onmessage = function(event) { log('RECV: ' + event.data); send_msg(); }; </script>
I just collected all relevant data as it did not work. First with 3-rd lighttpd instance for http server (and my original conf w/o wstunnel), then moved web page to a host computer, and then, after commenting out 'server.bind = "127.0.0.1"' in lighttpd-proxy.conf as I used other system, finally got:
CONNECT SEND: 1 RECV: 1 SEND: 2 RECV: 2 SEND: 3 RECV: 3 SEND: 4 RECV: 4 SEND: 5 RECV: 5
Thanks!
RE: [Solved] echo.pl (for mod_wstunnel) example - Added by andrey_filippov over 2 years ago
Just to admit where my stupid error was (as usually, very far from where I was looking). The counter.html was hosted on the same system, where all the lighttpd instances, backend, but not on my computer. Knowing that the websocket server is on the same system as webserver, I missed wrong for me "localhost" in counter.html .
Replacing
var ws = new WebSocket('ws://localhost:8080/ws/');
with
var ws = new WebSocket('ws://'+location.hostname+':8080/ws/');
fixed all my problems. It may be applicable to others too (and still it does not break the original example).
Andrey
RE: [Solved] echo.pl (for mod_wstunnel) example - Added by gstrauss over 2 years ago
FYI: It would break if the instructions were followed to a tee and the URL loaded in the browser was file:///dev/shm/count.html
, but the file: part seems to have gotten lots from my post.
In any case, it might be better to use your var ws = new WebSocket('ws://'+location.hostname+':8080/ws/');
and modify the instruction to host count.html on the same lighttpd server.
Thanks for the suggestion.
RE: [Solved] echo.pl (for mod_wstunnel) example - Added by andrey_filippov over 2 years ago
Just to thank you again for the great program - after fixing my error, everything worked with my original lighttpd.conf and I also tried without "bin-path" as you suggested. Wrote a PHP program listening to 2 different wstunnel sockets and replying to both using socket_select. Everything worked as expected.