8 oct 2009
today i wanted to play a game of spring [1] with a friend but it didn’t work. i was using windows xp (not linux but yes this is even more usual there) and i downloaded spring with the nice little lobby called ‘springlobby’. i even remembered my login for the lobby interface. after connecting we wanted to use skype which didn’t work for about 15minutes (yes i was using my linux laptop and the sound there usually suckz as it tends to block the soundcard for some unknown reason quite often). but the problem was also the new account on the other end which had to be created but which didn’t work. after a couple of skype restarts on both sides it was starting to work. (not mentioning the issue of adding a new contact…).
so the lobby was running and we could talk using skype, what else could go wrong?
right after wards i hosted a game (i didn’t expect it to work since i didn’t do any manual port forwarding for the kind of random ip i usually have). i didn’t see the ‘nat traversal’ option in springlobby first (because i tend to join other games instead of hosting exactly for this kind of issue). so the game failed but to detect it - especially if several ppl join your game - you have to launch the game. so the game starts in fullscreen (it’s an opengl application) and computes some routes (waypoints or whatever) which is important for the ai (also for the own units) for pathfinding. waiting about 40 seconds to see that the connection didn’t work.
so next i rehosted the game using ‘nat traversal’ clicked. but it didn’t work either. no error message and no diagnostics of the issue. just a silent fail - which is what i tend to hate most (except a silent fail after a timeout which i even hate more).
finally my friend tried to host a game (he is also behind NAT - but who is not nowadays?). of course the same problem - it didn’t work. but skype once the audio part worked keept working. skype managed to traverse the NAT (or at least was using a relay we didn’t know of - which is the usual fallback used by skype, see [2]).
this reminded me however of the solution for this problem i was thinking of quite some time ago when i wrote a lobbyclient myself [3] together with two friends.
the question is: “how to establish a connection before game launch?”
two answer this question we will have a look at how a game launch works right now.
say the game connection didn’t work for at least one player and say an average game is joined by 4-8 ppl. please think of the time each player has to wait in average to detect a network issue. believe me ‘it is a lot of time’ and this made the ‘autohost’ function very popular.
the autohost is a game hosted by a nice person which has a computer running 24/7 with some game starter script. if a programmed bot in the gameroom parses the chat of the players and detects some string as “!start” from the ‘virtual hoster’ the game is launched and spring.exe starts (that is the game binary). since spring.exe can’t be run dedicated it is not only a waste of power/bandwidth but also a waste of workspace. i expect the game to be run in the background but still this has lots of performance loss for the user.
autohosting is a nice thing for players but it seems - at least for me - be more like a workaround for a technological problem not solved properly.
the fix i was talking of is this:
when the ‘hoster’ is hosting a game the ‘hoster’ starts a udp-server on a random port (which is known after starting the server of course). the ip and port are then automatically given to the other players. now every player tries to connect to that ip:port right away without launching spring.exe and without creating a configuration file. if the connection from player to the hoster is working a green LED in the springlobby will light up and everyone sees the status immediately. when the game launches every client then connects - not the the hoster ip:port - but instead to localhost:port.
so now we need a tiny relay udp server with hole punching capabilities and as some might like UPnP network capabilities.
client1 (192.168.1.22) –lan– fritz!box (192.168.1.1) —– inet —————–many routers —————— inet —– fritz!box (192.168.1.1) —-lan— client2 (192.168.1.33)
as you can see both clients reside in the same subnets but this is no issue since both subnets (192.168.1.x/24) are in an address space which isn’t routed in the ipv4 internet definition and since both clients are routed by a router (fritzbox in this case, can be any other vendor as well) both are behind NAT (network address translation) - which is our problem in the first place.
our small udpserver (i call it “udpPuncher”) would require:
so you might say that is no new technology.
i’ve never seen such a udpserver or library. all i know are a couple of projects trying to solve that issue. take sip as an example - they have the same problem there and they often give you a stun server (udp holepunching) to relay connection establishment.
there was a nice project i came along [4] which checked the NAT capabilities of your own network (there was a linux and a windows client). i’m not sure about the results but this could be used to qualify the network NAT type in an attempt to write the not yet written udpPuncher.
ipv6 would be a nice solution but i doubt this will be here soon as nobody seems to have interest in ipv6.
#links * [1] http://springrts.com * [2] http://en.wikipedia.org/wiki/Skype_protocol * [3] http://code.google.com/p/qtlobby/ * [4] http://nattest.net.in.tum.de/?mod=infos&lan=de
UPDATE:
I just found out that [4] is not new at all (maybe it is but not but at least for me it is), i’ve read [5] some long time ago but didn’t remember it. Now here is a very detailed documentation about NAT with illustrated (but not animated ;-P) examples of usage: