mirror of
https://github.com/c-cube/tiny_httpd.git
synced 2025-12-05 19:00:32 -05:00
remove deps of tiny_httpd_ws
vendoring dbuenzli's code is neat!
This commit is contained in:
parent
a405fb046d
commit
4dce594c32
6 changed files with 204 additions and 9 deletions
|
|
@ -32,8 +32,6 @@
|
|||
(synopsis "Websockets for tiny_httpd")
|
||||
(depends
|
||||
(tiny_httpd (= :version))
|
||||
(base64 (>= 3.0))
|
||||
cryptokit
|
||||
(logs :with-test)
|
||||
(odoc :with-doc)))
|
||||
|
||||
|
|
|
|||
2
echo_ws.sh
Executable file
2
echo_ws.sh
Executable file
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
exec dune exec --display=quiet --profile=release "examples/echo_ws.exe" -- $@
|
||||
|
|
@ -3,5 +3,5 @@
|
|||
(name tiny_httpd_ws)
|
||||
(public_name tiny_httpd_ws)
|
||||
(synopsis "Websockets for tiny_httpd")
|
||||
(private_modules common_)
|
||||
(libraries tiny_httpd base64 cryptokit threads))
|
||||
(private_modules common_ utils_)
|
||||
(libraries tiny_httpd threads))
|
||||
|
|
|
|||
|
|
@ -414,9 +414,8 @@ end) : UPGRADE_HANDLER = struct
|
|||
(* produce the accept key *)
|
||||
let accept =
|
||||
(* yes, SHA1 is broken. It's also part of the spec for websockets. *)
|
||||
let hash = (Cryptokit.Hash.sha1 () [@ocaml.alert "-crypto"]) in
|
||||
Cryptokit.hash_string hash (key ^ "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
|
||||
|> Base64.encode_exn
|
||||
Utils_.sha_1 (key ^ "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
|
||||
|> Utils_.B64.encode ~url:false
|
||||
in
|
||||
|
||||
let headers = [ "sec-websocket-accept", accept ] in
|
||||
|
|
|
|||
198
src/ws/utils_.ml
Normal file
198
src/ws/utils_.ml
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
(* To keep the library lightweight, we vendor base64 and sha1
|
||||
from Daniel Bünzli's excellent libraries. Both of these functions
|
||||
are used only for the websocket handshake, on tiny data
|
||||
(one header's worth).
|
||||
|
||||
vendored from https://github.com/dbuenzli/uuidm
|
||||
and https://github.com/dbuenzli/webs . *)
|
||||
|
||||
module B64 = struct
|
||||
let alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
||||
|
||||
let alpha_url =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
|
||||
|
||||
let encode ~url s =
|
||||
let rec loop alpha len e ei s i =
|
||||
if i >= len then
|
||||
Bytes.unsafe_to_string e
|
||||
else (
|
||||
let i0 = i and i1 = i + 1 and i2 = i + 2 in
|
||||
let b0 = Char.code s.[i0] in
|
||||
let b1 =
|
||||
if i1 >= len then
|
||||
0
|
||||
else
|
||||
Char.code s.[i1]
|
||||
in
|
||||
let b2 =
|
||||
if i2 >= len then
|
||||
0
|
||||
else
|
||||
Char.code s.[i2]
|
||||
in
|
||||
let u = (b0 lsl 16) lor (b1 lsl 8) lor b2 in
|
||||
let c0 = alpha.[u lsr 18] in
|
||||
let c1 = alpha.[(u lsr 12) land 63] in
|
||||
let c2 =
|
||||
if i1 >= len then
|
||||
'='
|
||||
else
|
||||
alpha.[(u lsr 6) land 63]
|
||||
in
|
||||
let c3 =
|
||||
if i2 >= len then
|
||||
'='
|
||||
else
|
||||
alpha.[u land 63]
|
||||
in
|
||||
Bytes.set e ei c0;
|
||||
Bytes.set e (ei + 1) c1;
|
||||
Bytes.set e (ei + 2) c2;
|
||||
Bytes.set e (ei + 3) c3;
|
||||
loop alpha len e (ei + 4) s (i2 + 1)
|
||||
)
|
||||
in
|
||||
match String.length s with
|
||||
| 0 -> ""
|
||||
| len ->
|
||||
let alpha =
|
||||
if url then
|
||||
alpha_url
|
||||
else
|
||||
alpha
|
||||
in
|
||||
loop alpha len (Bytes.create ((len + 2) / 3 * 4)) 0 s 0
|
||||
end
|
||||
|
||||
let sha_1 s =
|
||||
(* Based on pseudo-code of RFC 3174. Slow and ugly but does the job. *)
|
||||
let sha_1_pad s =
|
||||
let len = String.length s in
|
||||
let blen = 8 * len in
|
||||
let rem = len mod 64 in
|
||||
let mlen =
|
||||
if rem > 55 then
|
||||
len + 128 - rem
|
||||
else
|
||||
len + 64 - rem
|
||||
in
|
||||
let m = Bytes.create mlen in
|
||||
Bytes.blit_string s 0 m 0 len;
|
||||
Bytes.fill m len (mlen - len) '\x00';
|
||||
Bytes.set m len '\x80';
|
||||
if Sys.word_size > 32 then (
|
||||
Bytes.set m (mlen - 8) (Char.unsafe_chr ((blen lsr 56) land 0xFF));
|
||||
Bytes.set m (mlen - 7) (Char.unsafe_chr ((blen lsr 48) land 0xFF));
|
||||
Bytes.set m (mlen - 6) (Char.unsafe_chr ((blen lsr 40) land 0xFF));
|
||||
Bytes.set m (mlen - 5) (Char.unsafe_chr ((blen lsr 32) land 0xFF))
|
||||
);
|
||||
Bytes.set m (mlen - 4) (Char.unsafe_chr ((blen lsr 24) land 0xFF));
|
||||
Bytes.set m (mlen - 3) (Char.unsafe_chr ((blen lsr 16) land 0xFF));
|
||||
Bytes.set m (mlen - 2) (Char.unsafe_chr ((blen lsr 8) land 0xFF));
|
||||
Bytes.set m (mlen - 1) (Char.unsafe_chr (blen land 0xFF));
|
||||
m
|
||||
in
|
||||
(* Operations on int32 *)
|
||||
let ( &&& ) = ( land ) in
|
||||
let ( lor ) = Int32.logor in
|
||||
let ( lxor ) = Int32.logxor in
|
||||
let ( land ) = Int32.logand in
|
||||
let ( ++ ) = Int32.add in
|
||||
let lnot = Int32.lognot in
|
||||
let sr = Int32.shift_right in
|
||||
let sl = Int32.shift_left in
|
||||
let cls n x = sl x n lor Int32.shift_right_logical x (32 - n) in
|
||||
(* Start *)
|
||||
let m = sha_1_pad s in
|
||||
let w = Array.make 16 0l in
|
||||
let h0 = ref 0x67452301l in
|
||||
let h1 = ref 0xEFCDAB89l in
|
||||
let h2 = ref 0x98BADCFEl in
|
||||
let h3 = ref 0x10325476l in
|
||||
let h4 = ref 0xC3D2E1F0l in
|
||||
let a = ref 0l in
|
||||
let b = ref 0l in
|
||||
let c = ref 0l in
|
||||
let d = ref 0l in
|
||||
let e = ref 0l in
|
||||
for i = 0 to (Bytes.length m / 64) - 1 do
|
||||
(* For each block *)
|
||||
(* Fill w *)
|
||||
let base = i * 64 in
|
||||
for j = 0 to 15 do
|
||||
let k = base + (j * 4) in
|
||||
w.(j) <-
|
||||
sl (Int32.of_int (Char.code @@ Bytes.get m k)) 24
|
||||
lor sl (Int32.of_int (Char.code @@ Bytes.get m (k + 1))) 16
|
||||
lor sl (Int32.of_int (Char.code @@ Bytes.get m (k + 2))) 8
|
||||
lor Int32.of_int (Char.code @@ Bytes.get m (k + 3))
|
||||
done;
|
||||
(* Loop *)
|
||||
a := !h0;
|
||||
b := !h1;
|
||||
c := !h2;
|
||||
d := !h3;
|
||||
e := !h4;
|
||||
for t = 0 to 79 do
|
||||
let f, k =
|
||||
if t <= 19 then
|
||||
!b land !c lor (lnot !b land !d), 0x5A827999l
|
||||
else if t <= 39 then
|
||||
!b lxor !c lxor !d, 0x6ED9EBA1l
|
||||
else if t <= 59 then
|
||||
!b land !c lor (!b land !d) lor (!c land !d), 0x8F1BBCDCl
|
||||
else
|
||||
!b lxor !c lxor !d, 0xCA62C1D6l
|
||||
in
|
||||
let s = t &&& 0xF in
|
||||
if t >= 16 then
|
||||
w.(s) <-
|
||||
cls 1
|
||||
(w.(s + 13 &&& 0xF)
|
||||
lxor w.(s + 8 &&& 0xF)
|
||||
lxor w.(s + 2 &&& 0xF)
|
||||
lxor w.(s));
|
||||
let temp = cls 5 !a ++ f ++ !e ++ w.(s) ++ k in
|
||||
e := !d;
|
||||
d := !c;
|
||||
c := cls 30 !b;
|
||||
b := !a;
|
||||
a := temp
|
||||
done;
|
||||
(* Update *)
|
||||
h0 := !h0 ++ !a;
|
||||
h1 := !h1 ++ !b;
|
||||
h2 := !h2 ++ !c;
|
||||
h3 := !h3 ++ !d;
|
||||
h4 := !h4 ++ !e
|
||||
done;
|
||||
let h = Bytes.create 20 in
|
||||
let i2s h k i =
|
||||
Bytes.set h k (Char.unsafe_chr (Int32.to_int (sr i 24) &&& 0xFF));
|
||||
Bytes.set h (k + 1) (Char.unsafe_chr (Int32.to_int (sr i 16) &&& 0xFF));
|
||||
Bytes.set h (k + 2) (Char.unsafe_chr (Int32.to_int (sr i 8) &&& 0xFF));
|
||||
Bytes.set h (k + 3) (Char.unsafe_chr (Int32.to_int i &&& 0xFF))
|
||||
in
|
||||
i2s h 0 !h0;
|
||||
i2s h 4 !h1;
|
||||
i2s h 8 !h2;
|
||||
i2s h 12 !h3;
|
||||
i2s h 16 !h4;
|
||||
Bytes.unsafe_to_string h
|
||||
|
||||
(*---------------------------------------------------------------------------
|
||||
Copyright (c) 2008 The uuidm programmers
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
---------------------------------------------------------------------------*)
|
||||
|
|
@ -10,8 +10,6 @@ bug-reports: "https://github.com/c-cube/tiny_httpd/issues"
|
|||
depends: [
|
||||
"dune" {>= "2.9"}
|
||||
"tiny_httpd" {= version}
|
||||
"base64" {>= "3.0"}
|
||||
"cryptokit"
|
||||
"logs" {with-test}
|
||||
"odoc" {with-doc}
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue