private void StunRequest(EndPoint stunEndPoint, StunPacket packet, Action <StunPacket> callback) { bool hasresponded = false; Action <EndPoint, byte[]> action = null; //--------------------------------------- // the stun response handler. //--------------------------------------- action = new Action <EndPoint, byte[]>((endpoint, data) => { //--------------------------------------------- // here, we try and catch any parse errors, which // may originate from other things attempting to // send data to this socket. //--------------------------------------------- try { StunPacket response = new StunPacket(); response.Parse(data); this.OnMessage -= action; hasresponded = true; callback(response); } catch { } }); //--------------------------------------- // setup timeout in case of no response. //--------------------------------------- Reactor.Timeout.Create(() => { if (!hasresponded) { this.OnMessage -= action; callback(null); } }, 2000); //--------------------------------------- // set on response, make request. //--------------------------------------- this.OnMessage += action; this.Send(stunEndPoint, packet.ToByteData()); }
private void StunRequest(EndPoint stunEndPoint, StunPacket packet, Action<StunPacket> callback) { bool hasresponded = false; Action<EndPoint, byte[]> action = null; //--------------------------------------- // the stun response handler. //--------------------------------------- action = new Action<EndPoint, byte[]>((endpoint, data) => { //--------------------------------------------- // here, we try and catch any parse errors, which // may originate from other things attempting to // send data to this socket. //--------------------------------------------- try { StunPacket response = new StunPacket(); response.Parse(data); this.OnMessage -= action; hasresponded = true; callback(response); } catch { } }); //--------------------------------------- // setup timeout in case of no response. //--------------------------------------- Reactor.Timeout.Create(() => { if (!hasresponded) { this.OnMessage -= action; callback(null); } }, 2000); //--------------------------------------- // set on response, make request. //--------------------------------------- this.OnMessage += action; this.Send(stunEndPoint, packet.ToByteData()); }
/// <summary> /// Pings a stun server and obtains a limited time public ip and port for this UDP socket. /// </summary> /// <param name="Host">The IP address of the Stun Server.</param> /// <param name="Port">The port of the Stun Server.</param> /// <param name="callback">A callback with the Stun response.</param> public void Stun(string Host, int Port, Action <Exception, StunResponse> callback) { //---------------------------------------------------------------- // save any events on this socket. //---------------------------------------------------------------- var actions = new List <Action <EndPoint, byte[]> >(); if (this.OnMessage != null) { foreach (var _action in this.OnMessage.GetInvocationList()) { var action = (Action <EndPoint, byte[]>)_action; actions.Add(action); this.OnMessage -= action; } } //---------------------------------------------------------------- // resolve stun endpoint. //---------------------------------------------------------------- Reactor.Net.Dns.GetHostAddresses(Host, (exception0, addresses) => { if (exception0 != null) { callback(exception0, null); return; } var remoteEP = new IPEndPoint(addresses[0], Port); StunPacket test1 = new StunPacket(); test1.Type = PacketType.BindingRequest; this.StunRequest(remoteEP, test1, (test1response) => { if (test1response == null) { foreach (var action in actions) { this.OnMessage += action; } callback(null, new StunResponse(NatType.UdpBlocked, null)); } else { if (this.LocalEndPoint.Equals(test1response.MappedAddress)) { StunPacket test2 = new StunPacket(); test2.Type = PacketType.BindingRequest; test2.ChangeRequest = new ChangeRequest(true, true); this.StunRequest(remoteEP, test2, (test2response) => { if (test2response == null) { foreach (var action in actions) { this.OnMessage += action; } callback(null, new StunResponse(NatType.SymmetricUdpFirewall, test1response.MappedAddress)); } else { foreach (var action in actions) { this.OnMessage += action; } callback(null, new StunResponse(NatType.OpenInternet, test1response.MappedAddress)); } }); } else { StunPacket test2 = new StunPacket(); test2.Type = PacketType.BindingRequest; test2.ChangeRequest = new ChangeRequest(true, true); this.StunRequest(remoteEP, test2, (test2response) => { if (test2response != null) { foreach (var action in actions) { this.OnMessage += action; } callback(null, new StunResponse(NatType.FullCone, test1response.MappedAddress)); } else { // Test I(II) StunPacket test12 = new StunPacket(); test12.Type = PacketType.BindingRequest; this.StunRequest(remoteEP, test12, (test12response) => { if (test12response == null) { foreach (var action in actions) { this.OnMessage += action; } callback(null, new StunResponse(NatType.UdpBlocked, null)); } else { StunPacket test3 = new StunPacket(); test3.Type = PacketType.BindingRequest; test3.ChangeRequest = new ChangeRequest(false, true); this.StunRequest(remoteEP, test3, (test3response) => { if (test3response == null) { foreach (var action in actions) { this.OnMessage += action; } callback(null, new StunResponse(NatType.PortRestrictedCone, test1response.MappedAddress)); } else { foreach (var action in actions) { this.OnMessage += action; } callback(null, new StunResponse(NatType.RestrictedCone, test1response.MappedAddress)); } }); } }); } }); } } }); }); }
/// <summary> /// Pings a stun server and obtains a limited time public ip and port for this UDP socket. /// </summary> /// <param name="Host">The IP address of the Stun Server.</param> /// <param name="Port">The port of the Stun Server.</param> /// <param name="callback">A callback with the Stun response.</param> public void Stun(string Host, int Port, Action<Exception, StunResponse> callback) { //---------------------------------------------------------------- // save any events on this socket. //---------------------------------------------------------------- var actions = new List<Action<EndPoint, byte[]>>(); if(this.OnMessage != null) { foreach(var _action in this.OnMessage.GetInvocationList()) { var action = (Action<EndPoint, byte[]>)_action; actions.Add(action); this.OnMessage -= action; } } //---------------------------------------------------------------- // resolve stun endpoint. //---------------------------------------------------------------- Reactor.Net.Dns.GetHostAddresses(Host, (exception0, addresses) => { if (exception0 != null) { callback(exception0, null); return; } var remoteEP = new IPEndPoint(addresses[0], Port); StunPacket test1 = new StunPacket(); test1.Type = PacketType.BindingRequest; this.StunRequest(remoteEP, test1, (test1response) => { if (test1response == null) { foreach(var action in actions) { this.OnMessage += action; } callback(null, new StunResponse(NatType.UdpBlocked, null)); } else { if (this.LocalEndPoint.Equals(test1response.MappedAddress)) { StunPacket test2 = new StunPacket(); test2.Type = PacketType.BindingRequest; test2.ChangeRequest = new ChangeRequest(true, true); this.StunRequest(remoteEP, test2, (test2response) => { if (test2response == null) { foreach(var action in actions) { this.OnMessage += action; } callback(null, new StunResponse(NatType.SymmetricUdpFirewall, test1response.MappedAddress)); } else { foreach(var action in actions) { this.OnMessage += action; } callback(null, new StunResponse(NatType.OpenInternet, test1response.MappedAddress)); } }); } else { StunPacket test2 = new StunPacket(); test2.Type = PacketType.BindingRequest; test2.ChangeRequest = new ChangeRequest(true, true); this.StunRequest(remoteEP, test2, (test2response) => { if (test2response != null) { foreach(var action in actions) { this.OnMessage += action; } callback(null, new StunResponse(NatType.FullCone, test1response.MappedAddress)); } else { // Test I(II) StunPacket test12 = new StunPacket(); test12.Type = PacketType.BindingRequest; this.StunRequest(remoteEP, test12, (test12response) => { if (test12response == null) { foreach(var action in actions) { this.OnMessage += action; } callback(null, new StunResponse(NatType.UdpBlocked, null)); } else { StunPacket test3 = new StunPacket(); test3.Type = PacketType.BindingRequest; test3.ChangeRequest = new ChangeRequest(false, true); this.StunRequest(remoteEP, test3, (test3response) => { if (test3response == null) { foreach(var action in actions) { this.OnMessage += action; } callback(null, new StunResponse(NatType.PortRestrictedCone, test1response.MappedAddress)); } else { foreach(var action in actions) { this.OnMessage += action; } callback(null, new StunResponse(NatType.RestrictedCone, test1response.MappedAddress)); } }); } }); } }); } } }); }); }