Bruce Wayne 5 年之前
父节点
当前提交
93295485c2
共有 2 个文件被更改,包括 362 次插入399 次删除
  1. 362 361
      STUN/Client/StunClient.cs
  2. 0 38
      STUN/Message/StunMessageType.cs

+ 362 - 361
STUN/Client/StunClient.cs

@@ -1,91 +1,92 @@
-using System;
+using STUN.Message;
+using STUN.Message.Enums;
+using STUN.Utils;
+using System;
 using System.IO;
 using System.Net;
 using System.Net.Sockets;
-using STUN.Message;
-using STUN.Utils;
 
 namespace STUN.Client
 {
-	/// <summary>
-	/// This class implements STUN client. Defined in RFC 3489.
-	/// </summary>
-	/// <example>
-	/// <code>
-	/// // Create new socket for STUN client.
-	/// Socket socket = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
-	/// socket.Bind(new IPEndPoint(IPAddress.Any,0));
-	/// 
-	/// // Query STUN server
-	/// STUN_Result result = STUN_Client.Query("stun.ekiga.net",3478,socket);
-	/// if(result.NetType != STUN_NetType.UdpBlocked){
-	///     // UDP blocked or !!!! bad STUN server
-	/// }
-	/// else{
-	///     IPEndPoint publicEP = result.PublicEndPoint;
-	///     // Do your stuff
-	/// }
-	/// </code>
-	/// </example>
-	public static class StunClient
-	{
-		#region static method Query
-
-		/// <summary>
-		/// Gets NAT info from STUN server.
-		/// </summary>
-		/// <param name="host">STUN server name or IP.</param>
-		/// <param name="port">STUN server port. Default port is 3478.</param>
-		/// <param name="localEP">Local IP end point.</param>
-		/// <returns>Returns UDP network info.</returns>
-		/// <exception cref="Exception">Is raised when <b>host</b> or <b>localEP</b> is null reference.</exception>
-		/// <exception cref="ArgumentNullException">Throws exception if unexpected error happens.</exception>
-		public static StunResult Query(string host, int port, IPEndPoint localEP)
-		{
-			if (host == null)
-			{
-				throw new ArgumentNullException(nameof(host));
-			}
-			if (localEP == null)
-			{
-				throw new ArgumentNullException(nameof(localEP));
-			}
-
-			using var s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
-			s.Bind(localEP);
-			return Query(host, port, s);
-		}
-
-		/// <summary>
-		/// Gets NAT info from STUN server.
-		/// </summary>
-		/// <param name="host">STUN server name or IP.</param>
-		/// <param name="port">STUN server port. Default port is 3478.</param>
-		/// <param name="socket">UDP socket to use.</param>
-		/// <returns>Returns UDP network info.</returns>
-		/// <exception cref="Exception">Throws exception if unexpected error happens.</exception>
-		public static StunResult Query(string host, int port, Socket socket)
-		{
-			if (host == null)
-			{
-				throw new ArgumentNullException(nameof(host));
-			}
-			if (socket == null)
-			{
-				throw new ArgumentNullException(nameof(socket));
-			}
-			if (port < 1)
-			{
-				throw new ArgumentException(@"Port value must be >= 1 !");
-			}
-			if (socket.ProtocolType != ProtocolType.Udp)
-			{
-				throw new ArgumentException(@"Socket must be UDP socket !");
-			}
-
-			var remoteEndPoint = new IPEndPoint(Dns.GetHostAddresses(host)[0], port);
-
-			/*
+    /// <summary>
+    /// This class implements STUN client. Defined in RFC 3489.
+    /// </summary>
+    /// <example>
+    /// <code>
+    /// // Create new socket for STUN client.
+    /// Socket socket = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
+    /// socket.Bind(new IPEndPoint(IPAddress.Any,0));
+    /// 
+    /// // Query STUN server
+    /// STUN_Result result = STUN_Client.Query("stun.ekiga.net",3478,socket);
+    /// if(result.NetType != STUN_NetType.UdpBlocked){
+    ///     // UDP blocked or !!!! bad STUN server
+    /// }
+    /// else{
+    ///     IPEndPoint publicEP = result.PublicEndPoint;
+    ///     // Do your stuff
+    /// }
+    /// </code>
+    /// </example>
+    public static class StunClient
+    {
+        #region static method Query
+
+        /// <summary>
+        /// Gets NAT info from STUN server.
+        /// </summary>
+        /// <param name="host">STUN server name or IP.</param>
+        /// <param name="port">STUN server port. Default port is 3478.</param>
+        /// <param name="localEP">Local IP end point.</param>
+        /// <returns>Returns UDP network info.</returns>
+        /// <exception cref="Exception">Is raised when <b>host</b> or <b>localEP</b> is null reference.</exception>
+        /// <exception cref="ArgumentNullException">Throws exception if unexpected error happens.</exception>
+        public static StunResult Query(string host, int port, IPEndPoint localEP)
+        {
+            if (host == null)
+            {
+                throw new ArgumentNullException(nameof(host));
+            }
+            if (localEP == null)
+            {
+                throw new ArgumentNullException(nameof(localEP));
+            }
+
+            using var s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+            s.Bind(localEP);
+            return Query(host, port, s);
+        }
+
+        /// <summary>
+        /// Gets NAT info from STUN server.
+        /// </summary>
+        /// <param name="host">STUN server name or IP.</param>
+        /// <param name="port">STUN server port. Default port is 3478.</param>
+        /// <param name="socket">UDP socket to use.</param>
+        /// <returns>Returns UDP network info.</returns>
+        /// <exception cref="Exception">Throws exception if unexpected error happens.</exception>
+        public static StunResult Query(string host, int port, Socket socket)
+        {
+            if (host == null)
+            {
+                throw new ArgumentNullException(nameof(host));
+            }
+            if (socket == null)
+            {
+                throw new ArgumentNullException(nameof(socket));
+            }
+            if (port < 1)
+            {
+                throw new ArgumentException(@"Port value must be >= 1 !");
+            }
+            if (socket.ProtocolType != ProtocolType.Udp)
+            {
+                throw new ArgumentException(@"Socket must be UDP socket !");
+            }
+
+            var remoteEndPoint = new IPEndPoint(Dns.GetHostAddresses(host)[0], port);
+
+            /*
                 In test I, the client sends a STUN Binding Request to a server, without any flags set in the
                 CHANGE-REQUEST attribute, and without the RESPONSE-ADDRESS attribute. This causes the server 
                 to send the response back to the address and port that the request came from.
@@ -140,287 +141,287 @@ namespace STUN.Client
 
             */
 
-			try
-			{
-				// Test I
-				var test1 = new StunMessage { Type = StunMessageType.BindingRequest };
-				var test1Response = DoTransaction(test1, socket, remoteEndPoint, 1600);
-
-				// UDP blocked.
-				if (test1Response == null)
-				{
-					return new StunResult(NatType.UdpBlocked, null);
-				}
-				else
-				{
-					// Test II
-					var test2 = new StunMessage
-					{
-						Type = StunMessageType.BindingRequest,
-						ChangeRequest = new StunChangeRequest(true, true)
-					};
-
-					// No NAT.
-					if (socket.LocalEndPoint.Equals(test1Response.MappedAddress))
-					{
-						var test2Response = DoTransaction(test2, socket, remoteEndPoint, 1600);
-						// Open Internet.
-						if (test2Response != null)
-						{
-							return new StunResult(NatType.OpenInternet, test1Response.MappedAddress);
-						}
-						// Symmetric UDP firewall.
-						else
-						{
-							return new StunResult(NatType.SymmetricUdpFirewall, test1Response.MappedAddress);
-						}
-					}
-					// NAT
-					else
-					{
-						var test2Response = DoTransaction(test2, socket, remoteEndPoint, 1600);
-
-						// Full cone NAT.
-						if (test2Response != null)
-						{
-							return new StunResult(NatType.FullCone, test1Response.MappedAddress);
-						}
-						else
-						{
-							/*
+            try
+            {
+                // Test I
+                var test1 = new StunMessage { Type = StunMessageType.BindingRequest };
+                var test1Response = DoTransaction(test1, socket, remoteEndPoint, 1600);
+
+                // UDP blocked.
+                if (test1Response == null)
+                {
+                    return new StunResult(NatType.UdpBlocked, null);
+                }
+                else
+                {
+                    // Test II
+                    var test2 = new StunMessage
+                    {
+                        Type = StunMessageType.BindingRequest,
+                        ChangeRequest = new StunChangeRequest(true, true)
+                    };
+
+                    // No NAT.
+                    if (socket.LocalEndPoint.Equals(test1Response.MappedAddress))
+                    {
+                        var test2Response = DoTransaction(test2, socket, remoteEndPoint, 1600);
+                        // Open Internet.
+                        if (test2Response != null)
+                        {
+                            return new StunResult(NatType.OpenInternet, test1Response.MappedAddress);
+                        }
+                        // Symmetric UDP firewall.
+                        else
+                        {
+                            return new StunResult(NatType.SymmetricUdpFirewall, test1Response.MappedAddress);
+                        }
+                    }
+                    // NAT
+                    else
+                    {
+                        var test2Response = DoTransaction(test2, socket, remoteEndPoint, 1600);
+
+                        // Full cone NAT.
+                        if (test2Response != null)
+                        {
+                            return new StunResult(NatType.FullCone, test1Response.MappedAddress);
+                        }
+                        else
+                        {
+                            /*
                                 If no response is received, it performs test I again, but this time, does so to 
                                 the address and port from the CHANGED-ADDRESS attribute from the response to test I.
                             */
 
-							// Test I(II)
-							var test12 = new StunMessage { Type = StunMessageType.BindingRequest };
-
-							var test12Response = DoTransaction(test12, socket, test1Response.ChangedAddress, 1600);
-							if (test12Response == null)
-							{
-								throw new Exception(@"STUN Test I(II) didn't get response !");
-							}
-							else
-							{
-								// Symmetric NAT
-								if (!test12Response.MappedAddress.Equals(test1Response.MappedAddress))
-								{
-									return new StunResult(NatType.Symmetric, test1Response.MappedAddress);
-								}
-								else
-								{
-									// Test III
-									var test3 = new StunMessage
-									{
-										Type = StunMessageType.BindingRequest,
-										ChangeRequest = new StunChangeRequest(false, true)
-									};
-
-									var test3Response = DoTransaction(test3, socket, test1Response.ChangedAddress, 1600);
-									// Restricted
-									if (test3Response != null)
-									{
-										return new StunResult(NatType.RestrictedCone, test1Response.MappedAddress);
-									}
-									// Port restricted
-									else
-									{
-										return new StunResult(NatType.PortRestrictedCone, test1Response.MappedAddress);
-									}
-								}
-							}
-						}
-					}
-				}
-			}
-			finally
-			{
-				// Junk all late responses.
-				var startTime = DateTime.Now;
-				while (startTime.AddMilliseconds(200) > DateTime.Now)
-				{
-					// We got response.
-					if (socket.Poll(1, SelectMode.SelectRead))
-					{
-						var receiveBuffer = new byte[512];
-						socket.Receive(receiveBuffer);
-					}
-				}
-			}
-		}
-
-		#endregion
-
-		#region method GetPublicIP
-
-		/// <summary>
-		/// Resolves local IP to public IP using STUN.
-		/// </summary>
-		/// <param name="stunServer">STUN server.</param>
-		/// <param name="port">STUN server port. Default port is 3478.</param>
-		/// <param name="localIP">Local IP address.</param>
-		/// <returns>Returns public IP address.</returns>
-		/// <exception cref="ArgumentNullException">Is raised when <b>stunServer</b> or <b>localIP</b> is null reference.</exception>
-		/// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
-		/// <exception cref="IOException">Is raised when no connection to STUN server.</exception>
-		public static IPAddress GetPublicIP(string stunServer, int port, IPAddress localIP)
-		{
-			if (stunServer == null)
-			{
-				throw new ArgumentNullException(nameof(stunServer));
-			}
-			if (stunServer == string.Empty)
-			{
-				throw new ArgumentException(@"Argument 'stunServer' value must be specified.");
-			}
-			if (port < 1)
-			{
-				throw new ArgumentException(@"Invalid argument 'port' value.");
-			}
-			if (localIP == null)
-			{
-				throw new ArgumentNullException(nameof(localIP));
-			}
-
-			if (!NetUtils.IsPrivateIP(localIP))
-			{
-				return localIP;
-			}
-
-			var result = Query(stunServer, port, NetUtils.CreateSocket(new IPEndPoint(localIP, 0), ProtocolType.Udp));
-			if (result.PublicEndPoint != null)
-			{
-				return result.PublicEndPoint.Address;
-			}
-
-			throw new IOException(@"Failed to STUN public IP address. STUN server name is invalid or firewall blocks STUN.");
-		}
-
-		#endregion
-
-		#region method GetPublicEP
-
-		/// <summary>
-		/// Resolves socket local end point to public end point.
-		/// </summary>
-		/// <param name="stunServer">STUN server.</param>
-		/// <param name="port">STUN server port. Default port is 3478.</param>
-		/// <param name="socket">UDP socket to use.</param>
-		/// <returns>Returns public IP end point.</returns>
-		/// <exception cref="ArgumentNullException">Is raised when <b>stunServer</b> or <b>socket</b> is null reference.</exception>
-		/// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
-		/// <exception cref="IOException">Is raised when no connection to STUN server.</exception>
-		public static IPEndPoint GetPublicEP(string stunServer, int port, Socket socket)
-		{
-			if (stunServer == null)
-			{
-				throw new ArgumentNullException(nameof(stunServer));
-			}
-			if (stunServer == string.Empty)
-			{
-				throw new ArgumentException(@"Argument 'stunServer' value must be specified.");
-			}
-			if (port < 1)
-			{
-				throw new ArgumentException(@"Invalid argument 'port' value.");
-			}
-			if (socket == null)
-			{
-				throw new ArgumentNullException(nameof(socket));
-			}
-			if (socket.ProtocolType != ProtocolType.Udp)
-			{
-				throw new ArgumentException(@"Socket must be UDP socket !");
-			}
-
-			var remoteEndPoint = new IPEndPoint(Dns.GetHostAddresses(stunServer)[0], port);
-
-			try
-			{
-				// Test I
-				var test1 = new StunMessage { Type = StunMessageType.BindingRequest };
-				var test1response = DoTransaction(test1, socket, remoteEndPoint, 1000);
-
-				// UDP blocked.
-				if (test1response == null)
-				{
-					throw new IOException(@"Failed to STUN public IP address. STUN server name is invalid or firewall blocks STUN.");
-				}
-
-				return test1response.SourceAddress;
-			}
-			catch
-			{
-				throw new IOException(@"Failed to STUN public IP address. STUN server name is invalid or firewall blocks STUN.");
-			}
-			finally
-			{
-				// Junk all late responses.
-				var startTime = DateTime.Now;
-				while (startTime.AddMilliseconds(200) > DateTime.Now)
-				{
-					// We got response.
-					if (socket.Poll(1, SelectMode.SelectRead))
-					{
-						var receiveBuffer = new byte[512];
-						socket.Receive(receiveBuffer);
-					}
-				}
-			}
-		}
-
-		#endregion
-
-		#region method DoTransaction
-
-		/// <summary>
-		/// Does STUN transaction. Returns transaction response or null if transaction failed.
-		/// </summary>
-		/// <param name="request">STUN message.</param>
-		/// <param name="socket">Socket to use for send/receive.</param>
-		/// <param name="remoteEndPoint">Remote end point.</param>
-		/// <param name="timeout">Timeout in milliseconds.</param>
-		/// <returns>Returns transaction response or null if transaction failed.</returns>
-		private static StunMessage DoTransaction(StunMessage request, Socket socket, IPEndPoint remoteEndPoint, int timeout)
-		{
-			var requestBytes = request.ToByteData();
-			var startTime = DateTime.Now;
-			// Retransmit with 500 ms.
-			while (startTime.AddMilliseconds(timeout) > DateTime.Now)
-			{
-				try
-				{
-					socket.SendTo(requestBytes, remoteEndPoint);
-
-					// We got response.
-					if (socket.Poll(500 * 1000, SelectMode.SelectRead))
-					{
-						var receiveBuffer = new byte[512];
-						socket.Receive(receiveBuffer);
-
-						// Parse message
-						var response = new StunMessage();
-						response.Parse(receiveBuffer);
-
-						// Check that transaction ID matches or not response what we want.
-						if (NetUtils.CompareArray(request.TransactionId, response.TransactionId))
-						{
-							return response;
-						}
-					}
-				}
-				catch
-				{
-					// ignored
-				}
-			}
-
-			return null;
-		}
-
-		#endregion
-
-		// TODO: Update to RFC 5389
-
-	}
+                            // Test I(II)
+                            var test12 = new StunMessage { Type = StunMessageType.BindingRequest };
+
+                            var test12Response = DoTransaction(test12, socket, test1Response.ChangedAddress, 1600);
+                            if (test12Response == null)
+                            {
+                                throw new Exception(@"STUN Test I(II) didn't get response !");
+                            }
+                            else
+                            {
+                                // Symmetric NAT
+                                if (!test12Response.MappedAddress.Equals(test1Response.MappedAddress))
+                                {
+                                    return new StunResult(NatType.Symmetric, test1Response.MappedAddress);
+                                }
+                                else
+                                {
+                                    // Test III
+                                    var test3 = new StunMessage
+                                    {
+                                        Type = StunMessageType.BindingRequest,
+                                        ChangeRequest = new StunChangeRequest(false, true)
+                                    };
+
+                                    var test3Response = DoTransaction(test3, socket, test1Response.ChangedAddress, 1600);
+                                    // Restricted
+                                    if (test3Response != null)
+                                    {
+                                        return new StunResult(NatType.RestrictedCone, test1Response.MappedAddress);
+                                    }
+                                    // Port restricted
+                                    else
+                                    {
+                                        return new StunResult(NatType.PortRestrictedCone, test1Response.MappedAddress);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            finally
+            {
+                // Junk all late responses.
+                var startTime = DateTime.Now;
+                while (startTime.AddMilliseconds(200) > DateTime.Now)
+                {
+                    // We got response.
+                    if (socket.Poll(1, SelectMode.SelectRead))
+                    {
+                        var receiveBuffer = new byte[512];
+                        socket.Receive(receiveBuffer);
+                    }
+                }
+            }
+        }
+
+        #endregion
+
+        #region method GetPublicIP
+
+        /// <summary>
+        /// Resolves local IP to public IP using STUN.
+        /// </summary>
+        /// <param name="stunServer">STUN server.</param>
+        /// <param name="port">STUN server port. Default port is 3478.</param>
+        /// <param name="localIP">Local IP address.</param>
+        /// <returns>Returns public IP address.</returns>
+        /// <exception cref="ArgumentNullException">Is raised when <b>stunServer</b> or <b>localIP</b> is null reference.</exception>
+        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
+        /// <exception cref="IOException">Is raised when no connection to STUN server.</exception>
+        public static IPAddress GetPublicIP(string stunServer, int port, IPAddress localIP)
+        {
+            if (stunServer == null)
+            {
+                throw new ArgumentNullException(nameof(stunServer));
+            }
+            if (stunServer == string.Empty)
+            {
+                throw new ArgumentException(@"Argument 'stunServer' value must be specified.");
+            }
+            if (port < 1)
+            {
+                throw new ArgumentException(@"Invalid argument 'port' value.");
+            }
+            if (localIP == null)
+            {
+                throw new ArgumentNullException(nameof(localIP));
+            }
+
+            if (!NetUtils.IsPrivateIP(localIP))
+            {
+                return localIP;
+            }
+
+            var result = Query(stunServer, port, NetUtils.CreateSocket(new IPEndPoint(localIP, 0), ProtocolType.Udp));
+            if (result.PublicEndPoint != null)
+            {
+                return result.PublicEndPoint.Address;
+            }
+
+            throw new IOException(@"Failed to STUN public IP address. STUN server name is invalid or firewall blocks STUN.");
+        }
+
+        #endregion
+
+        #region method GetPublicEP
+
+        /// <summary>
+        /// Resolves socket local end point to public end point.
+        /// </summary>
+        /// <param name="stunServer">STUN server.</param>
+        /// <param name="port">STUN server port. Default port is 3478.</param>
+        /// <param name="socket">UDP socket to use.</param>
+        /// <returns>Returns public IP end point.</returns>
+        /// <exception cref="ArgumentNullException">Is raised when <b>stunServer</b> or <b>socket</b> is null reference.</exception>
+        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
+        /// <exception cref="IOException">Is raised when no connection to STUN server.</exception>
+        public static IPEndPoint GetPublicEP(string stunServer, int port, Socket socket)
+        {
+            if (stunServer == null)
+            {
+                throw new ArgumentNullException(nameof(stunServer));
+            }
+            if (stunServer == string.Empty)
+            {
+                throw new ArgumentException(@"Argument 'stunServer' value must be specified.");
+            }
+            if (port < 1)
+            {
+                throw new ArgumentException(@"Invalid argument 'port' value.");
+            }
+            if (socket == null)
+            {
+                throw new ArgumentNullException(nameof(socket));
+            }
+            if (socket.ProtocolType != ProtocolType.Udp)
+            {
+                throw new ArgumentException(@"Socket must be UDP socket !");
+            }
+
+            var remoteEndPoint = new IPEndPoint(Dns.GetHostAddresses(stunServer)[0], port);
+
+            try
+            {
+                // Test I
+                var test1 = new StunMessage { Type = StunMessageType.BindingRequest };
+                var test1response = DoTransaction(test1, socket, remoteEndPoint, 1000);
+
+                // UDP blocked.
+                if (test1response == null)
+                {
+                    throw new IOException(@"Failed to STUN public IP address. STUN server name is invalid or firewall blocks STUN.");
+                }
+
+                return test1response.SourceAddress;
+            }
+            catch
+            {
+                throw new IOException(@"Failed to STUN public IP address. STUN server name is invalid or firewall blocks STUN.");
+            }
+            finally
+            {
+                // Junk all late responses.
+                var startTime = DateTime.Now;
+                while (startTime.AddMilliseconds(200) > DateTime.Now)
+                {
+                    // We got response.
+                    if (socket.Poll(1, SelectMode.SelectRead))
+                    {
+                        var receiveBuffer = new byte[512];
+                        socket.Receive(receiveBuffer);
+                    }
+                }
+            }
+        }
+
+        #endregion
+
+        #region method DoTransaction
+
+        /// <summary>
+        /// Does STUN transaction. Returns transaction response or null if transaction failed.
+        /// </summary>
+        /// <param name="request">STUN message.</param>
+        /// <param name="socket">Socket to use for send/receive.</param>
+        /// <param name="remoteEndPoint">Remote end point.</param>
+        /// <param name="timeout">Timeout in milliseconds.</param>
+        /// <returns>Returns transaction response or null if transaction failed.</returns>
+        private static StunMessage DoTransaction(StunMessage request, Socket socket, IPEndPoint remoteEndPoint, int timeout)
+        {
+            var requestBytes = request.ToByteData();
+            var startTime = DateTime.Now;
+            // Retransmit with 500 ms.
+            while (startTime.AddMilliseconds(timeout) > DateTime.Now)
+            {
+                try
+                {
+                    socket.SendTo(requestBytes, remoteEndPoint);
+
+                    // We got response.
+                    if (socket.Poll(500 * 1000, SelectMode.SelectRead))
+                    {
+                        var receiveBuffer = new byte[512];
+                        socket.Receive(receiveBuffer);
+
+                        // Parse message
+                        var response = new StunMessage();
+                        response.Parse(receiveBuffer);
+
+                        // Check that transaction ID matches or not response what we want.
+                        if (NetUtils.CompareArray(request.TransactionId, response.TransactionId))
+                        {
+                            return response;
+                        }
+                    }
+                }
+                catch
+                {
+                    // ignored
+                }
+            }
+
+            return null;
+        }
+
+        #endregion
+
+        // TODO: Update to RFC 5389
+
+    }
 }

+ 0 - 38
STUN/Message/StunMessageType.cs

@@ -1,38 +0,0 @@
-namespace STUN.Message
-{
-	/// <summary>
-	/// This enum specifies STUN message type.
-	/// </summary>
-	public enum StunMessageType
-	{
-		/// <summary>
-		/// STUN message is binding request.
-		/// </summary>
-		BindingRequest = 0x0001,
-
-		/// <summary>
-		/// STUN message is binding request response.
-		/// </summary>
-		BindingResponse = 0x0101,
-
-		/// <summary>
-		/// STUN message is binding request error response.
-		/// </summary>
-		BindingErrorResponse = 0x0111,
-
-		/// <summary>
-		/// STUN message is "shared secret" request.
-		/// </summary>
-		SharedSecretRequest = 0x0002,
-
-		/// <summary>
-		/// STUN message is "shared secret" request response.
-		/// </summary>
-		SharedSecretResponse = 0x0102,
-
-		/// <summary>
-		/// STUN message is "shared secret" request error response.
-		/// </summary>
-		SharedSecretErrorResponse = 0x0112
-	}
-}