12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273(*
* Copyright (c) 2016-2018 Maciej Wos <maciej.wos@gmail.com>
* Copyright (c) 2012-2018 Vincent Bernardoff <vb@luminar.eu.org>
*
* Permission to use, copy, modify, and 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.
*
*)openLwt.InfixopenWebsocketmoduleLwt_IO=Websocket.Make(Cohttp_lwt_unix.IO)letsend_framesstreamoc=letbuf=Buffer.create128inletsend_framefr=Buffer.clearbuf;Lwt_IO.write_frame_to_buf~mode:Serverbuffr;Lwt_io.writeoc@@Buffer.contentsbufinLwt_stream.iter_ssend_framestreamletread_framesicochandler_fn=letread_frame=Lwt_IO.make_read_frame~mode:Servericocinletrecinner()=read_frame()>>=Lwt.wrap1handler_fn>>=innerininner()letupgrade_connectionrequestincoming_handler=letheaders=Cohttp.Request.headersrequestinbeginmatchCohttp.Header.getheaders"sec-websocket-key"with|None->Lwt.fail_invalid_arg"upgrade_connection: missing header `sec-websocket-key`"|Somekey->Lwt.returnkeyend>>=funkey->lethash=b64_encoded_sha1sum(key^websocket_uuid)inletresponse_headers=Cohttp.Header.of_list["Upgrade","websocket";"Connection","Upgrade";"Sec-WebSocket-Accept",hash]inletresp=Cohttp.Response.make~status:`Switching_protocols~encoding:Cohttp.Transfer.Unknown~headers:response_headers~flush:true()inletframes_out_stream,frames_out_fn=Lwt_stream.create()inletficoc=Lwt.pick[(* input: data from the client is read from the input channel
* of the tcp connection; pass it to handler function *)read_framesicocincoming_handler;(* output: data for the client is written to the output
* channel of the tcp connection *)send_framesframes_out_streamoc;]inLwt.return(`Expert(resp,f),frames_out_fn)