1 | #! perl # mandatory depends=tcp |
1 | #! perl # mandatory depends=tcp |
2 | |
2 | |
3 | # websocket server on base port, called by tcp.ext |
3 | # websocket protocol server, actually only the handshake part |
|
|
4 | |
|
|
5 | use Digest::SHA1 (); |
4 | |
6 | |
5 | # websocket requests can be very long, and we want the tcp code to buffer for us |
7 | # websocket requests can be very long, and we want the tcp code to buffer for us |
6 | our $detector = ext::tcp::register websocket => 4096, sub { |
8 | our $detector = ext::tcp::register websocket => 4096, sub { |
7 | m{^(?:(?i)GET) /ws .*\015\012\015\012}s |
9 | m{^(?i:GET) \ (?i:http://[^/]+)? /ws \ (?:(?i)HTTP/[0-9\.]+)}xs |
8 | }, sub { |
10 | }, sub { |
|
|
11 | my ($id, $fh, $buf) = @_; |
|
|
12 | |
|
|
13 | $buf =~ /^Sec-WebSocket-Version\s*:\s*([0-9]+)/mi |
|
|
14 | or return; |
|
|
15 | my $version = $1; # 8 ff10, 13 rfc |
|
|
16 | |
|
|
17 | $buf =~ /^Sec-WebSocket-Key\s*:\s*(\S+)/mi |
|
|
18 | or return; |
|
|
19 | my $key = $1; |
|
|
20 | |
|
|
21 | if ($version != 8 && $version != 13) { |
|
|
22 | syswrite $fh, "HTTP/1.1 400 version mismatch\015\012" |
|
|
23 | . "connection: close\015\012" |
|
|
24 | . "sec-websocket-version: 13, 8\015\012\015\012"; |
|
|
25 | return; |
|
|
26 | } |
|
|
27 | |
|
|
28 | my $res = "HTTP/1.1 101 upgrading\015\012" |
|
|
29 | . "connection: upgrade\015\012" |
|
|
30 | . "upgrade: websocket\015\012" |
|
|
31 | . "sec-websocket-accept: " . (Digest::SHA1::sha1_base64 $key . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11") . "=\015\012" |
|
|
32 | . "\015\012"; |
|
|
33 | |
|
|
34 | syswrite $fh, $res; |
|
|
35 | |
|
|
36 | my $ns = cf::client::create fileno $_[1], $_[0]; |
|
|
37 | $ns->ws_version ($version); |
|
|
38 | $ns->run; |
9 | }; |
39 | }; |
10 | |
40 | |