Giter VIP home page Giter VIP logo

Comments (8)

andreas avatar andreas commented on August 13, 2024

I've looked further into this, and it appears to be quite easy, actually. Here's the diff between lwt and a local copy I've made Mirage-compatible:

------ lwt/websocket_lwt.ml
++++++ mirage/websocket_mirage.ml
@|-23,1 +23,1 ============================================================
-|module Lwt_IO = IO(Cohttp_lwt_unix.IO)
+|module Lwt_IO = IO(Cohttp_lwt.IO)
@|-26,2 +26,2 ============================================================
-|module Request = Cohttp.Request.Make(Cohttp_lwt_unix.IO)
+|module Request = Cohttp.Request.Make(Cohttp_lwt.IO)
-|module Response = Cohttp.Response.Make(Cohttp_lwt_unix.IO)
+|module Response = Cohttp.Response.Make(Cohttp_lwt.IO)
@|-35,1 +35,1 ============================================================
-|    flow: Conduit_lwt_unix.flow;
+|    flow: Conduit_mirage.Flow.flow;
@|-95,1 +95,1 ============================================================
-|    | Vchan of Conduit_lwt_unix.vchan_flow
+|    | Vchan of Conduit_mirage.vchan_flow
@|-99,3 +99,3 ============================================================
-|    | Conduit_lwt_unix.TCP tcp_flow ->
+|    | Conduit_mirage.TCP tcp_flow ->
-|      TCP (tcp_flow.Conduit_lwt_unix.ip, tcp_flow.Conduit_lwt_unix.port)
+|      TCP (tcp_flow.Conduit_mirage.ip, tcp_flow.Conduit_mirage.port)
-|    | Conduit_lwt_unix.Domain_socket { path; _ } ->
+|    | Conduit_mirage.Domain_socket { path; _ } ->
@|-103,1 +103,1 ============================================================
-|    | Conduit_lwt_unix.Vchan flow ->
+|    | Conduit_mirage.Vchan flow ->
@|-110,1 +110,1 ============================================================
-|  let open Conduit_lwt_unix in
+|  let open Conduit_mirage in
@|-144,1 +144,1 ============================================================
-|    ?(ctx=Conduit_lwt_unix.default_ctx)
+|    ?(ctx=Conduit_mirage.default_ctx)
@|-155,1 +155,1 ============================================================
-|    Conduit_lwt_unix.connect ~ctx client >>= fun (flow, ic, oc) ->
+|    Conduit_mirage.connect ~ctx client >>= fun (flow, ic, oc) ->
@|-214,1 +214,1 ============================================================
-|    ?(ctx=Conduit_lwt_unix.default_ctx) ~mode react =
+|    ?(ctx=Conduit_mirage.default_ctx) ~mode react =
@|-256,1 +256,1 ============================================================
-|  Conduit_lwt_unix.serve ?on_exn ?timeout ?stop ~ctx ~mode begin fun flow ic oc ->
+|  Conduit_mirage.serve ?on_exn ?timeout ?stop ~ctx ~mode begin fun flow ic oc ->
@|-273,1 +273,1 ============================================================
-|    ?on_exn ?check_request ?(ctx=Conduit_lwt_unix.default_ctx) ~mode react =
+|    ?on_exn ?check_request ?(ctx=Conduit_mirage.default_ctx) ~mode react =

------ lwt/websocket_cohttp_lwt.ml
++++++ mirage/websocket_cohttp_mirage.ml
@|-21,1 +21,1 ============================================================
-|module Lwt_IO = Websocket.IO(Cohttp_lwt_unix.IO)
+|module Lwt_IO = Websocket.IO(Cohttp_mirage.IO)
@|-63,1 +63,1 ============================================================
-|          | Conduit_lwt_unix.TCP tcp ->
+|          | Mirage_conduit.TCP tcp ->

Though we can certainly duplicate a bit of code, the question is whether this warrants extracting the common code to a functor.

@vbmithr, how would you prefer to approach this? I'm happy to help with the implementation.

Finally, Websocket_cohttp_lwt does not reveal that Frame is an alias of Websocket.Frame. This makes it hard to use the library in an IO-agnostic manner since Websocket.Frame and Websocket_cohttp_lwt.Frame are not considered equal. Any concerns about simply having module Frame = Websocket.Frame in Websocket_cohttp_lwt (like for Websocket_async)?

from ocaml-websocket.

vbmithr avatar vbmithr commented on August 13, 2024

I just happened to look into this right now. I'm trying to see what I can.

from ocaml-websocket.

vbmithr avatar vbmithr commented on August 13, 2024

Conduit_mirage interfaces are not compatible with Conduit_lwt_unix unfortunately. Straightforword functorization is not possible. It would be nice if Conduit would be more homogenous.
For the last question, yes sure, it should actually been this way.

from ocaml-websocket.

vbmithr avatar vbmithr commented on August 13, 2024

Ok, I have refactored to the maximum. Either copy Websocket_lwt_unix to make a Mirage version or better, try to put all common parts in a functor with an argument that would abstract out the if it's Mirage or UNIX… this would probably be better done in Conduit itself…

from ocaml-websocket.

andreas avatar andreas commented on August 13, 2024

Thanks for the refactoring, @vbmithr!

So my initial diff was terribly wrong, and this turned out be a much bigger rabbit hole than I anticipated 😅

After looking more closely at the code from a perspective of adding a Mirage-compatible websocket server without duplicating code, I made the following observations:

  • The current Lwt implementation is not using Cohttp_lwt_unix.Server to handle reading requests and writing responses, but rather works at the connection level using Conduit_lwt_unix. This appears to make some things more complicated, since the server-loop has to be reimplemented.
  • Websocket_cohttp_lwt is not used for upgrading requests in Websocket_lwt_unix, so the upgrade logic appears to be implemented twice (slightly differently).
  • Handling clients with Websocket_lwt_unix requires a function Connected_client.t -> unit Lwt.t, while Websocket_cohttp_lwt handles clients via a function for receiving frames (Frame.t -> unit) and another function for sending frames (Frame.t option -> unit). This means the Connected_client abstraction is not reused.

I might be missing something, or maybe there's a reason why the API and implementation has ended up like this. I'd be curious to learn if you have the time to elaborate. I've started dabbling with implementing some changes to address the above, but it's still unfinished. Unfortunately these changes are quite intrusive and can probably not be backwards-compatible 😞

from ocaml-websocket.

vbmithr avatar vbmithr commented on August 13, 2024

from ocaml-websocket.

vbmithr avatar vbmithr commented on August 13, 2024

from ocaml-websocket.

andreas avatar andreas commented on August 13, 2024

A quick follow-up on this issue...

I've worked on adding "response actions" to Cohttp (merged PR), which exposes the underlying input/output channels to the request handler. For the websocket server part of this repo, it means:

  1. All the HTTP request handling logic can be removed.
  2. With light functorization, the library can be agnostic to Lwt/Async.

Instead of trying to make modifications directly to this repo, I've included an edited version of websocket handling logic in graphql-cohttp with the above ideas in mind (work-in-progress PR). I think it's turned out rather well, but there are more details I'd like to iron out before trying to contribute upstream.

If you have any input or ideas, I'd be happy to hear.

from ocaml-websocket.

Related Issues (20)

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.