private void CreatePortMapAsync(object obj) { CreatePortMapAsyncState state = obj as CreatePortMapAsyncState; UdpClient udpClient = new UdpClient(); CreatePortMapListenState listenState = new CreatePortMapListenState(state, udpClient); int attempt = 0; int delay = PmpConstants.RetryDelay; ThreadPool.QueueUserWorkItem(new WaitCallback(CreatePortMapListen), listenState); while (attempt < PmpConstants.RetryAttempts && !listenState.Success) { udpClient.Send(state.Buffer, state.Buffer.Length, new IPEndPoint(localAddress, PmpConstants.ServerPort)); listenState.UdpClientReady.Set(); attempt++; delay *= 2; Thread.Sleep(delay); } state.Success = listenState.Success; udpClient.Close(); state.ResetEvent.Set(); }
private Mapping CreatePortMap(Mapping mapping, bool create) { List <byte> package = new List <byte> (); package.Add(PmpConstants.Version); package.Add(mapping.Protocol == Protocol.Tcp ? PmpConstants.OperationCodeTcp : PmpConstants.OperationCodeUdp); package.Add((byte)0); //reserved package.Add((byte)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))); CreatePortMapAsyncState state = new CreatePortMapAsyncState(); state.Buffer = package.ToArray(); state.Mapping = mapping; ThreadPool.QueueUserWorkItem(new WaitCallback(CreatePortMapAsync), state); WaitHandle.WaitAll(new WaitHandle[] { state.ResetEvent }); if (!state.Success) { string type = create ? "create" : "delete"; throw new MappingException(String.Format("Failed to {0} portmap (protocol={1}, private port={2}", type, mapping.Protocol, mapping.PrivatePort)); } return(state.Mapping); }
internal CreatePortMapListenState(CreatePortMapAsyncState state, UdpClient client) { Mapping = state.Mapping; UdpClient = client; UdpClientReady = new ManualResetEvent(false); }