lpil / mug

🍺 A TCP client for Gleam!
22 stars 3 forks source link

Support for unix sockets #8

Open nnuuvv opened 1 month ago

nnuuvv commented 1 month ago

As per the conversation in discord; image

cmkarlsson commented 1 month ago

I took a stab at implementing this. The change in mug is no problem. My proposed solution is to handle the host name as a gleam String and then to check if it starts with "/" or "@" and if so handle it as a unix socket or a unix abstract socket respectively. The idea came from how elixir postgres handles connecting to unix sockets.

The only design decision is if this should be handled in the gleam code or in the ffi. To me it seems easier to do by just modifying the ffi.

connect(Host0, Port0, Opts, Timeout) ->
  {Host1, Port1} =  case Host0 of
    "/" ++ _Path -> {{local, Host0}, 0};
    "@" ++ Path -> {{local, [0|Path]}, 0};
    Host0 -> {Host0, Port0}
  end,
  gen_tcp:connect(Host1, Port1, Opts, Timeout).

The alternative is to handle this in gleam, which I also tried. It requires a tagged type which will require an wrapped connect methods (which could accept {local, string()|binary()} or {hostname, string()}) or to have multiple external connectors and handle in gleam.

Another thing to consider is that the unix socket argument to connect accepts both an erlang string and an erlang binary. The thing is that they are handled differently. The binary is passed as is while the string is encoded using the file-system encoding (more here: https://www.erlang.org/doc/apps/kernel/inet.html#t:local_address/0). I don't know which one is more appropriate.

Lastly: mug uses glisten for testing purposes. glisten does currently not support unix sockets. I have a prototype done in glisten which adds support for that. The alternative (which I tried) is to write an FFI erlang echo server and use that instead.

I can PR the above code (but without unit tests) or I can wait until glisten code is done and merged and PR it with unit tests.

Anyway, as soon as these questions are sorted I can have a PR in.

Thanks