From a99134c8107169ac0b625a656eae179e4a168bc1 Mon Sep 17 00:00:00 2001 From: NZSmartie Date: Thu, 30 Nov 2017 09:09:59 +1300 Subject: [PATCH] Make OptionFactory a object --- src/CoAPNet/CoapMessage.cs | 103 +++++--------------------- src/CoAPNet/Options/Factory.cs | 74 ------------------- src/CoAPNet/Options/OptionFactory.cs | 104 +++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 161 deletions(-) delete mode 100644 src/CoAPNet/Options/Factory.cs create mode 100644 src/CoAPNet/Options/OptionFactory.cs diff --git a/src/CoAPNet/CoapMessage.cs b/src/CoAPNet/CoapMessage.cs index 3317784..099deb2 100644 --- a/src/CoAPNet/CoapMessage.cs +++ b/src/CoAPNet/CoapMessage.cs @@ -39,92 +39,9 @@ public enum CoapMessageType public enum CoapMessageCodeClass { Request = 0, - Success = 200, - ClientError = 400, - ServerError = 500 - } - - /// - /// Response Codes - /// See section 5.9 of [RFC7252] and section 12.1 of [RFC7252] - /// - public enum CoapMessageCode - { - /// - /// Placeholder and will throw when used. - /// - None = 0, - // 0.xx Request - /// - /// GET request from a client to a server used for retreiving resources - /// - Get = 1, - /// - /// Post request from a client to a server used for creating or updating resources - /// - Post = 2, - /// - /// Put request from a client to a server used for updating resources - /// - Put = 3, - /// - /// DELETE request from a client to a server used to delete resources - /// - Delete = 4, - // 2.xx Success - Created = 201, - Deleted = 202, - Valid = 203, - Changed = 204, - Content = 205, - // 4.xx Client Error - BadRequest = 400, - Unauthorized = 401, - BadOption = 402, - Forbidden = 403, - NotFound = 404, - MethodNotAllowed = 405, - NotAcceptable = 406, - PreconditionFailed = 412, - RequestEntityTooLarge = 413, - UnsupportedContentFormat = 415, - // 5.xx Server Error - InternalServerError = 500, - NotImplemented = 501, - BadGateway = 502, - ServiceUnavailable = 503, - GatewayTimeout = 504, - ProxyingNotSupported = 505 - } - - /// - /// Extension methods for quickly deciding which logic to apply to CoAP messages. - /// - public static class CoapMessageCodeExtensions - { - /// - /// indicates if the CoAP message is a Request from a client. - /// - public static bool IsRequest(this CoapMessageCode code) - => ((int) code / 100) == 0 && code != CoapMessageCode.None; - - /// - /// indicates if the CoAP message is a successful response from a server. - /// - public static bool IsSuccess(this CoapMessageCode code) - => ((int)code / 100) == 2; - - /// - /// indicates if the CoAP message is a error due to a client's request. - /// - public static bool IsClientError(this CoapMessageCode code) - => ((int)code / 100) == 4; - - /// - /// indicates if the CoAP message is a error due to internal server issues. - /// - public static bool IsServerError(this CoapMessageCode code) - => ((int)code / 100) == 5; + Success = 2, + ClientError = 4, + ServerError = 5 } /// @@ -209,6 +126,7 @@ public byte[] Token public int Id { get; set; } private List _options = new List(); + /// /// Gets or sets the list of options to be encoded into the message header. The order of these options are Critical and spcial care is needed when adding new items. /// Todo: Sort items based on and preserve options with identical Optionnumbers @@ -224,6 +142,17 @@ public List Options } } + private OptionFactory _optionFactory; + + /// + /// Gets or Sets the OptionFactory used when decoding options in a CoAP message header + /// + public OptionFactory OptionFactory + { + get => _optionFactory ?? (_optionFactory = OptionFactory.Default); + set => _optionFactory = value; + } + /// /// Gets or Sets The paylaod of the message. /// @@ -411,7 +340,7 @@ public void Deserialise(byte[] data) try { - var option = CoAPNet.Options.Factory.Create(optCode + optionDelta, + var option = OptionFactory.Create(optCode + optionDelta, data.Skip(i + 1).Take(dataLen).ToArray()); if (option != null) Options.Add(option); diff --git a/src/CoAPNet/Options/Factory.cs b/src/CoAPNet/Options/Factory.cs deleted file mode 100644 index ab68123..0000000 --- a/src/CoAPNet/Options/Factory.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Reflection; -using System.Collections.Generic; - -namespace CoAPNet.Options -{ - public static class Factory - { - static Dictionary _options = new Dictionary(); - - static Factory() - { - Register(); - Register(); - Register(); - Register(); - - Register(); - Register(); - - Register(); - Register(); - - Register(); - Register(); - Register(); - Register(); - Register(); - - Register(); - Register(); - } - - public static void Register() where T : CoapOption - { - Type type = typeof(T); - Register(type); - } - - public static void Register(Type type) - { - if(!type.GetTypeInfo().IsSubclassOf(typeof(CoapOption))) - throw new ArgumentException($"Type must be a subclass of {nameof(CoapOption)}"); - - var option = (CoapOption)Activator.CreateInstance(type); - _options.Add(option.OptionNumber, type); - } - - /// - /// Try to create an from the option number and data. - /// - /// - /// - /// null if the option is unsupported. - /// If the option number is unsuppported and is critical (See RFC 7252 Section 5.4.1) - public static CoapOption Create(int number, byte[] data = null) - { - // Let the exception get thrown if index is out of range - Type type = null; - if (!_options.TryGetValue(number, out type)) - { - if (number % 2 == 1) - throw new CoapOptionException($"Unsupported critical option ({number})", new ArgumentOutOfRangeException(nameof(number))); - return null; - } - - var option = (CoapOption)Activator.CreateInstance(type); - if (data != null) - option.FromBytes(data); - - return option; - } - } -} diff --git a/src/CoAPNet/Options/OptionFactory.cs b/src/CoAPNet/Options/OptionFactory.cs new file mode 100644 index 0000000..709dbc5 --- /dev/null +++ b/src/CoAPNet/Options/OptionFactory.cs @@ -0,0 +1,104 @@ +using System; +using System.Reflection; +using System.Collections.Generic; + +namespace CoAPNet.Options +{ + public class OptionFactory + { + private Dictionary _options = new Dictionary(); + + private static OptionFactory _instance; + + /// + /// A with all the supported options registered. + /// + public static OptionFactory Default => _instance ?? (_instance = new OptionFactory()); + + /// + /// Creates a new Options Factory with all the suported options registered. + /// + public OptionFactory() + { + Register(); + Register(); + Register(); + Register(); + + Register(); + Register(); + + Register(); + Register(); + + Register(); + Register(); + Register(); + Register(); + Register(); + + Register(); + Register(); + } + + /// + /// Creates a new Options Factory with all the suported options registered and registers addional . + /// + /// + public OptionFactory(params Type[] addtionalOptions) + : this() + { + Register(addtionalOptions); + } + + /// + /// Register an additional + /// + /// Must subclass + public void Register() where T : CoapOption + { + Register(typeof(T)); + } + + /// + /// Regisrers additional s + /// + /// + public void Register(params Type[] addtionalOptions) + { + foreach (var type in addtionalOptions) + { + if (!type.GetTypeInfo().IsSubclassOf(typeof(CoapOption))) + throw new ArgumentException($"Type must be a subclass of {nameof(CoapOption)}"); + + var option = (CoapOption)Activator.CreateInstance(type); + _options.Add(option.OptionNumber, type); + } + } + + /// + /// Try to create an from the option number and data. + /// + /// + /// + /// null if the option is unsupported. + /// If the option number is unsuppported and is critical (See RFC 7252 Section 5.4.1) + public CoapOption Create(int number, byte[] data = null) + { + // Let the exception get thrown if index is out of range + Type type = null; + if (!_options.TryGetValue(number, out type)) + { + if (number % 2 == 1) + throw new CoapOptionException($"Unsupported critical option ({number})", new ArgumentOutOfRangeException(nameof(number))); + return null; + } + + var option = (CoapOption)Activator.CreateInstance(type); + if (data != null) + option.FromBytes(data); + + return option; + } + } +}