Author Topic: Advertise System Question  (Read 4249 times)

Scorch

  • Jr. Member
  • **
  • Posts: 55
  • Karma: 2
    • View Profile
Advertise System Question
« on: June 25, 2006, 08:57:55 PM »
I have 2 problems I am working on right now:

The Plan:
I think I understand advertiseSystem and NAT punchthrough well enough to get this done.  I have 2 clients and a server.  Both clients are connected to the server, and wish to have a connection to each other.

Server tells both clients to advertise to the other and then connect.  (figure better odds of success if they both attempt to connect). 

Problem 1: Can't connect after calling advertise.

Since advertise creates a connection to send the advertise and then closes the connection, if I attempt to create my own connection before the advertise gets out, I get denied.

How do I know when its done disconnecting after advertise so I can issue my own connect?
Problem 2: If two clients attempt to connect to eachother at the same time, a race condition causes a disconnect (and in my system a crash but I don't know yet if the crash is mine or raknets).

Machine A issues a connect to Machine B, at the same time B is issuing a connect to A.  Lets say in this race, A establishes a connection first.  Then attempt B's connection is denied because A is allready connected to B.  The denied causes some cleanup including closing the connection to A because it thinks it failed.  Now neither are connected!

How can I tell if my attempt to connect is being denied because i had a race condition and i'm allready connected?

The only ideal solution to problem one I can think of so far is if advertise didn't open a connection to send out data (Junk data should be enough to fool a NAT server right?

The only ideal soltuion to problem two I can think of is if "allready connected" was either its own ID tag so I can handle it myself, or if "allready connected" was a successfull connect result.

[edit]  I forgot to say that my ideal soltuions have their flaws, I am not suggesting major changes to raknet, any old solution to this problem would be fine.

Scorch
« Last Edit: June 25, 2006, 09:03:35 PM by Scorch »

Rak'kar

  • Administrator
  • Hero Member
  • *****
  • Posts: 6895
  • Karma: 291
    • View Profile
    • RakNet
Re: Advertise System Question
« Reply #1 on: June 25, 2006, 10:53:15 PM »
Advertise system doesn't connect.  If you want to wait the next system I am working on is to redo the master server to have better support for NAT-punchthrough.

Scorch

  • Jr. Member
  • **
  • Posts: 55
  • Karma: 2
    • View Profile
Re: Advertise System Question
« Reply #2 on: June 25, 2006, 11:14:39 PM »
Advertise system doesn't actually connect no, but if I emediatly try to connect after advertise system teh connect call returns false.
added printf's to rakpeer.cpp and found that it returns false because it finds it in the remote list of allready existing connections.
I tried sleeping 100ms (30ms raknet thread timer) but that had no effect.


Scorch

  • Jr. Member
  • **
  • Posts: 55
  • Karma: 2
    • View Profile
Re: Advertise System Question
« Reply #3 on: June 25, 2006, 11:26:35 PM »
Ok, I have narrowed down the crash a bit more.

[edit] - took out one of the connects and my game app still crashes when the 2 clients attempt to connect to each other.
  still looking forward to suggestions, but I can't blame raknet for my crash ... back to the grindstone...


It is crashing if I receive a connection request from a player that I am already connected to....
since its a race condition, I don't know yet how to fix this one.  I can make the race condition less likly, but that is about it right now. ( I am going to try to add some delay on one side to make the race gap wider .. )
« Last Edit: June 26, 2006, 12:01:52 AM by Scorch »

Rak'kar

  • Administrator
  • Hero Member
  • *****
  • Posts: 6895
  • Karma: 291
    • View Profile
    • RakNet
Re: Advertise System Question
« Reply #4 on: June 26, 2006, 10:51:03 AM »
I'll look into if it crashes when someone connects that is already connected.  As for the rest, you can do the work if you want but if you wait a short while I'll do the work for you to make sure it works.

Scorch

  • Jr. Member
  • **
  • Posts: 55
  • Karma: 2
    • View Profile
Re: Advertise System Question
« Reply #5 on: June 26, 2006, 10:54:54 PM »
I have more information now.
The crash part turned out to be a bad iterator on my side.  It was a side effect of what happens inside rakknet, I have that patched so it can't happen agian, but I still have the same problem.

Here is the sinerio as what I have been able to map out:

-Server Tells A : ConnectTo( B )
-Server Tells B : ConnectTo( A )
-A receives ConnectTo( B ) and initiates a connection
-B receives ConnectTo( A ) and initiates a connection
-B receives a connection from A and accepts it.
-Some application level messages go back and forth.
-B's attempt to connect to A times out, B receives: "ID_CONNECTION_ATTEMPT_FAILED" and cleans up.
-Part of that clean up ends up sending a "ID_DISCONNECTION_NOTIFICATION" to A, now A and B are no longer connected at all.

Still working on a work around related to timing, but even if I get it working there is still a window depending on pings and such.

Scorch.

Rak'kar

  • Administrator
  • Hero Member
  • *****
  • Posts: 6895
  • Karma: 291
    • View Profile
    • RakNet
Re: Advertise System Question
« Reply #6 on: June 26, 2006, 11:45:12 PM »
Well if you're curious here's the algo I came up with so far.  But it will probably change once I get to implementing it.  I should have this for you in a pretty short amount of time.  The only delay is that I'm going to release it at the same time as the new directory server (e.g. master server) which is more complex.

NATPunchthrough

S = system that wants to connect
F = facilitator
R = system to get the connection requeset.

S knows IP of R in advance.
1. S->F facilitate connection request to R
2. if (R is not is connected) F->S R not connected.  Exit.
3. F -> (Ping S, Ping R), every 200 ms for 1 second.  Wait (highest of Ping R,S) ms more.
4. F picks time (lhighest of Ping R,S) * 6 from now and sends this time RELIABLE and timestamped to R,S.
5. At time picked in (4), S attempts to connect to R.  R sends offline message to S.
6. If R diconnects before or at step 4, F->S (notify disconnect)

Scorch

  • Jr. Member
  • **
  • Posts: 55
  • Karma: 2
    • View Profile
Re: Advertise System Question
« Reply #7 on: June 27, 2006, 12:15:06 AM »
From your attempts to maintain timing I take it that the NAT servers don't keep ports open long?  I don't know what the time restrictions are on that.

I also have one slight difference, I don't care if S connects to R or if R connects to S in my architecture.

I thought if I told S and R to both connect at the same time, proving them the external IP and port of the other, then the outgoing connect attempt from both sides would set up their respective NAT servers to receive the connect.  And in the race condition created, no matter which one "won" it would set up the NAT punchthrough for the other.  There is a posibility that both clients are behind more than 1 NAT server, in which case there is still a chance to fail.  That is why I have both clients send an advertise 100 or 200 ms before attempting to connect.

Here is my sequence:


S - server
A - Client A
B - Client B

A and B are allready connected to S.

S tells A to connect to B,
S tells B to connect to A,

A receives the command and isseus an advertise to B and starts a 200 ms timer.
B receives the command and issues an advertise to A and starts a 200 ms timer.
( even though the ping may be more than 200 ms between the two, the NAT punch through part  ( about 10% of the travel time )should have enough time unless they are behind like 50 NAT servers all using satilite and modem, in which case they shouldn't play my game ).

A issues a connect to B
B issues a connect to A.

No matter who wins the race, NAT punchthroughs are set up on both sides.
for example, A wins:
B receives connect from A, and accepts it
A receives connect from B, and accepts it.

B realizes that it is connected to A twice, and consolidates the two connections to one.
A realizes that it is connected to B twice, and considiates the two connections to one.

The last part is what I'm missing.    I thought I could do it at the application layer, but apparently not.  I wanted to issue both connects at once, because if one of the NAT punch's failed, I would effictively have a "backup".   I also think that you could do this entire process in roughly 200 ms.  I studdied NAT servers in college, but its been a while, from what I can rember of NAT servers a single advertise system should convince it to set up a route in its table, I don't know if sending multiple offline messages would help.


What you described apears to be basicly the same process as is in existance now, but just has added an attempt to syncronize clocks in the process. I do not know if that will make much of a difference in connect success rate.

 Scorch



Scorch

  • Jr. Member
  • **
  • Posts: 55
  • Karma: 2
    • View Profile
Re: Advertise System Question
« Reply #8 on: June 27, 2006, 12:34:25 AM »
The more I think about it, the more i'm sure that if you have both clients attempt to connect, you don't have to worry about the timing.  with the current model, you have to make sure that the receiver has finished calling advertise system before you issue a connect or it will fail.  But if both issue both an advertise and a connect, then no matter the result of the race condition, the calls will be in the right order in at least one direction, if not both.

Rak'kar

  • Administrator
  • Hero Member
  • *****
  • Posts: 6895
  • Karma: 291
    • View Profile
    • RakNet
Re: Advertise System Question
« Reply #9 on: June 27, 2006, 08:39:37 AM »
Some routers will ban you if they get a message from an unknown system.  So you have to send a message to that system before you get a message.  They both have to be in transit at the same time.

There's no such thing as two connections, or consoldating connections.  Sending a connection attempt is no different from sending a ping as far as the router is concerned.

Connections should be one way, because the system trying to connect might be banned and this requires that you call SetAllowedIncomingConnections on the client, which doesn't make sense.

Scorch

  • Jr. Member
  • **
  • Posts: 55
  • Karma: 2
    • View Profile
Re: Advertise System Question
« Reply #10 on: June 27, 2006, 11:28:10 AM »
I've never heard of a NAT server banning an incomming and not unbanning it when an outgoing goes to it, but I'll definitly take your word on that.  All of the NAT punch through documentation I have seen online didn't mention that posibility but I havn't seen everything I guess.


As for the both directions thingy, you have a point.  In my architecture, I already have everyone accepting connections and I don't care who established the connection because everyone is running RakPeer, with the same application level message set, so my assumption set is different there for my solution suggestion is different.

Scorch.