Inside3D!
     

NAT Fix -- Solves the "connection accepted" issue

 
Post new topic   Reply to topic    Inside3d Forums Forum Index -> Programming Tutorials
View previous topic :: View next topic  
Author Message
Baker



Joined: 14 Mar 2006
Posts: 1538

PostPosted: Fri Dec 11, 2009 8:32 am    Post subject: NAT Fix -- Solves the "connection accepted" issue Reply with quote

In cl_main.c (<--- not platform specific! Fix on any platform easy.) :

Quote:
/*
=====================
CL_EstablishConnection

Host should be either "local" or a net address to be passed on
=====================
*/
void CL_EstablishConnection (char *host)
{
if (cls.state == ca_dedicated)
return;

if (cls.demoplayback)
return;

CL_Disconnect ();

cls.netcon = NET_Connect (host);
if (!cls.netcon)
Host_Error ("CL_Connect: connect failed\n");
Con_DPrintf ("CL_EstablishConnection: connected to %s\n", host);

cls.demonum = -1; // not in the demo loop now
cls.state = ca_connected;
cls.signon = 0; // need all the signon messages before playing

MSG_WriteByte (&cls.message, clc_nop); // ProQuake NAT Fix

}


The notes and many changes to the network code in ProQuake make this difficult to isolate. I remembered seeing this singular change in the Q2K4 engine's source recently examinating Quake2 model support.

In both ProQuake and JoeQuake there about 3-4 changes marked NAT fix. Not sure why.

I was able to verify that this change alone solves the issue. Adding it in resolves the "connection accepted situation" and commenting it out generates "connection accepted". Despite all the places marked NAT fix in the ProQuake and JoeQuake source code, this single change above appears to be the only part necessary.

And the mystery of what exactly is required to do the NAT fix has boggled people such as Entar, aguirRe, myself and aggravated a lot of PSP developers and Wii people and so forth because winquake/glquake ports invariably inherit this problem.
Back to top
View user's profile Send private message
Team Xlink



Joined: 25 Jun 2009
Posts: 320

PostPosted: Fri Dec 11, 2009 11:08 pm    Post subject: Reply with quote

This has caused me so much frustration and has torn me to shreds trying to figure this out.

Baker, your are a life saver, I don't know how I can thank you enough for this.

I have went through ProQuakes, and JoeQuakes Source countless times and have tried so many different things, I can't thank you enough for what you have just done for me.


Thank you.
_________________
Anonymous wrote:
if it works, it works. if it doesn't, HAHAHA!
Back to top
View user's profile Send private message
Baker



Joined: 14 Mar 2006
Posts: 1538

PostPosted: Sat Dec 12, 2009 12:02 am    Post subject: Reply with quote

Team Xlink wrote:
This has caused me so much frustration and has torn me to shreds trying to figure this out.

Baker, your are a life saver, I don't know how I can thank you enough for this.

I have went through ProQuakes, and JoeQuakes Source countless times and have tried so many different things, I can't thank you enough for what you have just done for me.


Thank you.


It frustrated me to death in the past as well.

No need to thank me --- you solved my frustration with never being able to figure out how the hell to compile for the PSP [which led to me finally understanding how to use cygwin and then compiling FlashQuake].
Back to top
View user's profile Send private message
mh



Joined: 12 Jan 2008
Posts: 909

PostPosted: Sat Dec 12, 2009 2:19 am    Post subject: Reply with quote

One question about this - it's a protocol change isn't it? So one can't just add it to any engine in other words cos a client that has it would need a server that also has it?
_________________
DirectQ Engine - New release 1.8.666a, 9th August 2010
MHQuake Blog (General)
Direct3D 8 Quake Engines
Back to top
View user's profile Send private message Visit poster's website
Team Xlink



Joined: 25 Jun 2009
Posts: 320

PostPosted: Sat Dec 12, 2009 2:20 am    Post subject: Reply with quote

mh wrote:
One question about this - it's a protocol change isn't it? So one can't just add it to any engine in other words cos a client that has it would need a server that also has it?


I think it is only for the client because the Nat fix fixes the problem on the client side where the client doesn't complete the handshake.

So, Client Side I believe.
_________________
Anonymous wrote:
if it works, it works. if it doesn't, HAHAHA!
Back to top
View user's profile Send private message
Spike



Joined: 05 Nov 2004
Posts: 944
Location: UK

PostPosted: Sat Dec 12, 2009 10:51 am    Post subject: Reasoning Reply with quote

Reasoning:

A NAT will route packets from the client to the server and back.
If you have multiple clients/computers on the inside of the NAT and a new packet arrives, the NAT is only able to route the packet to the client computer if it knows which client computer it is meant to be sent to.
With the NQ protocols, the server listens on one port, and opens a new port for each client. It also initiates the connection on that new port.
This means that the client can begin connecting to the server, but once it has got a connection, the server starts sending packets to the router, and the router receives packets which it does not know how to route.
The solution is to send a dummy packet from the client's port to the server's new port for that client, thus opening a route on the client's NAT which basically tells the router how to route packets properly.

Complications:
Broken routers:
There are some routers which are so mind numbingly stupid that they close the connection again after 2 mins, and which will only be reopened by a client->server packet. NQ clients only send packets on receipt of a packet from a server, and in this case, no NAT fix will save you. Such routers are of course absurdly broken. A work around is to just send dummy nop packets (or even corrupt ones) every 2 mins, or each time you lose your connection, lol.
Server NATS:
Additionally, this is a client-side NAT fix only. For servers behind a NAT or router, the server will listen on a known port for new clients, and then auto-allocate a new port for each client. You can forward the known port, but the port-per-client ports are generated almost at random, depending on the operating system. Its generally a bad plan to route 4096+ to that server... The solution to this is to change port allocation to a known range, or to rewrite the network code to always use a single port for every client. This is probably why there are multiple chunks of proquake code marked as NAT fixes, perhaps.

Alternatives:
As mentioned above, the server can be modified to use a single serverside port. This provides a NAT fix for all clients' NATS as well as the server. But its a lot of code. FTE does this, as does DP, but it doesn't fix the client if they connect elsewhere, of course.

You don't have to send a meaningful packet. You could send a 'corrupt' packet to the server, so long as you send at least one udp payload byte from the correct client port to the correct server port. The server does not need to parse it, it needs merely to be routed by the client's NAT.
Generally UDP over wireless is quite lossy, so you may wish to send a couple of packets (with a time gap) if the client is on a wifi connection before the router, but over ethernet more than 1 is overkill, its not really possible to tell however.
_________________
What's a signature?
Back to top
View user's profile Send private message Visit poster's website
frag.machine



Joined: 25 Nov 2006
Posts: 728

PostPosted: Sat Dec 12, 2009 2:55 pm    Post subject: Reply with quote

mh wrote:
One question about this - it's a protocol change isn't it? So one can't just add it to any engine in other words cos a client that has it would need a server that also has it?


Not really. AFAIK this just adds an already existing (and harmless, since there's no server behavior for client nop's) message to the protocol handshake so the connection is kept alive. In theory, the client could send periodically a nop message to the server without breaking compatibility.
_________________
frag.machine - Q2K4 Project
http://fragmachine.quakedev.com/
Back to top
View user's profile Send private message Visit poster's website
r00k



Joined: 13 Nov 2004
Posts: 483

PostPosted: Sat Dec 12, 2009 3:58 pm    Post subject: Reply with quote

Looking closely it seems that the nat fix tells outbound packets to new connecting clients to wait until in datagram_getmessage

Code:

      // joe: NAT fix from ProQuake
      if (sock->net_wait)
      {
         sock->addr = readaddr;
         strcpy (sock->address, sfunc.AddrToString(&readaddr));
         sock->net_wait = false;
      }


where it updates the port... ?
Back to top
View user's profile Send private message
Baker



Joined: 14 Mar 2006
Posts: 1538

PostPosted: Sat Dec 12, 2009 4:22 pm    Post subject: Reply with quote

There does happen to be a server-side NAT fix written by Yugo2Heck:

http://quakeone.com/q1files/downloads/linux/qsrc-pq350-ssp.patch
http://quakeone.com/forums/quake-talk/quake-central/1020-new-euroquake-server-up-running-4.html#post11770

Back in the "older" days (2004-2006), I recommend someone with trouble connecting to try to connect to quake.ihoc.net to see if they could connect and if so, I knew they weren't using an NAT fixed client.

And you'd see a lot of "I can only connect to IHOC! I can't connect to any other server, please help OMG!".

However the best server answer would be to do whatever DarkPlaces and FTE do to use a single port. It would make server setup much easier for server hosts unfamiliar with NQ, which typically run into firewall issues because only post 26000 is open.

r00k wrote:
Looking closely it seems that the nat fix tells outbound packets to new connecting clients to wait until in datagram_getmessage

Code:

      // joe: NAT fix from ProQuake
      if (sock->net_wait)
      {
         sock->addr = readaddr;
         strcpy (sock->address, sfunc.AddrToString(&readaddr));
         sock->net_wait = false;
      }


where it updates the port... ?


@Rook: I don't claim to understand the networking code in code all that well, but I do know I didn't need to use the above code you quoted code to do a client-side fix for GLQuake. Just the one yellow line of code in post #1. I tested the NAT-fixed GLQuake against both ProQuake servers and against non-ProQuake servers (Clan Rum) and the single line of code allowed me to connect to both of them without "connection accepted" (and commenting out the single line would cause the "connection accepted" problem to come back).
Back to top
View user's profile Send private message
r00k



Joined: 13 Nov 2004
Posts: 483

PostPosted: Sun Dec 13, 2009 9:13 am    Post subject: Reply with quote

Hmm, that clc_nop just sends an emtpy packet.
Curious though if yugo's patch will still allow two machines on same network to connect to the same server?
Back to top
View user's profile Send private message
Team Xlink



Joined: 25 Jun 2009
Posts: 320

PostPosted: Sun Dec 13, 2009 5:00 pm    Post subject: Reply with quote

r00k wrote:
Hmm, that clc_nop just sends an emtpy packet.
Curious though if yugo's patch will still allow two machines on same network to connect to the same server?


Correct me if I am wrong but isn't this already possible?

I swear I have done this.


EDIT: My mistakem it turns out I did this when I was hosting a public server so I had multiple clients connect to it. Sorry, about that.
_________________
Anonymous wrote:
if it works, it works. if it doesn't, HAHAHA!
Back to top
View user's profile Send private message
r00k



Joined: 13 Nov 2004
Posts: 483

PostPosted: Mon Dec 14, 2009 6:12 pm    Post subject: Reply with quote

I meant would this patch DISALLOW multiple connections from the SAME IP address? Neutral

The client re-init's the socket after connection accepted, then the server scans the connected client's ip address, then reconnects the proper port. If two players have same IP but diff ports there may be a conflict. Hmm, or maybe two people sharing the same pov :O lol!
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Inside3d Forums Forum Index -> Programming Tutorials All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2004 phpBB Group