zerotier / libzt

Encrypted P2P sockets over ZeroTier

Home Page:https://zerotier.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to deal with scenarios that requires cancelling?

CCRcmcpe opened this issue · comments

I'm building a port forwarding application using the .NET binding, but struggled to let it complete an iperf3 test because an issue when dealing with cleanups, like shutdown and close.

After the forwarded service send a 0 length packet to the app, the app call shutdown (send) for the zerotier socket. But the other end does not receive the 0 length packet. So it basically has no effect. The Python example does not call shutdown either.

If you call close, the other end receive a 0 length packet, which means the other end stops receiving. However, on this end, the thread that receives the data from the zerotier socket does not stop, in other words, stuck in receive method. I don't have a way to cancel it, except to kill the thread. I think is this a last resort, and is no longer possible to acheive with current .NET API.

Any advice? Should I use poll instead to determine whether there are data to receive? I don't really understand how poll works with zerotier sockets.

BTW I'm not very familiar with socket programming. Trying to point out the core issue, per https://stackoverflow.com/questions/60083939/what-is-the-best-way-to-cancel-a-socket-receive-request I basically have to close the socket to cancel receiving. But in libzt closing the socket does not have this effect. oops.

And to clarify, the other end did execute close after receiving the 0 length packet. So on this end it should receive a 0 length packet to indicate that too (?), but it doesn't.

Normally when you're trying to react to a socket closure you need to be polling either via poll, select, or by setting the socket to non-blocking and just seeing what you get back. There is a C example here: https://github.com/zerotier/libzt/blob/2f0f25a15870ac0ae52815558c539e63d656d506/examples/c/nonblockingserver.c that should help with the concept. Unfortunately I don't have a good C# example currently.

I did a quick check of the C# wrapper and it looks like I implemented Poll(), it is intended to work just like the native C# function so I'd try that and if you find any missing or incorrect behavior I am interested in fixing that so please bring it to my attention.

Also, feel free to make a PR if you find anything else broken in that wrapper, we are interested in improving it.

P.S. Polling a set of OS and ZT sockets together in the same FD set doesn't work but I'm introducing a new "fused polling" mode to help with this and I'll try to add it to the C# wrapper if needed.

Thanks for the response. Polling is certainly considered, but I don't really understand the return value of it. Even if the socket is already closed (by remote), poll(can recv) still returns true.

@CCRcmcpe how did your port forwarder work out for you?

I do feel that this is one of the most common use cases of this library (open a local port but forward it to a ZeroTier end point). Maybe it could be done in the base library and exposed to the client libraries?