Giter VIP home page Giter VIP logo

ocaml-websocket's Introduction

ocaml-websocket — Websocket library for OCaml

The WebSocket Protocol enables two-way communication between a client running untrusted code in a controlled environment to a remote host that has opted-in to communications from that code.

The security model used for this is the origin-based security model commonly used by web browsers. The protocol consists of an opening handshake followed by basic message framing, layered over TCP.

The goal of this technology is to provide a mechanism for browser-based applications that need two-way communication with servers that does not rely on opening multiple HTTP connections (e.g., using XMLHttpRequest or <iframe>s and long polling).

Installation

ocaml-websocket can be installed with opam:

opam install websocket

If you don't use opam please consult the websocket.opam, websocket-lwt.opam and websocket-async.opam files for build instructions.

ocaml-websocket's People

Contributors

acm avatar andrewray avatar avsm avatar bcc32 avatar copy avatar dannywillems avatar j0sh avatar kayceesrk avatar kit-ty-kate avatar kkazuo avatar lostman avatar misterda avatar paurkedal avatar rgrinberg avatar simonjf avatar tizoc avatar ushitora-anqou avatar vbmithr avatar yallop avatar zoggy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ocaml-websocket's Issues

Missing Lwt_io_ext in websocket.cmxs

When dynamically loading the file websocket.cmxs:
undefined symbol: camlLwt_io_ext
It seems the Lwt_io_ext module is not included in websocket.cmxs .

Corrupted frame content + workaround

The content field of a Frame gets corrupted with random data after sending the frame. The workaround is to discard the content string after use or to make a copy before sending. I haven't looked into the problem close enough to determine the source of the problem but here's how to reproduce it:

(*
   File ws_content.ml

   Build with:

     ocamlfind opt -o ws_content \
       ws_content.ml \
       -package websocket.lwt -linkpkg

   Same, in safe-string mode. Requires String.copy or equivalent instead
   of Bytes.copy:

     ocamlfind opt -o ws_content \
       ws_content.ml \
       -package websocket.lwt -linkpkg -safe-string

   Run with:

     ./ws_content
*)

open Lwt

let connect () =
  let uri = Uri.of_string "https://echo.websocket.org" in
  Resolver_lwt.resolve_uri ~uri Resolver_lwt_unix.system >>= fun endp ->
  let ctx = Conduit_lwt_unix.default_ctx in
  Conduit_lwt_unix.endp_to_client ~ctx endp >>= fun client ->
  Websocket_lwt.with_connection ~ctx client uri

let push send content =
  send (Websocket_lwt.Frame.create ~content ())

let push_workaround send content =
  send (Websocket_lwt.Frame.create ~content:(Bytes.copy content) ())

let main () =
  connect () >>= fun (recv, send) ->
  let content = "hello" in
  Printf.printf "before: %S\n%!" content; (* prints "hello" *)
  push send content >>= fun () ->
  Printf.printf "after: %S\n%!" content; (* prints gibberish *)
  exit 0

let () = Lwt_main.run (main ())

The output is something like:

$ ./ws_content 
before: "hello"
after: "\148\157\194\024\147"

while it should be:

$ ./ws_content 
before: "hello"
after: "hello"

The workaround works well enough for our purposes, but it would be good to do something to save time to others. Some suggestions, from easier to better:

  • add a comment next to Frame.create explaining that the frame can't be reused (and perhaps set a flag preventing its reuse)
  • send a copy of the content field (slightly wasteful but imposes no burden on the user)
  • find out why the string gets corrupted and fix that

OCaml version: 4.02.3 on amd64

websocket 0.9 with iocaml

I've ported iocaml to webscoket 0.9 but I seem to be receiving invalid data from the websocket connection.

I wanted to try something a bit simpler to narrow down the issue so was playing with wscat, but I can't get that to work either. Perhaps I am driving the application wrong?

./wscat.native -s 8888
./wscat.native http://localhost:8888

Tracing the library a bit, the server is receiving 2 frames with masked set

    if masked then Lwt_io.eprintf "is masked\n" >> Lwt_io.read_into_exactly ic mask 0 4

but that's all. I'll try testing with websocket 0.8 to see if I can find anything else.

missing websocket.cmi

Hello,

It seems like websocket.cmi is not installed (current HEAD). I don't understand anything in the build system. I modified websocket.install but it was overwritten by the setup.exe -configure :-/

Compilation error

Any idea if lwt API was changed? I can't compile ocaml-websocket:

  • ocamlfind ocamlc -c -g -annot -package lwt.syntax -package lwt -package cryptokit -package cohttp.lwt -package bitstring.syntax -package bitstring -syntax camlp4o -I lib -o lib/websocket.cmo lib/websocket.ml
    File "lib/websocket.ml", line 202, characters 29-42:
    Error: The function applied to this argument has type
    ?buffer_size:int ->
    (Lwt_io.input_channel * Lwt_io.output_channel) Lwt.t
    This argument cannot be applied with label ~setup_socket
    Command exited with code 2.
    Compilation unsuccessful after building 4 targets (3 cached) in 00:00:01.
    E: Failure("Command ''/home/dev/.opam/4.00.1/bin/ocamlbuild' lib/websocket.cma lib/websocket.cmxa lib/websocket.a lib/websocket.cmxs tests/wscat.native -tag debug' terminated with error code 10")
    make: *** [build] Error 1

Any help would be appreciated.

Adding functions to the library

I'd like to add convenient functions in Websocket_lwt. For example:

  • establish_standard_server which would create a server and already handle some frame like in the server function of the wscat.ml example,
  • mk_frame_stream : (unit -> Frame.t Lwt.t) -> Frame.t Lwt_stream.t which would terminate the stream when a close frame is received.

What do you think about that ? I could create a separate library of course, but I think these functions would have their place in Websocket.

ws/wss scheme resolution?

I'm using the following code because the wss scheme doesn't seem to be supported by ocaml-conduit. I found the code for the Resolver_lwt.resolve_uri line in the tests subdirectory so I've been assuming it's proper usage.

let uri = Uri.of_string "wss://echo.websocket.org" in
Resolver_lwt.resolve_uri ~uri Resolver_lwt_unix.system

The result is a Conduit.endp of value ``Unknown "unknown scheme"` on my machine. Later, when I do this and it fails:

Conduit_lwt_unix.endp_to_client
  ~ctx:Conduit_lwt_unix.default_ctx (`Unknown "unknown scheme");;
Exception: Failure "resolution failed: unknown scheme".

Is this a problem with my usage, with ocaml-conduit, with ocaml-websocket, or is it something else?

The workaround I'm using consists in replacing wss by https in the URI as follows:

  let orig_uri = Uri.of_string ws_url in
  let uri = Uri.with_scheme orig_uri (Some "https") in
  ...

websocket.0.6 needs constraint on older cohttp

Due to the refactoring of modules.


The compilation of websocket.0.6 failed.

==== ERROR [while installing websocket.0.6] ====
# opam-version    1.1.0
# os              linux
# command         make
# path            /tmp/ocamlot/ocamlot.work.2013-08-29.166/opam-install/system/build/websocket.0.6
# compiler        system (4.00.1)
# exit-code       2
# env-file        /tmp/ocamlot/ocamlot.work.2013-08-29.166/opam-install/system/build/websocket.0.6/websocket-8363-60459a.env
# stdout-file     /tmp/ocamlot/ocamlot.work.2013-08-29.166/opam-install/system/build/websocket.0.6/websocket-8363-60459a.out
# stderr-file     /tmp/ocamlot/ocamlot.work.2013-08-29.166/opam-install/system/build/websocket.0.6/websocket-8363-60459a.err
### stdout ###
...[truncated]
ocamlfind ocamldep -package ocplib-endian -package lwt.syntax -package lwt.ssl -package lwt -package cryptokit -package cohttp.lwt -syntax camlp4o -modules lib/lwt_io_ext.ml > lib/lwt_io_ext.ml.depends
ocamlfind ocamldep -package ocplib-endian -package lwt.syntax -package lwt.ssl -package lwt -package cryptokit -package cohttp.lwt -syntax camlp4o -modules lib/websocket.mli > lib/websocket.mli.depends
ocamlfind ocamlc -c -g -annot -package ocplib-endian -package lwt.syntax -package lwt.ssl -package lwt -package cryptokit -package cohttp.lwt -syntax camlp4o -I lib -o lib/lwt_io_ext.cmo lib/lwt_io_ext.ml
ocamlfind ocamlc -c -g -annot -package ocplib-endian -package lwt.syntax -package lwt.ssl -package lwt -package cryptokit -package cohttp.lwt -syntax camlp4o -I lib -o lib/websocket.cmi lib/websocket.mli
ocamlfind ocamldep -package ocplib-endian -package lwt.syntax -package lwt.ssl -package lwt -package cryptokit -package cohttp.lwt -syntax camlp4o -modules lib/websocket.ml > lib/websocket.ml.depends
ocamlfind ocamlc -c -g -annot -package ocplib-endian -package lwt.syntax -package lwt.ssl -package lwt -package cryptokit -package cohttp.lwt -syntax camlp4o -I lib -o lib/websocket.cmo lib/websocket.ml
+ ocamlfind ocamlc -c -g -annot -package ocplib-endian -package lwt.syntax -package lwt.ssl -package lwt -package cryptokit -package cohttp.lwt -syntax camlp4o -I lib -o lib/websocket.cmo lib/websocket.ml
File "lib/websocket.ml", line 233, characters 14-28:
Error: Unbound value C.Request.make
Command exited with code 2.
### stderr ###
E: Failure("Command ''/home/avsm/src/git/ocamllabs/worker/ocaml/4.00.1/bin/ocamlbuild' lib/websocket.cma lib/websocket.cmxa lib/websocket.a lib/websocket.cmxs tests/wscat.native -tag debug' terminated with error code 10")
make: *** [build] Error 1

'opam install --verbose --yes websocket.0.6' failed.

OCAMLOT After 237.11s Opam_task.run "opam install --verbose --yes websocket.0.6" failed (4) in 162.23s

Triaged as part of OCamlPro/opam-repository#1029

can't compile and can't install with opam

Hello,

version 0.9.3 does not compile with tls 5.0:

File "tests/wscat.ml", line 49, characters 4-20:
Error: Unbound value Tls_lwt.rng_init

and current version in repository does not compile:

File "lib/websocket.ml", line 108, characters 4-16:
Error: Unbound value read_exactly

I signaled the second problem here: mirage/ocaml-cohttp@e30f292#commitcomment-11742886

I hope there will be new Cohttp/Websocket versions soon, as recent changes in tls/nocrypto/conduit resulted in a nightmare to install cohttp/websocket.

Strange bug that leads to Unix.ECONNREFUSED

Hello,

First thank you for the library. However I'm having some bugs I cannot explain. I manage to make it work between a python server and an ocaml client, but when the ocaml client tries to connect to the well known wscat (sudo apt-get install node-ws) which is run as a server with :

/usr/bin/wscat --listen 8889

I got an error from the client side:

Exception: Unix.Unix_error (Unix.ECONNREFUSED, "connect", "").

The code I'm running is the wscat installed by opam (I also tried to compile it by myself, and the bug stay the same). I checked with netcat the opened port and I find the 8889:

$netstat --listen | grep 8889
tcp        0      0 0.0.0.0:8889            0.0.0.0:*               LISTEN  

Also, I tried to connect to the node wscat using both a node wscat client and a python client running websocket, and both can connect to the server, so it's indeed a bug.

Do you know what could be the reason of such a bug ?

Thank you.

lwt/websocket_cohttp_lwt.mli, line 24, characters 23-40: # Error: Unbound module Cohttp_lwt_body

opam install websocket-lwt
The following actions will be performed:
  ∗  install websocket-lwt 2.10 

=-=- Gathering sources =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
[websocket-lwt.2.10] found in cache

=-=- Processing actions -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
[ERROR] The compilation of websocket-lwt failed at "/home/akochkov/.opam/default/bin/jbuilder build -j 7 -p websocket-lwt @install".

#=== ERROR while compiling websocket-lwt.2.10 =================================#
# context      2.0.0~beta5 | linux/x86_64 | ocaml-system.4.05.0 | git+https://github.com/BinaryAnalysisPlatform/opam-repository.git#testing
# path         ~/.opam/default/.opam-switch/build/websocket-lwt.2.10
# command      ~/.opam/default/bin/jbuilder build -j 7 -p websocket-lwt @install
# exit-code    1
# env-file     ~/.opam/log/websocket-lwt-8849-1872ec.env
# output-file  ~/.opam/log/websocket-lwt-8849-1872ec.out
### output ###
#     ocamldep lwt/websocket_cohttp_lwt.depends.ocamldep-output
#     ocamldep lwt/wscat.depends.ocamldep-output
#     ocamldep lwt/websocket_cohttp_lwt.dependsi.ocamldep-output
#     ocamldep lwt/websocket_lwt.depends.ocamldep-output
#     ocamldep lwt/websocket_lwt.dependsi.ocamldep-output
#       ocamlc lwt/websocket_cohttp_lwt.{cmi,cmti} (exit 2)
# (cd _build/default && /usr/bin/ocamlc.opt -w -40 -g -bin-annot -I /home/akochkov/.opam/default/lib/astring -I /home/akochkov/.opam/default/lib/base -I /home/akochkov/.opam/default/lib/base/caml -I /home/akochkov/.opam/default/lib/base/shadow_stdlib -I /home/akochkov/.opam/default/lib/base64 -I /home/akochkov/.opam/default/lib/bytes -I /home/akochkov/.opam/default/lib/cohttp -I /home/akochkov/[...]
# File "lwt/websocket_cohttp_lwt.mli", line 24, characters 23-40:
# Error: Unbound module Cohttp_lwt_body



=-=- Error report -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
┌─ The following actions failed
│ λ  build websocket-lwt 2.10
└─ 
╶─ No changes have been performed

Expose client IP address

Websocket_lwt.establish_server has the following signature:

val establish_server :
    ?timeout:int ->
    ?stop:unit Lwt.t ->
    ?random_string:Rng.t ->
    ctx:Conduit_lwt_unix.ctx ->
    mode:Conduit_lwt_unix.server ->
    (int -> Cohttp.Request.t -> (unit -> Frame.t Lwt.t) -> (Frame.t -> unit Lwt.t) -> unit Lwt.t) ->
    unit Lwt.t

I would like to get the connecting clients IP address, but the callback doesn't provide this info. It could be provided by passing the Conduit flow or the IP address directly.

If we're already breaking the signature, we could also make a new private type of which a value is passed to the callback, which contains all the information needed to send, receive and the other things, i.e.:

module Connected_client : sig
  type t
  val send : t -> Frame.t -> unit Lwt.t
  val request : t -> Cohttp.Request.t
  val ip : t -> Ipaddr.t
  (**)
end

val establish_server :
    ?timeout:int ->
    ?stop:unit Lwt.t ->
    ?random_string:Rng.t ->
    ctx:Conduit_lwt_unix.ctx ->
    mode:Conduit_lwt_unix.server ->
    (Connected_client.t -> unit Lwt.t) ->
    unit Lwt.t

A way to handle both websocket and regular HTTP requests

Hello,

I'd like to build a server able to act as a regular HTTP server but also as a websocket server, depending on the path of the initial HTTP request. For example, querying http://myserver/ws will make a webserver connection, while querying any other path will make a regular HTTP connection (retrieving pages etc.).
I could not find a way to do so, the only function being available is establish_server. Could there be either a function to switch from a cohttp connection to a websocket connection, or either a parameter to establish_server allowing to stay in regular HTTP on a given condition ?

cmx not installed

Getting this new warning on 4.03.0+flambda:

File "_none_", line 1:
Warning 58: no cmx file was found in path for module Websocket, and its interface was not compiled with -opaque

ocamlfind META file

I installed ocaml-websocket via OPAM, and the version was 0.5. However, the META file seems to be old (version 0.2) and I can't compile programs with ocamlfind (it says it requires bitstring but i can't install it for some reason...). Could you update the META file?

Build failure

I get the following build failure when installing websocket.0.9 with OPAM:

ocamlfind ocamlopt -o setup.exe setup.ml || ocamlfind ocamlc -o setup.exe setup.ml || true
rm -f setup.cmi setup.cmo setup.cmx setup.o
./setup.exe -configure 

Configuration: 
ocamlfind: ........................................... /home/leo/.opam/4.01.0/bin/ocamlfind
ocamlc: .............................................. /home/leo/.opam/4.01.0/bin/ocamlc.opt
ocamlopt: ............................................ /home/leo/.opam/4.01.0/bin/ocamlopt.opt
ocamlbuild: .......................................... /home/leo/.opam/4.01.0/bin/ocamlbuild
Package name: ........................................ websocket
Package version: ..................................... 0.9
os_type: ............................................. Unix
system: .............................................. linux
architecture: ........................................ amd64
ccomp_type: .......................................... cc
ocaml_version: ....................................... 4.01.0
standard_library_default: ............................ /home/leo/.opam/4.01.0/lib/ocaml
standard_library: .................................... /home/leo/.opam/4.01.0/lib/ocaml
standard_runtime: .................................... /home/leo/.opam/4.01.0/bin/ocamlrun
bytecomp_c_compiler: ................................. gcc -fno-defer-pop -Wall -D_FILE_OFFSET_BITS=64 -D_REENTRANT -fPIC
native_c_compiler: ................................... gcc -Wall -D_FILE_OFFSET_BITS=64 -D_REENTRANT
model: ............................................... default
ext_obj: ............................................. .o
ext_asm: ............................................. .s
ext_lib: ............................................. .a
ext_dll: ............................................. .so
default_executable_name: ............................. a.out
systhread_supported: ................................. true
Install architecture-independent files dir: .......... /usr/local
Install architecture-dependent files in dir: ......... $prefix
User executables: .................................... $exec_prefix/bin
System admin executables: ............................ $exec_prefix/sbin
Program executables: ................................. $exec_prefix/libexec
Read-only single-machine data: ....................... $prefix/etc
Modifiable architecture-independent data: ............ $prefix/com
Modifiable single-machine data: ...................... $prefix/var
Object code libraries: ............................... $exec_prefix/lib
Read-only arch-independent data root: ................ $prefix/share
Read-only architecture-independent data: ............. $datarootdir
Info documentation: .................................. $datarootdir/info
Locale-dependent data: ............................... $datarootdir/locale
Man documentation: ................................... $datarootdir/man
Documentation root: .................................. $datarootdir/doc/$pkg_name
HTML documentation: .................................. $docdir
DVI documentation: ................................... $docdir
PDF documentation: ................................... $docdir
PS documentation: .................................... $docdir
findlib_version: ..................................... 1.5.1
is_native: ........................................... true
suffix_program: ...................................... 
Remove a file.: ...................................... rm -f
Remove a directory.: ................................. rm -rf
Turn ocaml debug flag on: ............................ true
Turn ocaml profile flag on: .......................... false
Compiler support generation of .cmxs.: ............... true
OCamlbuild additional flags: ......................... 
Create documentations: ............................... true
Compile tests executable and library and run them: ... false
pkg_lwt: ............................................. /home/leo/.opam/4.01.0/lib/lwt
pkg_lwt_syntax: ...................................... /home/leo/.opam/4.01.0/lib/lwt
pkg_cohttp_lwt: ...................................... /home/leo/.opam/4.01.0/lib/cohttp
pkg_ocplib_endian: ................................... /home/leo/.opam/4.01.0/lib/ocplib-endian
pkg_tls_lwt: ......................................... /home/leo/.opam/4.01.0/lib/tls

./setup.exe -build 
/home/leo/.opam/4.01.0/bin/ocamlopt.opt -I /home/leo/.opam/4.01.0/lib/ocaml/ocamlbuild unix.cmxa /home/leo/.opam/4.01.0/lib/ocaml/ocamlbuild/ocamlbuildlib.cmxa myocamlbuild.ml /home/leo/.opam/4.01.0/lib/ocaml/ocamlbuild/ocamlbuild.cmx -o myocamlbuild
/home/leo/.opam/4.01.0/bin/ocamlfind ocamldep -package cohttp.lwt -package lwt -syntax camlp4o -package lwt.syntax -package ocplib-endian -package tls.lwt -syntax camlp4o -modules lib/lwt_io_ext.ml > lib/lwt_io_ext.ml.depends
/home/leo/.opam/4.01.0/bin/ocamlfind ocamldep -package cohttp.lwt -package lwt -syntax camlp4o -package lwt.syntax -package ocplib-endian -package tls.lwt -syntax camlp4o -modules lib/websocket.mli > lib/websocket.mli.depends
/home/leo/.opam/4.01.0/bin/ocamlfind ocamlc -c -g -annot -package cohttp.lwt -package lwt -syntax camlp4o -package lwt.syntax -package ocplib-endian -package tls.lwt -syntax camlp4o -ppopt -lwt-debug -I lib -o lib/lwt_io_ext.cmo lib/lwt_io_ext.ml
+ /home/leo/.opam/4.01.0/bin/ocamlfind ocamlc -c -g -annot -package cohttp.lwt -package lwt -syntax camlp4o -package lwt.syntax -package ocplib-endian -package tls.lwt -syntax camlp4o -ppopt -lwt-debug -I lib -o lib/lwt_io_ext.cmo lib/lwt_io_ext.ml
File "lib/lwt_io_ext.ml", line 24, characters 31-37:
Error: Unbound value client
Command exited with code 2.

two websocket modules

Hello,

The META file indicates that the package websocket.lwt requires the package websocket. But websocket_lwt.cma already embed websocket.cmo, resulting in this warning:

Warning 31: files .../.opam/4.02.1/lib/websocket/websocket_lwt.cma(Websocket) \
and .../.opam/4.02.1/lib/websocket/websocket.cma(Websocket) both define \
a module named Websocket

I think websocket.cmo should not be included in websocket_lwt.cma and let ocamlfind add it at lik time using the dependencies given in META.

There is the same problem with websocket_lwt.cmxa including both websocket.cmx and websocket_lwt.cmx but in this case this is an error instead of a warning.

Add tests/examples using secure websockets

Since ocaml-websocket uses ocaml-conduit, in theory it should support secure (HTTPS) websockets out-of-the-box. In practice, however, I've been unable to get even simple examples to run (see this message). I think a lot of headaches could be spared if such a simple example were shipped with the library (a secure version of the wscat example, for instance).

core is optional in opam file but required to compile

Hello,

the core package (through async) seems optional according to the opam file but it is required to compile or else the following error occurs:

...
# + ocamlfind ocamldep -package core -package containers -package cohttp -package cohttp.lwt -package conduit -package lwt -package lwt.ppx -package nocrypto.lwt -package ppx_deriving -modules tests/upgrade_connection.ml > tests/upgrade_connection.ml.depends
# ocamlfind: Package `core' not found
# Command exited with code 2.

Default value of check_request

Since release 2.7 Websocket_lwt.establish_server has a check_request parameter. This is good, except that it has a default value: check_origin_with_host. This is problematic when the server is behind a WS proxy because this control will fail and the resulting exception does not give a lot of information (so it took me some time to find it).

Moreover, since the on_exc parameter has no default handler, the exception Protocol_error "Bad headers" was raised and just shut down the websocker server.

So I would suggest: either

  • set no default value for check_request and on_exc or
  • keep the same check_origin_with_hostdefault but in this case set a more informative error message and set a default on_exc handler.

Add license

Just noticed that the library doesn't have a license yet.

Corrupted content of received frames

Following my comment in #58, here is a repro case:

  • Compile tests/wscat.ml
  • run the server: ./wscat -loglevel 3 -s http://localhost:8080/
  • run the client: ./wscat -loglevel 3 http://localhost:8080/
  • enter a long enough string then press enter: sdknklqsdfklfnsdfklqsdnfkqsjdfljqsdklfjqsdmklfjqsmkljfmklqsdjfkljqsdfkljqsdkfjmklqsdjfklqsdjmfklqsdjmfkljqsdmklfjqsdmklfjqsklfjklsqdjfklqsdjfklqsdjmfkljqsdklfjsdklqfjqsdjfmklqsdjflsjdfjfmklqsdjfklqsdjfkljsdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

Here is the server output:

wscat: wscat: endp = (TCP ((V4 127.0.0.1) 8080))
wscat: wscat: server = (TCP (Port 8080))
wscat: wscat: Connection from client id 0
wscat: wscat: Client 0: { Websocket.Frame.opcode = Websocket.Frame.Opcode.Text; extension = 0;
wscat: wscat:   final = true;
wscat: wscat:   content =
wscat: wscat:   ").\127E1&eX>,\127G<$gO<!xZ).zM1;gA>,xA+9p@6,~Z).y@6,~Z)'\127G0,y@6;gO0,\127G0;gO<!xA+9p@< y@6;gO0,\127G+9pA7,\127G+9pA7,\127G0;gO7!xM0;gO7!xM0;g@6,~@69eO0,\127G+9pA<!xZ).~F<!xA+9p@6,~X>!xZ< eX> rF1&eX> rG) pM0,y@6;gO0,\127G+9pA<!xA).rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<"
wscat: wscat:   }

and the client output:

> ).E1&eX>,G<$gO<!xZ).zM1;gA>,xA+9p@6,~Z).y@6,~Z)'G0,y@6;gO0,G0;gO<!xA+9p@< y@6;gO0,G+9pA7,G+9pA7,G0;gO7!xM0;gO7!xM0;g@6,~@69eO0,G+9pA<!xZ).~F<!xA+9p@6,~X>!xZ< eX> rF1&eX> rG) pM0,y@6;gO0,G+9pA<!xA).rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<,rM<

Sending the same string again to the client, here is the server output:

wscat: wscat: Client 0: { Websocket.Frame.opcode = Websocket.Frame.Opcode.Text; extension = 0;
wscat: wscat:   final = true;
wscat: wscat:   content =
wscat: wscat:   "\234\200w\178\242\192m\175\253\202w\176\255\194o\184\255\199p\173\234\200r\186\242\221o\182\253\202p\182\232\223x\183\245\202v\173\234\200q\183\245\202v\173\234\193w\176\243\202q\183\245\221o\184\243\202w\176\243\221o\184\255\199p\182\232\223x\183\255\198q\183\245\221o\184\243\202w\176\232\223x\182\244\202w\176\232\223x\182\244\202w\176\243\221o\184\244\199p\186\243\221o\184\244\199p\186\243\221o\183\245\202v\183\245\223m\184\243\202w\176\232\223x\182\255\199p\173\234\200v\177\255\199p\182\232\223x\183\245\202v\175\253\199p\173\255\198m\175\253\198z\177\242\192m\175\253\198z\176\234\198x\186\243\202q\183\245\221o\184\243\202w\176\232\223x\182\255\199p\182\234\200z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255\202z\186\255"
wscat: wscat:   }

So it seems that there is a corrupted buffer somewhere.

Async support

Hi,

I'd love to use your package as part of an application I'm currently writing that makes heavy use of Async and Cohttp. Is there any plan to add Async support the same way that Cohttp does by abstracting away the logic and offering both Lwt and Async as options?

Thanks

Don't install a module named Rng

Currently this library installs a module named Rng, which can cause problems with other libraries that might choose this name.

utop [1]: #require "websocket.async";;
utop [2]: Rng.cryptokit;;
- : Cryptokit.Random.rng -> Rng.t = <fun>

Optional TLS Support

Would be nice if the TLS support was optional, because forcing TLS introduces a lot of other dependencies, including on external C shared libs (libgmp), which affects other parts of the stack in undesirable ways (conduit/cohttp).

Per-project OPAM switches on my side would mitigate this issue, but since TLS isn't required for websockets, it'd be nice to use this library without dragging in all a bunch of extra stuff. Might make the API cleaner as well.

For example, downloading ocaml-websockets causes conduit/cohttp to be re-compiled with the extra TLS dependencies, which "infects" all other cohttp projects with those extra dependencies, even if TLS is not being used. This is especially problematic for binary portability if any external shared libraries are not typically installed by default in a base system -- libgmp is not.

Connection problem with firefox

Firefox fails to connect via websocket, while chrome succeeds.
I could track the problem down to this condition in websocket_lwt.ml, in function establish_server:

  && List.mem "upgrade"
  @@ List.map String.lowercase @@ C.Header.get_multi headers "connection"

If I remove this condition, then the connection with Firefox works. By printing the contents of the "connection" headers, Firefox sends keep-alive, Upgrade, while Chrome only send Upgrade, thus explaining why the condition fails with Firefox. Maybe splitting the string on commas and testing each element of the resulting list would be more robust ?

Missing lwt_io_ext.cmi

Hello,

I just opam-upgraded to websocket 0.9.1 and lwt_io_ext.cmi is not installed. All i have is:

META         websocket.a    websocket.cmi   websocket.cmx   websocket.cmxs
opam.config  websocket.cma  websocket.cmti  websocket.cmxa  websocket.mli

Prevent fd leakage

Currently the functions returning streams lack a way to
close the underlying connection, causing fds to leak.

async_ssl / websocket.2.9 need an upper bound somewhere

Latest opam repository fails to combine websocket and async_ssl out of the box:

#=== ERROR while installing websocket.2.9 =====================================#
# opam-version 1.2.2
# os           linux
# command      ocaml pkg/build.ml native=true native-dynlink=true lwt=false async=true async_ssl=true nocrypto=false cryptokit=false test=false
# path         /home/opam/.opam/system/build/websocket.2.9
# compiler     system (4.04.0)
# exit-code    10
# env-file     /home/opam/.opam/system/build/websocket.2.9/websocket-27-6ed0d4.env
# stdout-file  /home/opam/.opam/system/build/websocket.2.9/websocket-27-6ed0d4.out
# stderr-file  /home/opam/.opam/system/build/websocket.2.9/websocket-27-6ed0d4.err
### stdout ###
# [...]
# File "lib/websocket_async.ml", line 252, characters 28-852:
# Error: The function applied to this argument has type
#          'a Async.Std.Deferred.Or_error.t ->
#          ('a -> 'b Async.Std.Deferred.Or_error.t) ->
#          'b Core_kernel.Std.Or_error.t Async_kernel.Types.Deferred.t
# This argument cannot be applied with label ~f
# Command exited with code 2.
# + ocamlfind ocamlopt -package unix -package ocamlbuild -linkpkg -package cppo_ocamlbuild myocamlbuild.ml /home/opam/.opam/system/lib/ocamlbuild/ocamlbuild.cmx -o myocamlbuild
# File "_none_", line 1:
# Warning 58: no cmx file was found in path for module Ocamlbuild_cppo, and its interface was not compiled with -opaque

versions of async_ssl are:

async                   113.33.00  Monadic concurrency library
async_extra        113.33.00+4.03  Monadic concurrency library
async_kernel            113.33.00  Monadic concurrency library
async_rpc_kernel        113.33.00  Platform-independent core of Async RPC library
async_ssl               113.33.07  An Async-pipe-based interface with OpenSSL.
async_unix         113.33.00+4.03  Monadic concurrency library

cohttp.1.0.0 support

It seems that there are a few changes in cohttp.1.0.0 compared to 0.99 (mostly Cohttp_lwt_body deprecation in favor of Cohttp_lwt.Body).

How to detect closed connection

It seems to me there's no way to detect when a connection is closed. On this line the exception Close_frame_received is raised, but the exception is not exported in the .mli. In my testing it seems the exception sometimes is raised twice, and my guess is when 1) the close frame is received, 2) when the underlying socket is closed.

Error with 'opam install websocket' (v2.1)

Hello,
with $ opam install websocket

I have :
=== ERROR while installing websocket.2.1 =====================================#
opam-version 1.2.2
os linux
compiler 4.02.3
[...]

File "lib/websocket_lwt.ml", line 30, characters 6-22:
Error: Unbound value CU.Request.write
Command exited with code 2.

The following actions failed
∗ install websocket 2.1
No changes have been performed

This error occurs after the last cohttp update (from v0.18.3 to 0.19.0)

websocket 2.9 install fails

=-=- Processing actions -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=  🐫
∗  installed stringext.1.4.3
∗  installed magic-mime.1.0.0
∗  installed uchar.0.0.1
∗  installed ocplib-endian.1.0
∗  installed topkg.0.9.0
∗  installed base64.2.1.2
∗  installed astring.0.8.3
∗  installed cmdliner.1.0.0
∗  installed ipaddr.2.7.2
∗  installed fmt.0.8.2
∗  installed uri.1.9.2
∗  installed logs.0.6.2
∗  installed cstruct.2.3.2
∗  installed conduit.0.15.0
∗  installed cohttp.0.22.0
[ERROR] The compilation of websocket failed at "ocaml pkg/build.ml native=true native-dynlink=true lwt=true async=true async_ssl=false nocrypto=false cryptokit=false test=false".

#=== ERROR while installing websocket.2.9 =====================================#
# opam-version 1.2.2
# os           darwin
# command      ocaml pkg/build.ml native=true native-dynlink=true lwt=true async=true async_ssl=false nocrypto=false cryptokit=false test=false
# path         /Users/alin/.opam/system/build/websocket.2.9
# compiler     system (4.04.0)
# exit-code    10
# env-file     /Users/alin/.opam/system/build/websocket.2.9/websocket-94036-7355b0.env
# stdout-file  /Users/alin/.opam/system/build/websocket.2.9/websocket-94036-7355b0.out
# stderr-file  /Users/alin/.opam/system/build/websocket.2.9/websocket-94036-7355b0.err
### stdout ###
# [...]
# File "lib/websocket_async.ml", line 252, characters 28-852:
# Error: The function applied to this argument has type
#          'a Async.Std.Deferred.Or_error.t ->
#          ('a -> 'b Async.Std.Deferred.Or_error.t) ->
#          'b Core_kernel.Std.Or_error.t Async_kernel.Types.Deferred.t
# This argument cannot be applied with label ~f
# Command exited with code 2.
# + ocamlfind ocamlopt -package unix -package ocamlbuild -linkpkg -package cppo_ocamlbuild myocamlbuild.ml /Users/alin/.opam/system/lib/ocamlbuild/ocamlbuild.cmx -o myocamlbuild
# File "_none_", line 1:
# Warning 58: no cmx file was found in path for module Ocamlbuild_cppo, and its interface was not compiled with -opaque

I can gather more details on this failure if needed.

Thanks.

Install fails with 4.04.0 compiler

Hi,
Disclaimer not an ocaml person here, just wanted to compile a package that depends on websocket.2.9 and ran into problems.

Tried to install websocket.2.9 on armhf (Raspberry Pi) with 4.04.0 first which failed, then tried installing it on amd64 with 4.02.0 which worked, but as panama requires 4.04.0 I updated to that and now I get the same error message as on the Raspberry Pi when compiling websocket.

I deduct that that means there's a problem with websocket.2.9 but maybe I'm also missing a native dependency or something, any help would be greatly appreciated.

[ERROR] The compilation of websocket failed at "ocaml pkg/build.ml native=true
        native-dynlink=true lwt=true async=false async_ssl=false nocrypto=false
        cryptokit=false test=false".

#=== ERROR while installing websocket.2.9 =====================================#
# opam-version 1.2.2
# os           linux
# command      ocaml pkg/build.ml native=true native-dynlink=true lwt=true async=false async_ssl=false nocrypto=false cryptokit=false test=false
# path         /home/nini/.opam/4.04.0/build/websocket.2.9
# compiler     4.04.0
# exit-code    10
# env-file     /home/nini/.opam/4.04.0/build/websocket.2.9/websocket-31102-88c6ff.env
# stdout-file  /home/nini/.opam/4.04.0/build/websocket.2.9/websocket-31102-88c6ff.out
# stderr-file  /home/nini/.opam/4.04.0/build/websocket.2.9/websocket-31102-88c6ff.err
### stdout ###
# Error: This function has type
# [...]
#          (Conduit_lwt_unix.flow ->
#           Conduit_lwt_unix.ic ->
#           Conduit_lwt_unix.oc -> unit Conduit_lwt_unix.io) ->
#          unit Conduit_lwt_unix.io
#        It is applied to too many arguments; maybe you forgot a `;'.
# Command exited with code 2.
# + ocamlfind ocamlopt -package unix -package ocamlbuild -linkpkg -package cppo_ocamlbuild myocamlbuild.ml /home/nini/.opam/4.04.0/lib/ocamlbuild/ocamlbuild.cmx -o myocamlbuild
# File "_none_", line 1:
# Warning 58: no cmx file was found in path for module Ocamlbuild_cppo, and its interface was not compiled with -opaque

Default Rng generator

Hello,

Websocket_lwt.establish_standard_server now takes a ~g parameter. Would it be possible to make it optional and use !Nocrypto.Rng.generator as in various places in tests/*ml ? This would prevent breaking API...

Compilation error

olle@olle-ThinkPad-X220:~/ocaml/ocaml-websocket-master$ sudo ocaml setup.ml -build
Finished, 0 targets (0 cached) in 00:00:00.

  • ocamlfind ocamlc -where > /home/olle/ocaml/ocaml-websocket-master/_build/ocamlc.where
    ocamlfind: [WARNING] The DLL dllmysql_stubs.so occurs in multiple directories: /usr/lib/ocaml/stublibs
    ocamlfind: [WARNING] The DLL dllmysql_stubs.so occurs in multiple directories: /usr/local/lib/ocaml/3.12.1/stublibs
  • ocamlfind ocamlc -c -g -annot -package lwt.syntax -package lwt -package cryptokit -package bitstring.syntax -package bitstring -syntax camlp4o -I lib -o lib/websocket.cmi lib/websocket.mli
    ocamlfind: [WARNING] The DLL dllmysql_stubs.so occurs in multiple directories: /usr/lib/ocaml/stublibs
    ocamlfind: [WARNING] The DLL dllmysql_stubs.so occurs in multiple directories: /usr/local/lib/ocaml/3.12.1/stublibs

File "lib/websocket.mli", line 52, characters 22-27:
Error: Unbound module Uri

Command exited with code 2.
Compilation unsuccessful after building 2 targets (1 cached) in 00:00:00.
E: Failure("Command ''/usr/bin/ocamlbuild' lib/websocket.cma lib/websocket.cmxa lib/websocket.a lib/websocket.cmxs tests/wscat.native -tag debug' terminated with error code 10")

How to include uri package? I've got it installed in ocamlfind and all.

Regards
Olle

End_of_file exception when doing `send`

I'm trying to do something like this, just before this line: https://github.com/vbmithr/ocaml-websocket/blob/master/lwt/wscat.ml#L27

...
let _ = send @@ Frame.create ~content:"some stuff here" () in
Lwt_io.printf "> %s\n> %!" fr.content
... 

and I'm getting an End_of_file exception;
wasn't able to find anything within the documentation, or the code, that would help me to prevent that...
What I'm trying to do, in fact, is to have a periodic sender, that once at, let's say 10 seconds, will send some message to the server, and I imagine that send is used for that.
Any idea what am I missing here?

Thanks.

websockets + react hangs on frequent messages

I'm not sure whether I should post this here or in react's issue tracker, but I have an issue with using websockets with react and cohttp. I have an application, which listens to zmq socket for a json message, stores it in the database and notifies client about received message through websocket. I use react event stream to represent my stream of messages and map it on notification event stream with E.map. It works fine when messages are either appearing relatively rarely or messages are short and simple. When the messages are big (and require a long deserialization) and appear quite often (say 5 times a second) the whole event stream hangs.

I'm not sure but I suspect that due to performance issue some react invariant becomes broken which leads to such behaviour. I'm posting it here since the problem occurs only when I use websockets, in other cases even relatively heavy computations does not have such effect.

I've made a trivial example to depict the issue.

https://github.com/Freyr666/socktest

Thanks ahead.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.