/// <summary> /// Helper method using UDP or TCP that returns needed informations to begin peer-to-peer Punch Hole operations /// using an existing IPEndPoint /// </summary> /// <param name="hostEP">The IPEndPoint to which the socket will be bound to</param> /// <param name="serverEP">The IP Address of the STUN server</param> /// <param name="type">The connection type used to do the STUN Binding Request</param> /// <returns> /// A key-value pair where : /// * the key is the local IPEndPoint from where the STUN request occurs /// * the value is the MappedAddress IPEndPoint returned by the STUN server /// </returns> public static KeyValuePair <IPEndPoint, IPEndPoint> GetMappedAddressFrom(IPEndPoint hostEP, IPEndPoint serverEP, ProtocolType type) { StunMessage msg = new StunMessage(StunMethodType.Binding, StunMethodClass.Request, StunUtilities.NewTransactionId); StunClient cli = new StunClient(hostEP, serverEP, type, null, null); cli.Connect(); StunMessage resp = cli.SendMessage(msg); if (hostEP == null) { hostEP = cli.HostEP; } MappedAddress mappedAddress = resp.MappedAddress; cli.Disconnect(); return(new KeyValuePair <IPEndPoint, IPEndPoint>(hostEP, mappedAddress.EndPoint)); }
/// <summary> /// Helper method using TLS over TCP that returns needed informations to begin peer-to-peer Punch Hole operations /// using an existing IPEndPoint /// </summary> /// <param name="hostEP">The IPEndPoint to which the socket will be bound to</param> /// <param name="serverEP">The IP Address of the STUN server</param> /// <param name="remoteCertificateValidationHandler">The callback handler which validate STUN Server TLS certificate</param> /// <param name="clientCertificate"> /// Client certificate used for mutual authentication. This certificate must be in PKCS #12 format and must contains its private key /// The simpler way to create a certificate of this type is to follow this makecert tutorial http://www.inventec.ch/chdh/notes/14.htm. /// Once your certificate is created : launch "mmc", CTRL+M, select "Certificates", add, choose "Local machine". /// Find your certificate under "Personal", it must have a little key in its icon, right click on it, choose "All tasks > Export...". /// Check the "Export key" checkbox, finish the process and then you have a valid X509Certificate2 with its private key in it /// </param> /// <returns> /// A key-value pair where : /// * the key is the local IPEndPoint from where the STUN request occurs /// * the value is the MappedAddress IPEndPoint returned by the STUN server /// </returns> public static KeyValuePair <IPEndPoint, IPEndPoint> GetMappedAddressFrom(IPEndPoint hostEP, IPEndPoint serverEP, RemoteCertificateValidationCallback remoteCertificateValidationHandler, X509Certificate2 clientCertificate) { StunMessage msg = new StunMessage(StunMethodType.Binding, StunMethodClass.Request, StunUtilities.NewTransactionId); StunClient cli = new StunClient(hostEP, serverEP, ProtocolType.Tcp, clientCertificate, remoteCertificateValidationHandler); cli.Connect(); StunMessage resp = cli.SendMessage(msg); if (hostEP == null) { hostEP = cli.HostEP; } MappedAddress mappedAddress = resp.MappedAddress; cli.Disconnect(); return(new KeyValuePair <IPEndPoint, IPEndPoint>(hostEP, mappedAddress.EndPoint)); }
/// <summary> /// Sample usage of this StunClient /// </summary> /// <param name="args">Unused</param> private static void Main(string[] args) { KeyValuePair <IPEndPoint, IPEndPoint> stunKeyValue = StunUtilities.GetMappedAddressFrom(null, new IPEndPoint(IPAddress.Parse("66.228.45.110"), StunClient.DEFAULT_STUN_PORT), ProtocolType.Udp); StunMessage msg = new StunMessage(StunMethodType.Binding, StunMethodClass.Request, StunUtilities.NewTransactionId); msg.Stun.Realm = new UTF8Attribute(StunAttributeType.Realm, "Hello World !"); msg.Stun.Username = new UTF8Attribute(StunAttributeType.Username, "Bob"); byte[] octets = msg; StunMessage msgCopy = octets; // Reuse of an existing local IPEndPoint makes the three requests returning // the same MappedAddress IPEndPoint if this client is behind a Cone NAT StunClient cli1 = new StunClient(stunKeyValue.Key, new IPEndPoint(IPAddress.Parse("66.228.45.110"), StunClient.DEFAULT_STUNS_PORT), ProtocolType.Tcp, null, (sender, certificate, chain, sslPolicyErrors) => true); // Sample TLS over TCP working with ejabberd but may not work with the sample server IP given here cli1.Connect(); StunMessage resp1 = cli1.SendMessage(msgCopy); cli1.Disconnect(); msgCopy.ClearAttributes(); StunClient cli2 = new StunClient(stunKeyValue.Key, new IPEndPoint(IPAddress.Parse("132.177.123.13"), StunClient.DEFAULT_STUN_PORT), ProtocolType.Udp, null, null); cli2.Connect(); StunMessage resp2 = cli2.SendMessage(msgCopy); cli2.Disconnect(); }
/// <summary> /// Sample usage of this StunClient /// </summary> /// <param name="args">Unused</param> private static void Main(string[] args) { KeyValuePair<IPEndPoint, IPEndPoint> stunKeyValue = StunUtilities.GetMappedAddressFrom(null, new IPEndPoint(IPAddress.Parse("66.228.45.110"), StunClient.DEFAULT_STUN_PORT), ProtocolType.Udp); StunMessage msg = new StunMessage(StunMethodType.Binding, StunMethodClass.Request, StunUtilities.NewTransactionId); msg.Stun.Realm = new UTF8Attribute(StunAttributeType.Realm, "Hello World !"); msg.Stun.Username = new UTF8Attribute(StunAttributeType.Username, "Bob"); byte[] octets = msg; StunMessage msgCopy = octets; // Reuse of an existing local IPEndPoint makes the three requests returning // the same MappedAddress IPEndPoint if this client is behind a Cone NAT StunClient cli1 = new StunClient(stunKeyValue.Key, new IPEndPoint(IPAddress.Parse("66.228.45.110"), StunClient.DEFAULT_STUNS_PORT), ProtocolType.Tcp, null, (sender, certificate, chain, sslPolicyErrors) => true); // Sample TLS over TCP working with ejabberd but may not work with the sample server IP given here cli1.Connect(); StunMessage resp1 = cli1.SendMessage(msgCopy); cli1.Disconnect(); msgCopy.ClearAttributes(); StunClient cli2 = new StunClient(stunKeyValue.Key, new IPEndPoint(IPAddress.Parse("132.177.123.13"), StunClient.DEFAULT_STUN_PORT), ProtocolType.Udp, null, null); cli2.Connect(); StunMessage resp2 = cli2.SendMessage(msgCopy); cli2.Disconnect(); }