Sfoglia il codice sorgente

Add more attributes

Bruce Wayne 5 anni fa
parent
commit
a009cf2f9e

+ 18 - 43
STUN/Message/Attributes/Attribute.cs → STUN/Message/Attribute.cs

@@ -1,10 +1,11 @@
-using STUN.Message.Enums;
+using STUN.Message.Attributes;
+using STUN.Message.Enums;
 using STUN.Utils;
 using System;
 using System.Collections.Generic;
 using System.Linq;
 
-namespace STUN.Message.Attributes
+namespace STUN.Message
 {
     /// <summary>
     /// https://tools.ietf.org/html/rfc5389#section-15
@@ -30,7 +31,6 @@ namespace STUN.Message.Attributes
 
         public IAttribute Value { get; set; }
 
-
         private byte[] _magicCookie;
         private byte[] _transactionId;
 
@@ -75,47 +75,22 @@ namespace STUN.Message.Attributes
 
             var value = bytes.Skip(4).Take(Length).ToArray();
 
-            IAttribute t;
-            switch (Type)
-            {
-                case AttributeType.MappedAddress:
-                {
-                    t = new MappedAddressAttribute();
-                    break;
-                }
-                case AttributeType.XorMappedAddress:
-                {
-                    t = new XorMappedAddressAttribute(_magicCookie, _transactionId);
-                    break;
-                }
-                case AttributeType.ResponseAddress:
-                {
-                    t = new ResponseAddressAttribute();
-                    break;
-                }
-                case AttributeType.ChangeRequest:
-                {
-                    t = new ChangeRequestAttribute();
-                    break;
-                }
-                case AttributeType.SourceAddress:
-                {
-                    t = new SourceAddressAttribute();
-                    break;
-                }
-                //TODO:Parse
-                default:
-                    return 0;
-            }
-
-            if (t.TryParse(value))
+            IAttribute t = Type switch
             {
-                Value = t;
-            }
-            else
-            {
-                return 0;
-            }
+                AttributeType.MappedAddress => new MappedAddressAttribute(),
+                AttributeType.XorMappedAddress => new XorMappedAddressAttribute(_magicCookie, _transactionId),
+                AttributeType.ResponseAddress => new ResponseAddressAttribute(),
+                AttributeType.ChangeRequest => new ChangeRequestAttribute(),
+                AttributeType.SourceAddress => new SourceAddressAttribute(),
+                AttributeType.ChangedAddress => new ChangedAddressAttribute(),
+                AttributeType.OtherAddress => new OtherAddressAttribute(),
+                AttributeType.ReflectedFrom => new ReflectedFromAttribute(),
+                AttributeType.ErrorCode => new ErrorCodeAttribute(),
+                _ => new UselessAttribute()
+            };
+
+            //TODO:Parse
+            Value = t.TryParse(value) ? t : null;
 
             return 4 + Length + (4 - Length % 4) % 4; // 对齐
         }

+ 7 - 0
STUN/Message/Attributes/ChangedAddressAttribute.cs

@@ -0,0 +1,7 @@
+namespace STUN.Message.Attributes
+{
+    /// <summary>
+    /// https://tools.ietf.org/html/rfc3489#section-11.2.3
+    /// </summary>
+    public class ChangedAddressAttribute : AddressAttribute { }
+}

+ 45 - 0
STUN/Message/Attributes/ErrorCodeAttribute.cs

@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace STUN.Message.Attributes
+{
+    /// <summary>
+    /// https://tools.ietf.org/html/rfc5389#section-15.6
+    /// </summary>
+    public class ErrorCodeAttribute : IAttribute
+    {
+        public IEnumerable<byte> Bytes
+        {
+            get
+            {
+                var res = new List<byte> { 0, 0, Class, Number };
+                res.AddRange(Encoding.UTF8.GetBytes(ReasonPhrase).Take(MaxReasonPhraseBytesLength));
+                return res;
+            }
+        }
+
+        public ushort ErrorCode { get; set; }
+        public string ReasonPhrase { get; set; }
+
+        public byte Class => (byte)(ErrorCode % 1000 / 100);
+        public byte Number => (byte)(ErrorCode % 100);
+
+        public const int MaxReasonPhraseBytesLength = 762;
+
+        public bool TryParse(byte[] bytes)
+        {
+            if (bytes.Length < 4 || bytes.Length > 4 + MaxReasonPhraseBytesLength) return false;
+
+            var @class = (byte)(bytes[2] & 0b111);
+            var number = Math.Min(bytes[3], (ushort)99);
+
+            ErrorCode = (ushort)(@class * 100 + number);
+
+            ReasonPhrase = bytes.Length > 4 ? Encoding.UTF8.GetString(bytes, 4, bytes.Length - 4) : string.Empty;
+
+            return true;
+        }
+    }
+}

+ 7 - 0
STUN/Message/Attributes/OtherAddressAttribute.cs

@@ -0,0 +1,7 @@
+namespace STUN.Message.Attributes
+{
+    /// <summary>
+    /// https://tools.ietf.org/html/rfc5780#section-7.4
+    /// </summary>
+    public class OtherAddressAttribute : AddressAttribute { }
+}

+ 7 - 0
STUN/Message/Attributes/ReflectedFromAttribute.cs

@@ -0,0 +1,7 @@
+namespace STUN.Message.Attributes
+{
+    /// <summary>
+    /// https://tools.ietf.org/html/rfc3489#section-11.2.11
+    /// </summary>
+    public class ReflectedFromAttribute : AddressAttribute { }
+}

+ 44 - 0
STUN/Message/Attributes/UnknownAttribute.cs

@@ -0,0 +1,44 @@
+using STUN.Message.Enums;
+using STUN.Utils;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace STUN.Message.Attributes
+{
+    /// <summary>
+    /// https://tools.ietf.org/html/rfc5389#section-15.9
+    /// </summary>
+    public class UnknownAttribute : IAttribute
+    {
+        public IEnumerable<byte> Bytes
+        {
+            get
+            {
+                var res = new List<byte>();
+                foreach (var type in Types)
+                {
+                    res.AddRange(Convert.ToUInt16(type).ToBe());
+                }
+                return res;
+            }
+        }
+
+        public IEnumerable<AttributeType> Types { get; set; }
+
+        public bool TryParse(byte[] bytes)
+        {
+            if (bytes.Length < 2 || (bytes.Length & 1) == 1) return false;
+
+            var list = new List<AttributeType>();
+            for (var i = 0; i < bytes.Length >> 1; ++i)
+            {
+                var b = bytes.Skip(i << 1).Take(2);
+                list.Add((AttributeType)BitUtils.FromBe(b));
+            }
+            Types = list;
+
+            return true;
+        }
+    }
+}

+ 20 - 0
STUN/Message/Attributes/UselessAttribute.cs

@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+
+namespace STUN.Message.Attributes
+{
+    /// <summary>
+    /// 无法理解的属性
+    /// </summary>
+    public class UselessAttribute : IAttribute
+    {
+        public IEnumerable<byte> Bytes => _bytes;
+
+        private byte[] _bytes;
+
+        public bool TryParse(byte[] bytes)
+        {
+            _bytes = bytes;
+            return _bytes != null;
+        }
+    }
+}

+ 5 - 0
STUN/Utils/BitUtils.cs

@@ -18,6 +18,11 @@ namespace STUN.Utils
             return BitConverter.ToUInt16(BitConverter.IsLittleEndian ? new[] { b2, b1 } : new[] { b1, b2 }, 0);
         }
 
+        public static ushort FromBe(IEnumerable<byte> b)
+        {
+            return BitConverter.ToUInt16(BitConverter.IsLittleEndian ? b.Reverse().ToArray() : b.ToArray(), 0);
+        }
+
         public static IEnumerable<byte> GetRandomBytes(int n)
         {
             var temp = new byte[n];