← Back to team overview

p2psp team mailing list archive

Re: NAT Traversal Set of rules implementation

 

Hi Vicente,

thanks for your replies.

On 08/11/2015 08:09 AM, Vicente Gonzalez wrote:
>
>>         Currently I noticed that in some rare cases the TCP socket of
>>         the peer receives 0 bytes from the splitter, which indicates
>>         a closed socket. Let's see if this persists and if a reason
>>         can be found.
>>
>>
>>     Please, remind me for what are you using this socket ...
>     This is just the TCP connection between peer and splitter, during
>     sending the IDs of the existing peers to the arriving peer (in
>     disconnect_from_the_splitter()). It occurs in about 5% of the test
>     runs and leads to connection failure.
>
>
> In your code ..., ¿where is this function declared?
It is declared in peer_nts.py, line 130 [1]
<https://github.com/jellysheep/p2psp/blob/adc3867cda688a30878a4f47119f0775d48678fb/src/peer_nts.py#L130>.
It is the line where the peer waits to be incorporated by the splitter.
Now I found out the problem only occurs if the peer cannot be
incorporated into the team: The splitter disconnects from an arriving
peer after a timeout during which the splitter did not receive UDP
packets from both the peer and the monitor. So in these cases too many
UDP packets dropped.
This only happened when the configured packet loss was above 10%, so
this behaviour is to be expected and shows that the timeout at the
splitter works.

>     The last few days I adapted the Peer_NTS class to connect to
>     several ports (probable source ports of the other peer), i.e. the
>     incorporated peers send to a number of consecutive ports at the
>     arriving peer behind a SYMSP NAT (sequential source port allocation).
>     Currently I am developing an algorithm to find the most probable
>     source ports to try. For example, if a port difference of 10
>     between the port to the splitter and to the monitor is determined,
>     then the actual port step could be one of {1,2,5,10}. So until now
>     the 3rd existing peer would try the ports
>     source_port_to_splitter+{3,4,...,15}, and with the new algorithm
>     the ports source_port_to_splitter+{3,4,5,6,7,8,10,12,15,20,30,40}
>     are tried.
>
>
> Why do you expect that with the new algorithm the performance will be
> better?
There are a few things to consider when predicting source ports:
1. The port step cannot be determined reliably (as stated above). If the
splitter measures a port step of 10, it could actually be one of
{1,2,5,10}. So there is a measured port step and an actual port step.
2. For each probable port step, a few number of "skips" should be tried,
because some source ports are skipped if the port is already taken by
another UDP "connection". So as the third peer is 3 port steps after the
monitor, the ports {3,4,...}, {6,8,...}, {15,20,...}, {30,40,...} should
be tried (in addition to source_port_to_splitter).
3. The number of port "skips" depends on the assumed port step: If a
port step of 10 is measured but a port step of 1 is assumed, then there
must have been 9 port skips between the UDP packets to the splitter and
to the monitor. So it is very likely that there will be also many port
skips between the packets to the peers, so many different should be
tried: {3,4,5,6,7,8}. However if both the measured and the assumed port
skip are 10, then there have been no port skips and it is less likely
that some will occur between the packets to the peers, so few port skips
are tried: {30,40}.
So the algorithm chooses the most probable source ports, given any
measured port step.
In the two trivial implementations, either assuming the port step 1
(currently implemented) or the measured port step 10, the port cannot be
predicted correctly in many cases: If the assumed port step is 1 and the
actual is 10, then the predicted ports will be {3,4,...,23}, while the
actual taken port is one of {30,40,...}. If the assumed port step is 10
and the actual is 1, then the predicted ports will be {30,40,...,230},
while the actual taken port is one of {3,4,...}.

> The case SYMSP<->SYMSP is difficult to handle in real-world scenarios,
> as for each tried destination port (probable source port of the other
> peer) another source port is created. So if another UDP connection
> besides the P2PSP software is established, the two peers are "out of
> step" and cannot connect to each other, because the source ports do
> not match.
>
> Well, this is something quite difficult to control. I suppose that for
> these cases, the incoming could try to join the team more than one
> time, with the aim of that this situation does not happen in some of
> the tries.
This would be good and convenient for the user, if you do not have to
retry connecting the peers yourself. I would like to implement it like this:
Considering the splitter timeout noted above, the peer will have a
timeout on its own and will retry incorporation into the team before the
splitter quits the connection. Also if a connection to one or more peers
cannot be established (I suppose *all* have to be working for P2PSP to
work), then the peer will retry as well.
When retrying incorporation, the peer sends goodbye messages to all
connected peers and closes the UDP socket, then retries sending UDP
packets from a new socket to the splitter and the monitor again. So the
TCP connection to the splitter has to remain open until the arriving
peer is connected to all existing peers (or else the peer would have to
start "from scratch", connecting to the splitter, receiving the
configuration etc.).

Regards,
Max


[1]
https://github.com/jellysheep/p2psp/blob/adc3867cda688a30878a4f47119f0775d48678fb/src/peer_nts.py#L130

Follow ups

References