RandyGaul / cute_headers

Collection of cross-platform one-file C/C++ libraries with no dependencies, primarily used for games
4.28k stars 266 forks source link

cute_net.h times out over the internet #344

Closed Siltnamis closed 1 year ago

Siltnamis commented 1 year ago

Hi, I'm trying out this lib and it appears to work great on local network however, if I try to connect to IP that is not on the same local network the connection never gets made and just times out. It is reproducible with provided examples in this repo. Interesting note that the server receives data but somehow fails to make a connection. (I've added a conditional breakpoint after recvfrom on server side and it triggers when connection is attempted).

when starting a server: if I supply a loopback address "127.0.0.1:port" only this machine can connect (no one else even on LAN) if I supply a local address "192.x.x.x:port" anyone on LAN can connect and if router ports are opened anyone outside should be able to connect right?

So the setup to reproduce this issue is: start server example with local address and port start client and attempt to connect with your local address (SUCCESS) start client and attempt to connect with your public address (FAIL - times out even though some data is read from socket) start client on different machine/network and attempt to connect with servers public address (FAIL - same as above)

Honestly, I have no clue how is this behavior possible. It looks like data is sent over the internet but the connection is never made. Please take a look, thanks.

Update: Ok, so I found out that server just doesn't find its own endpoint in tokens endpoints list. because server was started with "192.x.x.x:port" and client tried to connect with servers public IP. The problem is that cn_server_start will always fail if I provide its own public IP. Would it make sense to pass only the port to cn_server_start and not full address? So either I am misunderstanding the usage or there is no way to connect over the internet currently.

r-lyeh commented 1 year ago

try to use '0.0.0.0:port' to bind the server address

Siltnamis commented 1 year ago

does not work. it calls cn_endpoint_equals(server_endpoint, token.endpoints[i]). And token endpoint contains "publicip:port" while server endpoint is "0.0.0.0:port" and ignores this connection attempt. So my understanding is that server thinks that this connection is not meant for it. If I skip this check and assume that it matches - everything appears to work just fine.

RandyGaul commented 1 year ago

There's a difference between your public IP and your machines local IP. You found the core issue, you would like to host your server on an IP behind a NAT device, which provides the machine with a local IP. The server starts up with it's local IP. However, the connect token has a reference to the public IP and the client must access the server on the public IP. The client and the connect token don't know anything about the server's local IP. So the security check fails since there's no matching IP between server local and the connect token list.

I think we can support this use-case with a small addition to the server's API. We can add an optional setting to the server, where it will know it's own public IP despite starting up with a local IP. You would have to provide the server with the public IP yourself, it will not have a way to find it on its own.

I do want to point out though, this is not a great solution for games today in terms of shipping. Requiring port-forwarding is outdated. Instead, by hosting your server on the cloud with a public IP none of this workaround is necessary at all, and no port-forwarding is required. I would encourage users to try out port-forwarding for testing and development, but not for releasing a game.

@Siltnamis Do you think this server API addition would work for you?

Siltnamis commented 1 year ago

Yes it would be useful for me. I'm far away from shipping anything so it is just easier to host on my local dev machine and let a friend join and tryout the game outside LAN. Thank you for explanation :)

RandyGaul commented 1 year ago

Verified this working with my own router + port forwarding. You can now call cn_server_set_public_ip for development and testing.