libzt icon indicating copy to clipboard operation
libzt copied to clipboard

Non-blocking I/O with zt & native sockets

Open darrinsmart opened this issue 4 years ago • 5 comments

I'm writing an app that forwards between host-native sockets and libzt sockets.

zts_poll()/zts_select() are useful for network events from the zerotier side, and I can run a dedicated thread with the zts event loop. The problem is that if it is blocked on select/poll, I can't wake it up from the host-native thread when there is more data to send.

Is there a recommended way to poll on both zerotier & native sockets at the same time?

If not, perhaps a good enhancement would be a variant of zts_poll that took an array of pollfd in addition to the zts_pollfd array, blocking until either of them have an event.

Alternatively, a zts_pipe() function, mimicking the pipe(2) system call with lwip sockets, would make it possible to run a zerotier event loop in one thread and a native evenet loop in another. The self-pipe trick can be used to unblock the zt loop.

darrinsmart avatar May 21 '20 03:05 darrinsmart

Interesting proposal, I'm acknowledging that I've seen this but that I don't have a solution for you yet. There will be a slight refactoring of libzt after our 2.0 release and I can definitely revisit this if you haven't found a workaround. Is this still an issue for you?

joseph-henry avatar Sep 11 '20 00:09 joseph-henry

I'm also looking for this, My goal was to write a stdin/stdout to ZeroTier socket proxy in Python for use as a ProxyCommand in ssh. I was looking for some sort of select/poll of both ZT and OS sockets, and was going to fall back to a thread for the outbound and one for the inbound, but it sounds like that won't work due to the above.

In my case I can use non-blocking recv and read(), and just busy-loop with a small sleep(). But for many uses that would be objectionable. My use-case is proxying an SSH connection from a hosted Docker container which does not allow making tun/tap devices, as part of my ci/cd pipeline.

linsomniac avatar Mar 16 '21 22:03 linsomniac

Hmm. It seems like this is a common enough use-case that maybe I should add something to the API now, some sort of "socket fusion" mode that can be applied to a few different types of operations. I'm currently performing an update to the API so I'll keep this in mind as I work and try to fit something in.

joseph-henry avatar Mar 17 '21 17:03 joseph-henry

Apologies for taking so long to get back to you on this. Our immediate need for it has gone away, but our use case was to basically leverage the excellent NAT-busting capability of Zerotier to facilitate P2P features in our product. Doing it in-app has advantages: No system administration privileges required to set it up, and no system-wide security concerns.

darrinsmart avatar Mar 17 '21 17:03 darrinsmart

FYI: This is what I've come up with in Python/libzt to proxy between stdio and a ZeroTier addr/port, and it seems to work as an SSH ProxyCommand: https://github.com/linsomniac/ztproxy

linsomniac avatar Mar 21 '21 00:03 linsomniac