Skip to content

refactor(client): expose a way open multiple smux streams over one smux session

Currently snowflakeClientTransport.Dial() creates a smux session, and then immediately calls smux.OpenStream(), and Transport uses this stream for its implementation of being a net.Conn. Calling a Dial() on the same Transport makes it connect to a new proxy.

This sounds sub-optimal, in case the user (the library user) wants multiplexing. I know they can overlay another smux session on top of the net.Conn that is returned from Transport.Dial() (which is what I did in https://github.com/WofWca/snowflake-generalized/), but that would add unnecessary connection overhead.

Implementation

Implementation-wise, this sounds like we need smux.Session to be a part of the client Transport struct, and perhaps the collection of proxies should be started by some other method on Transport instead of Dial. It looks like the Transport struct doesn't really hold much state anyway, besides configs and the broker and NAT measurement state, so I think it makes sense to make it responsible for holding proxy connections and the session, perhaps similar to Pion's SCTPTransport, which has Start() and OnDataChannel(), but generally I'm not sure if it's common practice to call such things "transport"s.

Practical benefits?

TL;DR: right now: not much.

I know that currently the Tor integration of Snowflake doesn't really utilize more than one Dial() (except when it receives more than one SOCKS connection for whatever reason), so here my proposal is of no use. But in my application, I tried hacking up a version to test it. Here is the diff of my project, and here is the prototype change of Snowflake that it's based on: !481 (closed).

I tried to do speed tests with those changes by browsing through a Snowflake + SOCKS tunnel, but was unable to see significant difference, although it felt like it's a bit snappier.

So, as of now there doesn't seem to be a practical benefit to doing this. But this might come in handy if we get rid of the current bottleneck for the speed of Snowflake.

Prototype

As linked above, see

Alternatives?

According to the Snowflake paper, smux is only used to terminate timed out sessions, but smux is made for more than that. It implements channels, and buffering, so it adds overhead.
So, maybe instead we could find another, lighter solution for timing out the sessions.

On the other head, even if we do decide to abolish smux as this old session terminator, perhaps it would still be nice to keep multiplexing it in Snowflake, to simplify the life of library users who don't really know of the existence of multiplexer libraries, or, worse, don't know what multiplexing is.

Edited by WofWca