public override Task <Mapping> GetSpecificMappingAsync(Protocol protocol, int publicPort) { Guard.IsTrue(protocol == Protocol.Tcp || protocol == Protocol.Udp, "protocol"); Guard.IsInRange(publicPort, 0, ushort.MaxValue, "port"); NatDiscoverer.TraceSource.LogInfo("GetSpecificMappingAsync - Getting mapping for protocol: {0} port: {1}", Enum.GetName(typeof(Protocol), protocol), publicPort); var message = new GetSpecificPortMappingEntryRequestMessage(protocol, publicPort); return(_soapClient .InvokeAsync("GetSpecificPortMappingEntry", message.ToXml()) .TimeoutAfter(TimeSpan.FromSeconds(4)) .ContinueWith(task => { if (!task.IsFaulted) { var responseData = task.Result; var messageResponse = new GetPortMappingEntryResponseMessage(responseData, DeviceInfo.ServiceType, false); return new Mapping(messageResponse.Protocol , IPAddress.Parse(messageResponse.InternalClient) , messageResponse.InternalPort , publicPort // messageResponse.ExternalPort is short.MaxValue , messageResponse.LeaseDuration , messageResponse.PortMappingDescription); } else { MappingException e = task.Exception.InnerException as MappingException; if (e != null && e.ErrorCode == UpnpConstants.NoSuchEntryInArray) { return null; } // DD-WRT Linux base router (and others probably) fails with 402-InvalidArgument // when no mapping is found in the mappings table if (e != null && e.ErrorCode == UpnpConstants.InvalidArguments) { NatDiscoverer.TraceSource.LogWarn("Router failed with 402-InvalidArgument. Mapping not found is assumed."); return null; } throw task.Exception.InnerException; } })); }
public override async Task <Mapping> GetSpecificMappingAsync(Protocol protocol, int publicPort) { Guard.IsTrue(protocol == Protocol.Tcp || protocol == Protocol.Udp, "protocol"); Guard.IsInRange(publicPort, 0, ushort.MaxValue, "port"); NatDiscoverer.TraceSource.LogInfo("GetSpecificMappingAsync - Getting mapping for protocol: {0} port: {1}", Enum.GetName(typeof(Protocol), protocol), publicPort); try { var message = new GetSpecificPortMappingEntryRequestMessage(protocol, publicPort); var responseData = await _soapClient .InvokeAsync("GetSpecificPortMappingEntry", message.ToXml()) .TimeoutAfter(TimeSpan.FromSeconds(4)); var messageResponse = new GetPortMappingEntryResponseMessage(responseData, DeviceInfo.ServiceType, false); if (messageResponse.Protocol != protocol) { NatDiscoverer.TraceSource.LogWarn("Router responded to a protocol {0} query with a protocol {1} answer, work around applied.", protocol, messageResponse.Protocol); } return(new Mapping(protocol , IPAddress.Parse(messageResponse.InternalClient) , messageResponse.InternalPort , publicPort // messageResponse.ExternalPort is short.MaxValue , messageResponse.LeaseDuration , messageResponse.PortMappingDescription)); } 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); return(null); } throw; } }