shadowsocks-rust icon indicating copy to clipboard operation
shadowsocks-rust copied to clipboard

Expose local addresses that local servers listen on

Open dlon opened this issue 2 years ago • 8 comments

I'm trying to run a local SOCKS server using the service crate. It's pretty useful to assign a random port by binding sockets to 127.0.0.1:0. There's currently no good way to retrieve this port, though.

Would it make sense to bind sockets earlier and provide methods for obtaining local addresses through the Server instance? If you disagree with that idea, I could probably live with simply publicly exporting the Socks{4,5}{TcpHandler,UdpServer} types.

Would a PR with any of these changes be accepted?

dlon avatar Mar 31 '22 13:03 dlon

The listeners are created on the stack of the internal local tasks. How can you retrieve the references of them and call the local_addr to fulfill your goal?

I would suggest you to get an available port before starting the server, just like what we did when starting plugins.

zonyitoo avatar Mar 31 '22 13:03 zonyitoo

Could the bind() not be moved to a separate create() method that is called before running the server? I'm not sure how feasible it would be:

let builder = SocksBuilder::new();
builder.set_udp_bind_addr(a);
let server = builder.create().await?; // calls bind(). New instance contains TcpListener
server.local_addr();
server.run().await; // consumes server & listens

dlon avatar Apr 01 '22 08:04 dlon

I don't want to expose the underlying socks server. Making APIs public will require more works to maintain API stability.

Why not just select a random port prior to create a local server instance?

zonyitoo avatar Apr 01 '22 08:04 zonyitoo

Further more, if you set 127.0.0.1:0 to local listen address, then TCP and UDP sockets may listen to different ports.

zonyitoo avatar Apr 01 '22 08:04 zonyitoo

Why not just select a random port prior to create a local server instance?

It's doable, but it's not as nice. I now need to create a temporary socket just to have the kernel assign a free port for me.

TCP and UDP sockets may listen to different ports.

Isn't this already the case? I's nothing new. I'm also not sure why it's a problem.

dlon avatar Apr 01 '22 17:04 dlon

https://github.com/shadowsocks/shadowsocks-rust/blob/7388ddfb7d36d5b84908c476daabc91c8b065a37/crates/shadowsocks/src/plugin/mod.rs#L232-L235

Just 2 lines of code. KISS.

zonyitoo avatar Apr 02 '22 02:04 zonyitoo

That sort of works. It's possible (but maybe unlikely) for the port to be reserved by someone else right after the TcpListener is dropped.

dlon avatar Apr 04 '22 08:04 dlon

That would happen rarely.

zonyitoo avatar Apr 04 '22 14:04 zonyitoo

I'll close this issue. It looks like we can use Socks*Server::local_addr now.

dlon avatar Aug 30 '23 13:08 dlon