diff --git a/src/ws/dune b/src/ws/dune index 7fc4745c..2ac87ea4 100644 --- a/src/ws/dune +++ b/src/ws/dune @@ -4,4 +4,8 @@ (public_name tiny_httpd_ws) (synopsis "Websockets for tiny_httpd") (private_modules common_ utils_) + (foreign_stubs + (language c) + (names tiny_httpd_ws_stubs) + (flags :standard -std=c99 -fPIC -O2)) (libraries tiny_httpd threads)) diff --git a/src/ws/tiny_httpd_ws.ml b/src/ws/tiny_httpd_ws.ml index fb8e7af6..c0cd7b2e 100644 --- a/src/ws/tiny_httpd_ws.ml +++ b/src/ws/tiny_httpd_ws.ml @@ -272,14 +272,14 @@ module Reader = struct self.header.payload_len self.header.mask);*) () + external apply_masking_ : bytes -> bytes -> int -> int -> unit + = "tiny_httpd_ws_apply_masking" + [@@noalloc] (** Apply masking to the parsed data *) - let apply_masking ~mask_key (buf : bytes) off len : unit = - for i = 0 to len - 1 do - let c = Bytes.get buf (off + i) in - let c_m = Bytes.unsafe_get mask_key (i land 0b11) in - let c_xor = Char.chr (Char.code c lxor Char.code c_m) in - Bytes.set buf (off + i) c_xor - done + + let[@inline] apply_masking ~mask_key (buf : bytes) off len : unit = + assert (off >= 0 && off + len <= Bytes.length buf); + apply_masking_ mask_key buf off len let read_body_to_string (self : t) : string = let len = self.header.payload_len in diff --git a/src/ws/tiny_httpd_ws_stubs.c b/src/ws/tiny_httpd_ws_stubs.c new file mode 100644 index 00000000..779e255a --- /dev/null +++ b/src/ws/tiny_httpd_ws_stubs.c @@ -0,0 +1,21 @@ + +#include +#include +#include + +CAMLprim value tiny_httpd_ws_apply_masking(value _mask_key, value _buf, + value _offset, value _len) { + CAMLparam4(_mask_key, _buf, _offset, _len); + + char const *mask_key = String_val(_mask_key); + char *buf = Bytes_val(_buf); + intnat offset = Int_val(_offset); + intnat len = Int_val(_len); + + for (intnat i = 0; i < len; ++i) { + char c = buf[offset + i]; + char c_m = mask_key[i & 0x3]; + buf[offset + i] = c ^ c_m; + } + CAMLreturn(Val_unit); +}