22using NetworkLibrary . P2P . Components . HolePunch ;
33using System ;
44using System . Collections . Generic ;
5+ using System . Linq ;
56using System . Net ;
67using System . Threading ;
78using System . Threading . Tasks ;
9+ using System . Transactions ;
810
911namespace NetworkLibrary . P2P . Components . StateManagemet . Client
1012{
@@ -16,6 +18,7 @@ internal class ClientHolepunchState : IState
1618 internal Guid destinationId ;
1719 internal IPEndPoint succesfulEpToReceive ;
1820 internal IPEndPoint succesfullEpToSend ;
21+ internal IPEndPoint relayServerEndpoint ;
1922 internal Action Success ;
2023 internal Action < byte [ ] , List < EndpointData > > KeyReceived ;
2124 internal EndpointTransferMessage targetEndpoints ;
@@ -29,11 +32,12 @@ internal class ClientHolepunchState : IState
2932 private StateManager client ;
3033 private int totalPunchRoutines = 0 ;
3134 private CancellationTokenSource cancellationTokenSource = new CancellationTokenSource ( ) ;
32- public ClientHolepunchState ( Guid destinationId , Guid stateId , StateManager client )
35+ public ClientHolepunchState ( Guid destinationId , Guid stateId , StateManager client , IPEndPoint relayServerEndpoint )
3336 {
3437 this . destinationId = destinationId ;
3538 StateId = stateId ;
3639 this . client = client ;
40+ this . relayServerEndpoint = relayServerEndpoint ;
3741 }
3842 // A asks B
3943 public void Initiate ( )
@@ -46,7 +50,7 @@ public void InitiateByRemote(MessageEnvelope message)
4650 HandleEndpointMessage ( message ) ;
4751 }
4852 // get remote ep then punch
49- private void RetrieveRemoteEndpoint ( Guid destinatioinId )
53+ private void RetrieveRemoteEndpoint ( Guid destinationId )
5054 {
5155 var message = new MessageEnvelope
5256 {
@@ -56,28 +60,59 @@ private void RetrieveRemoteEndpoint(Guid destinatioinId)
5660 } ;
5761 if ( encypted )
5862 message . KeyValuePairs = new Dictionary < string , string > ( ) { { "Encrypted" , null } } ;
59- client . SendAsyncMessage ( destinatioinId , message ) ;
63+ client . SendAsyncMessage ( destinationId , message ) ;
6064 // reply will be handled on HandleEndpointMessage
6165 }
6266
6367 private void HandleEndpointMessage ( MessageEnvelope message )
6468 {
6569 targetEndpoints = KnownTypeSerializer . DeserializeEndpointTransferMessage ( message . Payload , message . PayloadOffset ) ;
66- cryptoKey = targetEndpoints . IpRemote ;
70+
71+ // the remote ip on relay is local means relay server and remote client is in same local network
72+ var ipToVerify = targetEndpoints . LocalEndpoints . Last ( ) . Ip ;
73+ if ( IPUtils . IsLoopback ( ipToVerify ) || IPUtils . IsPrivate ( ipToVerify ) )
74+ {
75+ // (localhost client + relay) vs remote client
76+ //if im not also local, i should try the internet address of the relay.
77+ var relayIp = relayServerEndpoint . Address . GetAddressBytes ( ) ;
78+ if ( ! IPUtils . IsLoopback ( relayIp ) && ! IPUtils . IsPrivate ( relayIp ) )
79+ targetEndpoints . LocalEndpoints . Add ( new EndpointData ( new IPEndPoint ( relayServerEndpoint . Address , targetEndpoints . LocalEndpoints [ 0 ] . Port ) ) ) ;
80+ }
81+
82+ // Here we need to remove loopback because i might send messages to myself if we share the same port..
83+ List < EndpointData > toRemove = new List < EndpointData > ( ) ;
84+ foreach ( var endpoint in targetEndpoints . LocalEndpoints )
85+ {
86+ if ( IPUtils . IsLoopback ( endpoint . Ip ) )
87+ {
88+ toRemove . Add ( endpoint ) ;
89+ }
90+
91+ }
92+ foreach ( var item in toRemove )
93+ {
94+ targetEndpoints . LocalEndpoints . Remove ( item ) ;
95+ }
96+
97+ cryptoKey = targetEndpoints . IpRemote ; // yea, didnt wanna change the type
6798 KeyReceived ? . Invoke ( cryptoKey , targetEndpoints . LocalEndpoints ) ;
6899 if ( cryptoKey != null )
69100 {
70101 aesAlgorithm = new ConcurrentAesAlgorithm ( cryptoKey , cryptoKey ) ;
71102 }
103+
72104 var count = targetEndpoints . LocalEndpoints . Count ;
73105 Interlocked . Exchange ( ref totalPunchRoutines , count ) ;
74106 for ( int i = 0 ; i < count ; i ++ )
75107 {
108+ var Ip = targetEndpoints . LocalEndpoints [ i ] . Ip ;
76109 var ep = targetEndpoints . LocalEndpoints [ i ] . ToIpEndpoint ( ) ;
77110
78- // last one is remote end point, we need to try locals first.
79- if ( i == count - 1 )
111+ // first handle the local ips, start remote later, because if we are on local why go through internet..
112+ if ( ! IPUtils . IsPrivate ( Ip ) )
113+ {
80114 PunchRoutine ( ep , delay : true ) ;
115+ }
81116 else
82117 PunchRoutine ( ep ) ;
83118 }
@@ -95,7 +130,7 @@ private async void PunchRoutine(IPEndPoint ep, bool delay = false)
95130
96131 if ( delay )
97132 {
98- await Task . Delay ( 1500 , cancellationTokenSource . Token ) . ConfigureAwait ( false ) ;
133+ await Task . Delay ( 1000 , cancellationTokenSource . Token ) . ConfigureAwait ( false ) ;
99134 }
100135 // Console.WriteLine("Punching towards: " + ep.ToString());
101136
@@ -131,7 +166,7 @@ private async void PunchRoutine(IPEndPoint ep, bool delay = false)
131166 // inside of this message i must put the endpoint i shot at
132167 public void HandleMessage ( IPEndPoint remoteEndpoint , MessageEnvelope message )
133168 {
134-
169+ // here i would like to receive all, then rank the ips select nearest.
135170 if ( Interlocked . CompareExchange ( ref succesfulEpToReceive , remoteEndpoint , null ) == null )
136171 {
137172 //Console.WriteLine("Received Sucess: " + remoteEndpoint.ToString());
@@ -168,9 +203,10 @@ public void HandleMessage(MessageEnvelope message)
168203 if ( Interlocked . Exchange ( ref stop , 1 ) == 0 )
169204 {
170205 cancellationTokenSource . Cancel ( ) ;
171- Consensus ( ) ;
172206 // get the sucessfull ep
173207 succesfullEpToSend = KnownTypeSerializer . DeserializeEndpointData ( message . Payload , message . PayloadOffset ) . ToIpEndpoint ( ) ;
208+ Consensus ( ) ;
209+
174210 }
175211 }
176212 else if ( message . Header == Constants . HolpunchMessagesSent )
@@ -220,7 +256,7 @@ public void Release(bool isCompletedSuccessfully)
220256 {
221257 if ( Interlocked . CompareExchange ( ref isReleased , 1 , 0 ) == 0 )
222258 {
223- if ( isCompletedSuccessfully )
259+ if ( isCompletedSuccessfully && succesfullEpToSend != null && succesfulEpToReceive != null )
224260 currentStatus = StateStatus . Completed ;
225261 else
226262 currentStatus = StateStatus . Failed ;
0 commit comments