Delphi UDP Hole Punching: on internet not always works

  

I’m trying to implement UDP Hole Punching with Delphi with Indy and Firemonkey technology.

I have tried to follow this document: https://www.researchgate.net/publication/1959162_Peer-to-Peer_Communication_Across_Network_Address_Translators

The program seems to work but is NOT stable.

If I work on a system on the local intranet no problem.
If I work on an internet, it doesn’t always work and I don’t know why.

I have created two applications.

The first is server side.
Everytime all clients connect correctly to server.
The server registers the Local IP and Internet IP pairs in a variable (fPeers).

I created an IdUDPServer instance.
This is the “Connect push button” code:

procedure TForm1.B_ConnectClick(Sender: TObject);
var
vIdSocketHandle: TIdSocketHandle;
begin
if IdUDPServer.Active then
begin
IdUDPServer.Active := False;
B_Connect.Text := ‘Connect’;
end
else
begin
IdUDPServer.Bindings.Clear;
vIdSocketHandle := IdUDPServer.Bindings.Add;
vIdSocketHandle.IP := GStack.LocalAddress;
vIdSocketHandle.Port := E_POrt.Text.ToInteger;

IdUDPServer.Active := True;
B_Connect.Text := ‘Disconnect’;
end;
end;

During the IdUDPServerUDPRead event I capture the Local and Internet IP addresses of the clients that connect.
In the TStringLIST called fPeerIP I add the list of addresses.

procedure TForm1.IdUDPServerUDPRead(AThread: TIdUDPListenerThread;
const AData: TIdBytes; ABinding: TIdSocketHandle);
var vPair: string;
vData: string;
vString: string;
vLog: string;
begin
vPair := ABinding.PeerIP + ‘:’+ABinding.PeerPort.ToString;
vData := BytesToString(AData);
vLog := ”;

if leftstr(vdata,7) = ‘LOCALIP’ then
begin
vString := vPair+#9+lsExtract(vData,2,’,’);

if fPeerIP.IndexOfName(vString) = -1 then
begin
fPeerIP.Add(vString);
M_Peers.Lines.Add(vString);

vLog := vLog + vString + #13#10;
IdUDPServer.Send(ABinding.PeerIP, ABinding.PeerPort, ‘Peer aggiunto alla lista’);
end;

end
else vLog := vData;
end;

On the client side, I created an IdUDPServer instance which, upon connection, sends a string to the server.

procedure TForm2.B_ConnectClick(Sender: TObject);
var vIdSocketHandle: TIdSocketHandle;
vLocalAddressList: TIdStackLocalAddressList;
vI: Integer;
vSendLIST: TStringLIST;
begin
if IdUDPServer.Active then
begin
Timer.Enabled := False;
IdUDPServer.Active := False;
B_Connect.Text := ‘Connect’;

M_Networks.Lines.Clear;
M_Debug.Lines.Clear;
LB_Peers.Items.Clear;
end
else
begin
try
vSendLIST := TStringLIST.Create;
IdUDPServer.Bindings.Clear;

vLocalAddressList := TIdStackLocalAddressList.Create;
GStack.GetLocalAddressList(vLocalAddressList);
M_Networks.Lines.Clear;
for vI := 0 to vLocalAddressList.Count-1 do
begin
if vLocalAddressList.Addresses[vI].IPVersion = id_IPV4 then
begin
M_Networks.Lines.Add(vLocalAddressList.Addresses[vI].IPAddress);
vSendLIST.Add(Format(‘LOCALIP,%s:%d’,[vLocalAddressList.Addresses[vI].IPAddress,E_ClientPort.Text.ToInteger]));
end;
end;

vIdSocketHandle := IdUDPServer.Bindings.Add;
vIdSocketHandle.Port := E_ClientPort.Text.ToInteger;
vIdSocketHandle.IP := ‘0.0.0.0’;

IdUDPServer.Active := True;
for vI := 0 to vSendLIST.Count-1 do
IdUDPServer.Send(E_Server.Text, E_Port.Text.ToInteger, vSendLIST[vI]);

B_Connect.Text := ‘Disconnect’;
if Assigned(vSendLIST) then FreeAndNil(vSendLIST);
finally
if Assigned(vLocalAddressList) then FreeAndnil(vLocalAddressList);
end;
end;
end;

Also on the client side, in the IdUDPServerUDPRead event I detect the list of Peers (function sent by the server) and send a “PING” to each connected peer.

I realize maybe I have given little information.
I’d like to know your opinion and possibly indicate to me if I made a mistake in the process that activates the Hole Punching.

Thanks in advance
LS

Comments are closed.