A partir do sgcWebSockets 4.5.2, você pode construir seus próprios servidor e clientes STUN/TURN usando a biblioteca sgcWebSockets.
STUN
Session Traversal Utilities for NAT (STUN) é um protocolo para descobrir seu endereço público e determinar quaisquer restrições no seu roteador que impediriam uma conexão direta com um par.
O cliente envia uma requisição a um servidor STUN na Internet, que responde com o endereço público do cliente e se ele é ou não acessível por trás do NAT do roteador.
TURN
Alguns roteadores que usam NAT empregam uma restrição chamada 'NAT Simétrico'. Isso significa que o roteador só aceita conexões de pares aos quais você já se conectou anteriormente.
Traversal Using Relays around NAT (TURN) destina-se a contornar a restrição do NAT Simétrico abrindo uma conexão com um servidor TURN e retransmitindo todas as informações por meio desse servidor. Você criaria uma conexão com um servidor TURN e diria a todos os pares para enviar pacotes ao servidor, que os encaminharia para você. Isso obviamente vem com alguma sobrecarga, portanto é usado apenas se não houver outras alternativas.
Construindo um Servidor STUN/TURN
O processo para criar um Servidor Delphi STUN/TURN é muito simples: basta criar um TsgcTURNServer e configurar as seguintes propriedades:
- Port: por padrão é 3478, a porta comum para o protocolo STUN/TURN.
- STUNOptions: aqui você pode configurar as opções STUN. Geralmente as requisições STUN não usam autenticação, portanto pode deixar com os valores padrão.
- TURNOptions: aqui você pode configurar as opções TURN. Geralmente os servidores TURN exigem credenciais de longa duração (porque o TURN usa Relay Address para trocar dados entre pares atrás de NATs e isso requer muitos recursos). Aqui você pode configurar o endereço IP do Relay Address em TURNOptions.Allocation.RelayIP.
Trate o evento OnSTUNRequestAuthorization para definir a senha quando um cliente TURN enviar uma requisição.
Por fim, defina a propriedade Active como True para iniciar o servidor.
Veja abaixo uma configuração de exemplo onde requisições STUN não exigem autorização e requisições TURN exigem credenciais de longa duração.
oTURN := TsgcTURNServer.Create(nil);
oTURN.Port := 3478;
oTURN.STUNOptions.Authentication.Enabled := False;
oTURN.TURNOptions.Authentication.Enabled := True;
oTURN.TURNOptions.Authentication.LongTermCredentials.Enabled := True;
oTURN.TURNOptions.Authentication.LongTermCredentials.Realm := 'sgcWebSockets';
oTURN.TURNOptions.Authentication.LongTermCredentials.StaleNonce := 600;
oTURN.Active := True;
procedure OnSTUNRequestAuthorization(Sender: TObject; const aRequest: TsgcSTUN_Message; const aUsername, aRealm: string; var Password: string);
begin
if (aUsername = 'my-user') and (aRealm = 'sgcWebSockets') then
Password := 'my-password';
end;
Construindo um Cliente STUN/TURN
Criar um novo cliente Delphi STUN/TURN é tão simples quanto um servidor. Basta criar um TsgcTURNClient e configurar as seguintes propriedades:
- Host: é o nome DNS ou endereço IP onde o servidor STUN/TURN está rodando.
- Port: é a porta; por padrão, 3478.
- STUNOptions: aqui você pode configurar as opções STUN. Geralmente as requisições STUN não usam autenticação, portanto pode deixar com os valores padrão.
- TURNOptions: aqui você pode configurar as opções TURN. Geralmente os servidores TURN exigem credenciais de longa duração (porque o TURN usa Relay Address para trocar dados entre pares atrás de NATs e isso requer muitos recursos).
Alocar Endereço IP
O protocolo TURN permite usar um Relayed IP Address para trocar dados entre pares que estão atrás de NATs.
Para criar um novo Relayed IP Address em um servidor TURN, o cliente deve primeiro chamar o método Allocate. Este método envia uma requisição ao servidor TURN para criar um novo Relayed IP Address; se o servidor TURN puder criá-lo, o cliente receberá uma resposta bem-sucedida. O cliente poderá se comunicar com outros pares durante o tempo definido no lifetime da alocação.
oTURN := TsgcTURNClient.Create(nil);
oTURN.Host := 'turn.sgcwebsockets.com';
oTURN.Port := 3478;
oTURN.Allocate();
procedure OnTURNAllocate(Sender: TObject; const aSocket: TsgcSocketConnection; const
aMessage: TsgcSTUN_Message; const aAllocation: TsgcTURN_ResponseAllocation);
begin
DoLog('Relayed IP: ' + aAllocation.RelayedIP + '. Relayed Port: ' + IntToStr(aAllocation.RelayedPort));
end;
procedure OnSTUNResponseError(Sender: TObject; const aMessage: TsgcSTUN_Message;
const aError: TsgcSTUN_ResponseError);
begin
DoLog('Error: ' + IntToStr(aError.Code) + ' ' + aError.Reason);
end;
O lifetime pode ser atualizado para evitar expiração usando o método Refresh. O Lifetime é o número de segundos até expirar. Se o valor for zero, a alocação será excluída.
oTURN.Refresh(600);
