예제 #1
0
        public override Task CreatePortMapAsync(Mapping mapping)
        {
            Guard.IsNotNull(mapping, "mapping");
            if (mapping.PrivateIP.Equals(IPAddress.None)) mapping.PrivateIP = DeviceInfo.LocalAddress;

            NatDiscoverer.TraceSource.LogInfo("CreatePortMapAsync - Creating port mapping {0}", mapping);

            var message = new CreatePortMappingRequestMessage(mapping);
            return _soapClient
                .InvokeAsync("AddPortMapping", message.ToXml())
                .TimeoutAfter(TimeSpan.FromSeconds(4))
                .ContinueWith(task =>
                {
                    if (!task.IsFaulted)
                    {
                        RegisterMapping(mapping);
                    }
                    else
                    {
                        MappingException me = task.Exception.InnerException as MappingException;

                        if (me == null)
                        {
                            throw task.Exception.InnerException;
                        }

                        switch (me.ErrorCode)
                        {
                            case UpnpConstants.OnlyPermanentLeasesSupported:
                                NatDiscoverer.TraceSource.LogWarn(
                                    "Only Permanent Leases Supported - There is no warranty it will be closed");
                                mapping.Lifetime = 0;
                                // We create the mapping anyway. It must be released on shutdown.
                                mapping.LifetimeType = MappingLifetime.ForcedSession;
                                CreatePortMapAsync(mapping);
                                break;
                            case UpnpConstants.SamePortValuesRequired:
                                NatDiscoverer.TraceSource.LogWarn(
                                    "Same Port Values Required - Using internal port {0}", mapping.PrivatePort);
                                mapping.PublicPort = mapping.PrivatePort;
                                CreatePortMapAsync(mapping);
                                break;
                            case UpnpConstants.RemoteHostOnlySupportsWildcard:
                                NatDiscoverer.TraceSource.LogWarn("Remote Host Only Supports Wildcard");
                                mapping.PublicIP = IPAddress.None;
                                CreatePortMapAsync(mapping);
                                break;
                            case UpnpConstants.ExternalPortOnlySupportsWildcard:
                                NatDiscoverer.TraceSource.LogWarn("External Port Only Supports Wildcard");
                                throw me;
                            case UpnpConstants.ConflictInMappingEntry:
                                NatDiscoverer.TraceSource.LogWarn("Conflict with an already existing mapping");
                                throw me;

                            default:
                                throw me;
                        }
                    }
                });
        }
예제 #2
0
 void onPortMappingDone(Open.Nat.Mapping mapping, bool isError)
 {
     if (isError)
     {
         Debug.Log("Port mapping failed");
     }
     else
     {
         Debug.Log("Port " + mapping.PublicPort + " mapped (" + mapping.Protocol + ")");
     }
 }
 public void OpenExternalPort(int privatePort, int publicPort, string description)
 {
     localHostPort = privatePort;
     var timeSpan = new TimeSpan(0, 0, 0, 30);
     var cancellationTokenSource = new CancellationTokenSource(timeSpan);
     natDiscoverer = new NatDiscoverer();
     natDevice = natDiscoverer
         .DiscoverDeviceAsync(PortMapper.Upnp, cancellationTokenSource)
         .IsCompleted();
     mapping = new Mapping(Protocol.Tcp, privatePort, publicPort, description);
     natDevice
         .CreatePortMapAsync(mapping)
         .IsCompleted();
 }
예제 #4
0
        private async Task<Mapping> InternalCreatePortMapAsync(Mapping mapping, bool create)
        {
            var package = new List<byte>();

            package.Add(PmpConstants.Version);
            package.Add(mapping.Protocol == Protocol.Tcp ? PmpConstants.OperationCodeTcp : PmpConstants.OperationCodeUdp);
            package.Add(0); //reserved
            package.Add(0); //reserved
            package.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short) mapping.PrivatePort)));
            package.AddRange(
                BitConverter.GetBytes(create ? IPAddress.HostToNetworkOrder((short) mapping.PublicPort) : (short) 0));
            package.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(mapping.Lifetime)));

            try
            {
                byte[] buffer = package.ToArray();
                int attempt = 0;
                int delay = PmpConstants.RetryDelay;

                using (var udpClient = new UdpClient())
                {
                    CreatePortMapListen(udpClient, mapping);

                    while (attempt < PmpConstants.RetryAttempts)
                    {
                        await
                            udpClient.SendAsync(buffer, buffer.Length,
                                                new IPEndPoint(LocalAddress, PmpConstants.ServerPort));

                        attempt++;
                        delay *= 2;
                        Thread.Sleep(delay);
                    }
                }
            }
            catch (Exception e)
            {
                string type = create ? "create" : "delete";
                string message = String.Format("Failed to {0} portmap (protocol={1}, private port={2})",
                                               type,
                                               mapping.Protocol,
                                               mapping.PrivatePort);
                NatDiscoverer.TraceSource.LogError(message);
                var pmpException = e as MappingException;
                throw new MappingException(message, pmpException);
            }

            return mapping;
        }
예제 #5
0
        public override async Task CreatePortMapAsync(Mapping mapping)
        {
            Guard.IsNotNull(mapping, "mapping");

            mapping.PrivateIP = DeviceInfo.LocalAddress;
            try
            {
                var message = new CreatePortMappingRequestMessage(mapping);
                await _soapClient
                    .InvokeAsync("AddPortMapping", message.ToXml())
                    .TimeoutAfter(TimeSpan.FromSeconds(4));
                RegisterMapping(mapping);
            }
            catch(MappingException me)
            {
                switch (me.ErrorCode)
                {
                    case UpnpConstants.OnlyPermanentLeasesSupported:
                        NatDiscoverer.TraceSource.LogWarn("Only Permanent Leases Supported - There is no warranty it will be closed");
                        mapping.Lifetime = 0;
                        // We create the mapping anyway. It must be released on shutdown.
                        mapping.LifetimeType = MappingLifetime.ForcedSession;
                        CreatePortMapAsync(mapping);
                        break;
                    case UpnpConstants.SamePortValuesRequired:
                        NatDiscoverer.TraceSource.LogWarn("Same Port Values Required - Using internal port {0}", mapping.PrivatePort);
                        mapping.PublicPort = mapping.PrivatePort;
                        CreatePortMapAsync(mapping);
                        break;
                    case UpnpConstants.RemoteHostOnlySupportsWildcard:
                        NatDiscoverer.TraceSource.LogWarn("Remote Host Only Supports Wildcard");
                        mapping.PublicIP = IPAddress.None;
                        CreatePortMapAsync(mapping);
                        break;
                    case UpnpConstants.ExternalPortOnlySupportsWildcard:
                        NatDiscoverer.TraceSource.LogWarn("External Port Only Supports Wildcard");
                        throw;
                    case UpnpConstants.ConflictInMappingEntry:
                        NatDiscoverer.TraceSource.LogWarn("Conflict with an already existing mapping");
                        throw;

                    default:
                        throw;
                }
            }
        }
예제 #6
0
파일: NatUtils.cs 프로젝트: Civa/Zenith
        internal async Task<bool> CreateNatTraversalEntry(NatMappingEntry entry)
        {
            try
            {
                var discoverer = new NatDiscoverer();
                var cts = new CancellationTokenSource(10000);
                var device = await discoverer.DiscoverDeviceAsync(PortMapper.Upnp, cts);

                Mapping mapping = new Mapping((Protocol)((int)entry.Protocol), entry.PrivatePort, entry.PublicPort, entry.Description);
                await device.CreatePortMapAsync(mapping);

                return true;
            }
            catch (NatDeviceNotFoundException NfExc)
            {
                //log exc
                return false;
            }
            catch (MappingException MExc)
            {
                //log exc
                return false;
            }
        }
예제 #7
0
		public override async Task DeletePortMapAsync(Mapping mapping)
		{
            Guard.IsNotNull(mapping, "mapping");

            try
		    {
                var message = new DeletePortMappingRequestMessage(mapping);
                await _soapClient
                    .InvokeAsync("DeletePortMapping", message.ToXml())
                    .TimeoutAfter(TimeSpan.FromSeconds(4));
                UnregisterMapping(mapping);
            }
		    catch (MappingException e)
		    {
                if(e.ErrorCode != UpnpConstants.NoSuchEntryInArray) throw; 
		    }
        }
 public DeletePortMappingRequestMessage(Mapping mapping)
 {
     _mapping = mapping;
 }
예제 #9
0
        private void CreatePortMapListen(UdpClient udpClient, Mapping mapping)
        {
            var endPoint = new IPEndPoint(LocalAddress, PmpConstants.ServerPort);

            while (true)
            {
                byte[] data = udpClient.Receive(ref endPoint);

                if (data.Length < 16)
                    continue;

                if (data[0] != PmpConstants.Version)
                    continue;

                var opCode = (byte) (data[1] & 127);

                var protocol = Protocol.Tcp;
                if (opCode == PmpConstants.OperationCodeUdp)
                    protocol = Protocol.Udp;

                short resultCode = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data, 2));
                int epoch = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data, 4));

                short privatePort = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data, 8));
                short publicPort = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(data, 10));

                var lifetime = (uint) IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data, 12));

                if (privatePort < 0 || publicPort < 0 || resultCode != PmpConstants.ResultCodeSuccess)
                {
                    var errors = new[]
                                     {
                                         "Success",
                                         "Unsupported Version",
                                         "Not Authorized/Refused (e.g. box supports mapping, but user has turned feature off)"
                                         ,
                                         "Network Failure (e.g. NAT box itself has not obtained a DHCP lease)",
                                         "Out of resources (NAT box cannot create any more mappings at this time)",
                                         "Unsupported opcode"
                                     };
                    throw new MappingException(resultCode, errors[resultCode]);
                }

                if (lifetime == 0) return; //mapping was deleted

                //mapping was created
                //TODO: verify that the private port+protocol are a match
                mapping.PublicPort = publicPort;
                mapping.Protocol = protocol;
                mapping.Expiration = DateTime.Now.AddSeconds(lifetime);
                return;
            }
        }
예제 #10
0
 /// <summary>
 /// Creates the port map asynchronous.
 /// </summary>
 /// <param name="mapping">The <see cref="Mapping">Mapping</see> entry.</param>
 /// <example>
 /// device.CreatePortMapAsync(new Mapping(Protocol.Tcp, 1700, 1600));
 /// </example>
 /// <exception cref="MappingException">MappingException</exception>
 public abstract Task CreatePortMapAsync(Mapping mapping);
예제 #11
0
        private Task RenewMapping(Mapping mapping)
        {
            var renewMapping = new Mapping(mapping);
            renewMapping.Expiration = DateTime.UtcNow.AddSeconds(mapping.Lifetime);

            NatDiscoverer.TraceSource.LogInfo("Renewing mapping {0}", renewMapping);
            return CreatePortMapAsync(renewMapping)
                .ContinueWith(task =>
                {
                    if (task.IsFaulted)
                    {
                        NatDiscoverer.TraceSource.LogWarn("Renew {0} failed", mapping);
                    }
                    else
                    {
                        NatDiscoverer.TraceSource.LogInfo("Next renew scheduled at: {0}",
                                                            renewMapping.Expiration.ToLocalTime().TimeOfDay);
                    }
                });
        }
예제 #12
0
 protected void RegisterMapping(Mapping mapping)
 {
     _openedMapping.Remove(mapping);
     _openedMapping.Add(mapping);
 }
예제 #13
0
 /// <summary>
 /// Deletes a mapped port asynchronous.
 /// </summary>
 /// <param name="mapping">The <see cref="Mapping">Mapping</see> entry.</param>
 /// <example>
 /// device.DeletePortMapAsync(new Mapping(Protocol.Tcp, 1700, 1600));
 /// </example>
 /// <exception cref="MappingException">MappingException-class</exception>
 public abstract Task DeletePortMapAsync(Mapping mapping);
예제 #14
0
 /// <summary>
 /// Creates the port map asynchronous.
 /// </summary>
 /// <param name="mapping">The <see cref="Mapping">Mapping</see> entry.</param>
 /// <example>
 /// device.CreatePortMapAsync(new Mapping(Protocol.Tcp, 1700, 1600));
 /// </example>
 /// <exception cref="MappingException">MappingException</exception>
 public abstract Task CreatePortMapAsync(Mapping mapping);
예제 #15
0
 protected void UnregisterMapping(Mapping mapping)
 {
     _openedMapping.RemoveWhere(x => x.Equals(mapping));
 }
예제 #16
0
 protected void RegisterMapping(Mapping mapping)
 {
     _openedMapping.Remove(mapping);
     _openedMapping.Add(mapping);
 }
예제 #17
0
        public override Task CreatePortMapAsync(Mapping mapping)
        {
            Guard.IsNotNull(mapping, "mapping");
            if (mapping.PrivateIP.Equals(IPAddress.None))
            {
                mapping.PrivateIP = DeviceInfo.LocalAddress;
            }

            NatDiscoverer.TraceSource.LogInfo("CreatePortMapAsync - Creating port mapping {0}", mapping);

            var message = new CreatePortMappingRequestMessage(mapping);

            return(_soapClient
                   .InvokeAsync("AddPortMapping", message.ToXml())
                   .TimeoutAfter(TimeSpan.FromSeconds(4))
                   .ContinueWith(task =>
            {
                if (!task.IsFaulted)
                {
                    RegisterMapping(mapping);
                }
                else
                {
                    MappingException me = task.Exception.InnerException as MappingException;

                    if (me == null)
                    {
                        throw task.Exception.InnerException;
                    }

                    switch (me.ErrorCode)
                    {
                    case UpnpConstants.OnlyPermanentLeasesSupported:
                        NatDiscoverer.TraceSource.LogWarn(
                            "Only Permanent Leases Supported - There is no warranty it will be closed");
                        mapping.Lifetime = 0;
                        // We create the mapping anyway. It must be released on shutdown.
                        mapping.LifetimeType = MappingLifetime.ForcedSession;
                        CreatePortMapAsync(mapping);
                        break;

                    case UpnpConstants.SamePortValuesRequired:
                        NatDiscoverer.TraceSource.LogWarn(
                            "Same Port Values Required - Using internal port {0}", mapping.PrivatePort);
                        mapping.PublicPort = mapping.PrivatePort;
                        CreatePortMapAsync(mapping);
                        break;

                    case UpnpConstants.RemoteHostOnlySupportsWildcard:
                        NatDiscoverer.TraceSource.LogWarn("Remote Host Only Supports Wildcard");
                        mapping.PublicIP = IPAddress.None;
                        CreatePortMapAsync(mapping);
                        break;

                    case UpnpConstants.ExternalPortOnlySupportsWildcard:
                        NatDiscoverer.TraceSource.LogWarn("External Port Only Supports Wildcard");
                        throw me;

                    case UpnpConstants.ConflictInMappingEntry:
                        NatDiscoverer.TraceSource.LogWarn("Conflict with an already existing mapping");
                        throw me;

                    default:
                        throw me;
                    }
                }
            }));
        }
예제 #18
0
        public void GetGenericMappingAsync(int index, List <Mapping> mappings,
                                           TaskCompletionSource <IEnumerable <Mapping> > taskCompletionSource)
        {
            var message = new GetGenericPortMappingEntry(index);

            _soapClient
            .InvokeAsync("GetGenericPortMappingEntry", message.ToXml())
            .TimeoutAfter(TimeSpan.FromSeconds(4))
            .ContinueWith(task =>
            {
                if (!task.IsFaulted)
                {
                    var responseData    = task.Result;
                    var responseMessage = new GetPortMappingEntryResponseMessage(responseData,
                                                                                 DeviceInfo.ServiceType, true);

                    IPAddress internalClientIp;
                    if (!IPAddress.TryParse(responseMessage.InternalClient, out internalClientIp))
                    {
                        NatDiscoverer.TraceSource.LogWarn("InternalClient is not an IP address. Mapping ignored!");
                    }
                    else
                    {
                        var mapping = new Mapping(responseMessage.Protocol
                                                  , internalClientIp
                                                  , responseMessage.InternalPort
                                                  , responseMessage.ExternalPort
                                                  , responseMessage.LeaseDuration
                                                  , responseMessage.PortMappingDescription);
                        mappings.Add(mapping);
                    }

                    GetGenericMappingAsync(index + 1, mappings, taskCompletionSource);
                }
                else
                {
                    MappingException e = task.Exception.InnerException as MappingException;

                    if (e == null)
                    {
                        throw task.Exception.InnerException;
                    }

                    if (e.ErrorCode == UpnpConstants.SpecifiedArrayIndexInvalid ||
                        e.ErrorCode == UpnpConstants.NoSuchEntryInArray)
                    {
                        // there are no more mappings
                        taskCompletionSource.SetResult(mappings);
                        return;
                    }

                    // DD-WRT Linux base router (and others probably) fails with 402-InvalidArgument when index is out of range
                    if (e.ErrorCode == UpnpConstants.InvalidArguments)
                    {
                        NatDiscoverer.TraceSource.LogWarn("Router failed with 402-InvalidArgument. No more mappings is assumed.");
                        taskCompletionSource.SetResult(mappings);
                        return;
                    }

                    throw task.Exception.InnerException;
                }
            });
        }
예제 #19
0
		public override async Task<IEnumerable<Mapping>> GetAllMappingsAsync()
		{
            var index = 0;
		    var mappings = new List<Mapping>();

            while (true)
            {
                try
                {
                    var message = new GetGenericPortMappingEntry(index);

                    var responseData = await _soapClient
                        .InvokeAsync("GetGenericPortMappingEntry", message.ToXml())
                        .TimeoutAfter(TimeSpan.FromSeconds(4));

                    var responseMessage = new GetPortMappingEntryResponseMessage(responseData, DeviceInfo.ServiceType, true);

                    var mapping = new Mapping(responseMessage.Protocol
                        , IPAddress.Parse(responseMessage.InternalClient)
                        , responseMessage.InternalPort
                        , responseMessage.ExternalPort
                        , responseMessage.LeaseDuration
                        , responseMessage.PortMappingDescription);
                    mappings.Add(mapping);
                    index++;
                }
                catch (MappingException e)
                {
                    if (e.ErrorCode == UpnpConstants.SpecifiedArrayIndexInvalid) break; // there are no more mappings
                    throw;
                }
            }

            return mappings.ToArray();
        }
예제 #20
0
 internal Mapping(Mapping mapping)
 {
     PrivateIP = mapping.PrivateIP;
     PrivatePort = mapping.PrivatePort;
     Protocol = mapping.Protocol;
     PublicIP = mapping.PublicIP;
     PublicPort = mapping.PublicPort;
     LifetimeType = mapping.LifetimeType;
     Description = mapping.Description;
     _lifetime = mapping._lifetime;
     _expiration = mapping._expiration;
 }
예제 #21
0
 public CreatePortMappingRequestMessage(Mapping mapping)
 {
     _mapping = mapping;
 }
예제 #22
0
 protected void UnregisterMapping(Mapping mapping)
 {
     _openedMapping.RemoveWhere(x => x.Equals(mapping));
 }
예제 #23
0
        public override Task DeletePortMapAsync(Mapping mapping)
        {
            Guard.IsNotNull(mapping, "mapping");

            if (mapping.PrivateIP.Equals(IPAddress.None)) mapping.PrivateIP = DeviceInfo.LocalAddress;

            NatDiscoverer.TraceSource.LogInfo("DeletePortMapAsync - Deleteing port mapping {0}", mapping);

            var message = new DeletePortMappingRequestMessage(mapping);
            return _soapClient
                .InvokeAsync("DeletePortMapping", message.ToXml())
                .TimeoutAfter(TimeSpan.FromSeconds(4))
                .ContinueWith(task =>
                {
                    if (!task.IsFaulted)
                    {
                        UnregisterMapping(mapping);
                    }
                    else
                    {
                        MappingException e = task.Exception.InnerException as MappingException;
                        if (e != null && e.ErrorCode != UpnpConstants.NoSuchEntryInArray) throw e;
                    }
                });
        }
예제 #24
0
        private async Task RenewMapping(Mapping mapping)
        {
            var renewMapping = new Mapping(mapping);
            try
            {
                renewMapping.Expiration = DateTime.UtcNow.AddSeconds(mapping.Lifetime);

                NatDiscoverer.TraceSource.LogInfo("Renewing mapping {0}", renewMapping);
                await CreatePortMapAsync(renewMapping);
                NatDiscoverer.TraceSource.LogInfo("Next renew scheduled at: {0}",
                                                  renewMapping.Expiration.ToLocalTime().TimeOfDay);
            }
            catch (Exception)
            {
                NatDiscoverer.TraceSource.LogWarn("Renew {0} failed", mapping);
            }
        }
예제 #25
0
        public void GetGenericMappingAsync(int index, List<Mapping> mappings,
            TaskCompletionSource<IEnumerable<Mapping>> taskCompletionSource)
        {
            var message = new GetGenericPortMappingEntry(index);

            _soapClient
                .InvokeAsync("GetGenericPortMappingEntry", message.ToXml())
                .TimeoutAfter(TimeSpan.FromSeconds(4))
                .ContinueWith(task =>
                {
                    if (!task.IsFaulted)
                    {
                        var responseData = task.Result;
                        var responseMessage = new GetPortMappingEntryResponseMessage(responseData,
                            DeviceInfo.ServiceType, true);

                        IPAddress internalClientIp;
                        if (!IPAddress.TryParse(responseMessage.InternalClient, out internalClientIp))
                        {
                            NatDiscoverer.TraceSource.LogWarn("InternalClient is not an IP address. Mapping ignored!");
                        }
                        else
                        {
                            var mapping = new Mapping(responseMessage.Protocol
                                , internalClientIp
                                , responseMessage.InternalPort
                                , responseMessage.ExternalPort
                                , responseMessage.LeaseDuration
                                , responseMessage.PortMappingDescription);
                            mappings.Add(mapping);
                        }

                        GetGenericMappingAsync(index + 1, mappings, taskCompletionSource);
                    }
                    else
                    {
                        MappingException e = task.Exception.InnerException as MappingException;

                        if (e == null)
                        {
                            throw task.Exception.InnerException;
                        }

                        if (e.ErrorCode == UpnpConstants.SpecifiedArrayIndexInvalid
                            || e.ErrorCode == UpnpConstants.NoSuchEntryInArray)
                        {
                            // there are no more mappings
                            taskCompletionSource.SetResult(mappings);
                            return;
                        }

                        // DD-WRT Linux base router (and others probably) fails with 402-InvalidArgument when index is out of range
                        if (e.ErrorCode == UpnpConstants.InvalidArguments)
                        {
                            NatDiscoverer.TraceSource.LogWarn("Router failed with 402-InvalidArgument. No more mappings is assumed.");
                            taskCompletionSource.SetResult(mappings);
                            return;
                        }

                        throw task.Exception.InnerException;
                    }
                });
        }
예제 #26
0
 /// <summary>
 /// Deletes a mapped port asynchronous.
 /// </summary>
 /// <param name="mapping">The <see cref="Mapping">Mapping</see> entry.</param>
 /// <example>
 /// device.DeletePortMapAsync(new Mapping(Protocol.Tcp, 1700, 1600));
 /// </example>
 /// <exception cref="MappingException">MappingException-class</exception>
 public abstract Task DeletePortMapAsync(Mapping mapping);
예제 #27
0
		public override async Task<IEnumerable<Mapping>> GetAllMappingsAsync()
		{
            var index = 0;
		    var mappings = new List<Mapping>();

            NatDiscoverer.TraceSource.LogInfo("GetAllMappingsAsync - Getting all mappings");
            while (true)
            {
                try
                {
                    var message = new GetGenericPortMappingEntry(index++);

                    var responseData = await _soapClient
                        .InvokeAsync("GetGenericPortMappingEntry", message.ToXml())
                        .TimeoutAfter(TimeSpan.FromSeconds(4));

                    var responseMessage = new GetPortMappingEntryResponseMessage(responseData, DeviceInfo.ServiceType, true);

                    IPAddress internalClientIp;
                    if(!IPAddress.TryParse(responseMessage.InternalClient, out internalClientIp))
                    {
                        NatDiscoverer.TraceSource.LogWarn("InternalClient is not an IP address. Mapping ignored!");
                        continue;
                    }

                    var mapping = new Mapping(responseMessage.Protocol
                        , internalClientIp
                        , responseMessage.InternalPort
                        , responseMessage.ExternalPort
                        , responseMessage.LeaseDuration
                        , responseMessage.PortMappingDescription);
                    mappings.Add(mapping);
                }
                catch (MappingException e)
                {
                    // there are no more mappings
                    if (e.ErrorCode == UpnpConstants.SpecifiedArrayIndexInvalid
                     || e.ErrorCode == UpnpConstants.NoSuchEntryInArray
                     // DD-WRT Linux base router (and others probably) fails with 402-InvalidArgument when index is out of range
                     || e.ErrorCode == UpnpConstants.InvalidArguments
                     // LINKSYS WRT1900AC AC1900 it returns errocode 501-PAL_UPNP_SOAP_E_ACTION_FAILED
                     || e.ErrorCode == UpnpConstants.ActionFailed)
                    {
                        NatDiscoverer.TraceSource.LogWarn("Router failed with {0}-{1}. No more mappings is assumed.", e.ErrorCode, e.ErrorText);
                        break; 
                    }
                    throw;
                }
            }

            return mappings.ToArray();
        }
예제 #28
0
 public override async Task DeletePortMapAsync(Mapping mapping)
 {
     await InternalCreatePortMapAsync(mapping, false)
         .TimeoutAfter(TimeSpan.FromSeconds(4));
     UnregisterMapping(mapping);
 }
예제 #29
0
        private Task<Mapping> InternalCreatePortMapAsync(Mapping mapping, bool create)
        {
            var package = new List<byte>();

            package.Add(PmpConstants.Version);
            package.Add(mapping.Protocol == Protocol.Tcp ? PmpConstants.OperationCodeTcp : PmpConstants.OperationCodeUdp);
            package.Add(0); //reserved
            package.Add(0); //reserved
            package.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short) mapping.PrivatePort)));
            package.AddRange(
                BitConverter.GetBytes(create ? IPAddress.HostToNetworkOrder((short) mapping.PublicPort) : (short) 0));
            package.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(mapping.Lifetime)));

            byte[] buffer = package.ToArray();
            int attempt = 0;
            int delay = PmpConstants.RetryDelay;

            var udpClient = new UdpClient();
            CreatePortMapListen(udpClient, mapping);

            Task task = Task.Factory.FromAsync<byte[], int, IPEndPoint, int>(
                        udpClient.BeginSend, udpClient.EndSend,
                        buffer, buffer.Length,
                        new IPEndPoint(LocalAddress, PmpConstants.ServerPort),
                        null);

            while (attempt < PmpConstants.RetryAttempts - 1)
            {
                task = task.ContinueWith(t =>
                {
                    if (t.IsFaulted)
                    {
                        string type = create ? "create" : "delete";
                        string message = String.Format("Failed to {0} portmap (protocol={1}, private port={2})",
                            type,
                            mapping.Protocol,
                            mapping.PrivatePort);
                        NatDiscoverer.TraceSource.LogError(message);
                        throw new MappingException(message, t.Exception);
                    }

                    return Task.Factory.FromAsync<byte[], int, IPEndPoint, int>(
                        udpClient.BeginSend, udpClient.EndSend,
                        buffer, buffer.Length,
                        new IPEndPoint(LocalAddress, PmpConstants.ServerPort),
                        null);
                }).Unwrap();

                attempt++;
                delay *= 2;
                Thread.Sleep(delay);
            }

            return task.ContinueWith(t =>
            {
                udpClient.Close();
                return mapping;
            });
        }
예제 #30
0
		public override async Task DeletePortMapAsync(Mapping mapping)
		{
            Guard.IsNotNull(mapping, "mapping");

            if (mapping.PrivateIP.Equals(IPAddress.None)) mapping.PrivateIP = DeviceInfo.LocalAddress;
            
            NatDiscoverer.TraceSource.LogInfo("DeletePortMapAsync - Deleteing port mapping {0}", mapping);

            try
		    {
                var message = new DeletePortMappingRequestMessage(mapping);
                await _soapClient
                    .InvokeAsync("DeletePortMapping", message.ToXml())
                    .TimeoutAfter(TimeSpan.FromSeconds(4));
                UnregisterMapping(mapping);
            }
		    catch (MappingException e)
		    {
                if(e.ErrorCode != UpnpConstants.NoSuchEntryInArray) throw; 
		    }
        }
예제 #31
0
 public override Task DeletePortMapAsync(Mapping mapping)
 {
     return InternalCreatePortMapAsync(mapping, false)
         .TimeoutAfter(TimeSpan.FromSeconds(4))
         .ContinueWith(t => UnregisterMapping(mapping));
 }
 public CreatePortMappingRequestMessage(Mapping mapping)
 {
     _mapping = mapping;
 }
예제 #33
0
 public DeletePortMappingRequestMessage(Mapping mapping)
 {
     _mapping = mapping;
 }