|
|
@ -136,34 +136,36 @@ namespace Mono.Nat.Pmp
|
|
|
|
{
|
|
|
|
{
|
|
|
|
while (!cancellationToken.IsCancellationRequested)
|
|
|
|
while (!cancellationToken.IsCancellationRequested)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var result = await udpClient.ReceiveAsync().ConfigureAwait(false);
|
|
|
|
try
|
|
|
|
var endPoint = result.RemoteEndPoint;
|
|
|
|
{
|
|
|
|
byte[] data = data = result.Buffer;
|
|
|
|
var result = await udpClient.ReceiveAsync().ConfigureAwait(false);
|
|
|
|
|
|
|
|
var endPoint = result.RemoteEndPoint;
|
|
|
|
|
|
|
|
byte[] data = data = result.Buffer;
|
|
|
|
|
|
|
|
|
|
|
|
if (data.Length < 16)
|
|
|
|
if (data.Length < 16)
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
if (data[0] != PmpConstants.Version)
|
|
|
|
if (data[0] != PmpConstants.Version)
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
var opCode = (byte)(data[1] & 127);
|
|
|
|
var opCode = (byte)(data[1] & 127);
|
|
|
|
|
|
|
|
|
|
|
|
var protocol = Protocol.Tcp;
|
|
|
|
var protocol = Protocol.Tcp;
|
|
|
|
if (opCode == PmpConstants.OperationCodeUdp)
|
|
|
|
if (opCode == PmpConstants.OperationCodeUdp)
|
|
|
|
protocol = Protocol.Udp;
|
|
|
|
protocol = Protocol.Udp;
|
|
|
|
|
|
|
|
|
|
|
|
short resultCode = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data, 2));
|
|
|
|
short resultCode = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data, 2));
|
|
|
|
int epoch = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data, 4));
|
|
|
|
int epoch = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data, 4));
|
|
|
|
|
|
|
|
|
|
|
|
short privatePort = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data, 8));
|
|
|
|
short privatePort = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data, 8));
|
|
|
|
short publicPort = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data, 10));
|
|
|
|
short publicPort = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data, 10));
|
|
|
|
|
|
|
|
|
|
|
|
var lifetime = (uint)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data, 12));
|
|
|
|
var lifetime = (uint)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data, 12));
|
|
|
|
|
|
|
|
|
|
|
|
if (privatePort < 0 || publicPort < 0 || resultCode != PmpConstants.ResultCodeSuccess)
|
|
|
|
if (privatePort < 0 || publicPort < 0 || resultCode != PmpConstants.ResultCodeSuccess)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var errors = new[]
|
|
|
|
var errors = new[]
|
|
|
|
{
|
|
|
|
{
|
|
|
|
"Success",
|
|
|
|
"Success",
|
|
|
|
"Unsupported Version",
|
|
|
|
"Unsupported Version",
|
|
|
|
"Not Authorized/Refused (e.g. box supports mapping, but user has turned feature off)"
|
|
|
|
"Not Authorized/Refused (e.g. box supports mapping, but user has turned feature off)"
|
|
|
@ -173,19 +175,25 @@ namespace Mono.Nat.Pmp
|
|
|
|
"Unsupported opcode"
|
|
|
|
"Unsupported opcode"
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
var errorMsg = errors[resultCode];
|
|
|
|
var errorMsg = errors[resultCode];
|
|
|
|
NatUtility.Log("Error in CreatePortMapListen: " + errorMsg);
|
|
|
|
NatUtility.Log("Error in CreatePortMapListen: " + errorMsg);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (lifetime == 0) return; //mapping was deleted
|
|
|
|
if (lifetime == 0) return; //mapping was deleted
|
|
|
|
|
|
|
|
|
|
|
|
//mapping was created
|
|
|
|
//mapping was created
|
|
|
|
//TODO: verify that the private port+protocol are a match
|
|
|
|
//TODO: verify that the private port+protocol are a match
|
|
|
|
mapping.PublicPort = publicPort;
|
|
|
|
mapping.PublicPort = publicPort;
|
|
|
|
mapping.Protocol = protocol;
|
|
|
|
mapping.Protocol = protocol;
|
|
|
|
mapping.Expiration = DateTime.Now.AddSeconds(lifetime);
|
|
|
|
mapping.Expiration = DateTime.Now.AddSeconds(lifetime);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
NatUtility.Logger.ErrorException("Error in CreatePortMapListen", ex);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|