Custom transport in Phoenix

I’m gonna try to implement a custom transport using a UDP protocol.

I don’t find the documentation informative. In the example section, the provided example does not provide a new transport, it only showcases how one can use a transport to write a different logic based on incoming messages. It replaces the “channels” logic from the default socket implementation, but does not hint on how one can replace the web-socket or long-polling itself.

Or maybe I’m misreading the name transport? Is this the right place to look for it?

I’m trying to replace web-socket with a custom UDP protocol, and have the channels work as they currently do.

You can check out Telly GitHub - trarbr/telly: a proof of concept telnet transport for the Phoenix framework. It is a raw TCP transport (using plain text and JSON payloads) written using ranch. Written for phoenix 1.1 though, so probably doesn’t work with modern phoenix, but should serve as a starting point.

I also wrote a couple blog posts about it
http://tr.arbr.dk/phoenix-transport-adapters-part-1.html
http://tr.arbr.dk/phoenix-transport-adapters-part-2.html

1 Like

The transport you referring to is Phoenix.Socket.Transport, which allows you to define a custom way to “transport” you messages over the sockets.
If you want to do raw UDP probably you need to take a look at gen_udp.

1 Like

I don’t want raw UDP. I want a socket over UDP that can be used as a replacement for Phoenix provided socket.

Phoenix currently has long-polling and web-socket support. I want something that can be used over UDP.

Seems like not possible at the moment?

Why wouldn’t it be possible? You just have to build it yourself on top of raw udp using gen_udp. I bet it would take about ~750 LOC. That’s like, almost nothing (compared to what it would take in other PLs), but it’s still not nothing. You better be willing to roll up your sleeves!

@vfsoraki did you manage to do this? I’m looking into writing a completely custom transport, but it looks like this isn’t possible with the current public api. I’ve been looking at the phoenix source and it seems that you’d need to use some private apis to achieve this. You have to implement the Phoenix.Socket.Transport behaviour, where Phoenix.Socket is the default implementation. It makes use of the private Phoenix.Channel.Server module to join a channel and send messages. Since it’s private, the api could change at any point, so this is in fact not officially supported.

@brendan
It is possible. There even is an example in the docs: Phoenix.Socket.Transport Example

I am using a custom Phoenix.Socket.Transport myself in one of my projects, since I wanted a raw websocket with protobuf encoding.

But only if you want either websockets or longpolling.

Phoenix doesn’t support UDP since it is using cowboy as it’s server which is a HTTP server and that’s running over TCP (or QUIC which is layered on top of UDP but that isn’t currently supported).

If you need UDP i think gen_udp is what you want.

1 Like

No I didn’t do it. After searching a bit, I found that what @moogle19 said to be true.

It doesn’t actually let you define another kind of transport, only what you’re allowed under cowboy.

2 Likes

That isn’t a different transport, it just allows a different websocket handler that doesn’t connect to phoenix channels.
Saying it is possible and then saying only if using websockets or longpolling is a contradiction and not helpful.
If phoenix channels supported custom transports (with the public api), then I should be able to for example hookup mqtt/rabbitmq/udp to phoenix channels. From my understanding, this is currently not possible.

Yeah, it looks like the transport rewrite in Phoenix v1.4 means that a transport adapter must be using websockets or longpolling - sorry if my earlier contributions to this thread indicated otherwise, I was not aware of the change :frowning: