Compare commits

..
16 Commits
Author SHA1 Message Date
BlubbFish 0c4e2d17cc add DataMatrix GPSDLib ImageSharp StreamDeckSharp TelegramBot and updated mqtt, litjson and coordinates 2026-08-03 23:09:16 +02:00
BlubbFish 0287850d13 update libs 2021-04-10 19:01:29 +02:00
BlubbFish f9f9ff5129 added Coordinates 2021-03-24 20:37:30 +01:00
BlubbFish daaeca5bf2 „update.sh“ ändern 2020-09-16 16:24:25 +02:00
BlubbFish c6d02a0a71 Update update.sh 2020-06-15 16:52:11 +02:00
BlubbFish edae4170e3 Add RaspberryIO_26 2019-12-04 20:01:44 +01:00
BlubbFish 40b5328739 Update dependencies 2019-05-30 15:04:59 +02:00
BlubbFish e73ef2504c add update.sh 2019-03-29 17:42:41 +01:00
BlubbFish 831c3dfc54 Update litjson 2019-03-08 10:41:22 +01:00
BlubbFish 491ed23867 add Mono.Posix 2019-02-17 15:53:29 +01:00
BlubbFish 6e68241722 add RaspberryIO Library 2019-02-17 14:25:35 +01:00
BlubbFish 82755ce75d update modules 2019-02-15 16:28:58 +01:00
BlubbFish 1d66da260b Added in submodules for removed folders 2019-02-15 13:00:47 +01:00
BlubbFish 48eb1a6974 Removing the folders that are now repositories 2019-02-15 13:00:09 +01:00
BlubbFish 3cda8ca417 Added in submodules for removed folders 2019-02-15 12:59:51 +01:00
BlubbFish a103b9f491 Removing the folders that are now repositories 2019-02-15 12:58:54 +01:00
76 changed files with 83 additions and 12226 deletions
+33
View File
@@ -0,0 +1,33 @@
[submodule "litjson"]
path = litjson
url = http://git.blubbfish.net/vs_librarys/litjson.git
[submodule "mqtt"]
path = mqtt
url = http://git.blubbfish.net/vs_librarys/mqtt.git
[submodule "RaspberryIO"]
path = RaspberryIO
url = http://git.blubbfish.net/vs_librarys/RaspberryIO.git
[submodule "Mono.Posix"]
path = Mono.Posix
url = http://git.blubbfish.net/vs_librarys/Mono.Posix.git
[submodule "RaspberryIO_26"]
path = RaspberryIO_26
url = http://git.blubbfish.net/vs_librarys/RaspberryIO_26.git
[submodule "Coordinates"]
path = Coordinates
url = https://git.blubbfish.net/vs_librarys/Coordinates.git
[submodule "DataMatrix.net"]
path = DataMatrix.net
url = https://git.blubbfish.net/vs_librarys/DataMatrix.net.git
[submodule "GPSDLib"]
path = GPSDLib
url = https://git.blubbfish.net/vs_librarys/GPSDLib.git
[submodule "ImageSharp"]
path = ImageSharp
url = https://git.blubbfish.net/vs_librarys/ImageSharp.git
[submodule "StreamDeckSharp"]
path = StreamDeckSharp
url = https://git.blubbfish.net/vs_librarys/StreamDeckSharp.git
[submodule "TelegramBot"]
path = TelegramBot
url = https://git.blubbfish.net/vs_librarys/TelegramBot.git
Submodule
+1
Submodule Coordinates added at 86f0509c9a
+1
Submodule DataMatrix.net added at ed37b7ba01
Submodule
+1
Submodule GPSDLib added at 0ff9e48e2e
Submodule
+1
Submodule ImageSharp added at 7e8cddf208
Submodule
+1
Submodule Mono.Posix added at 2f0ae844d0
Submodule
+1
Submodule RaspberryIO added at 2f74732924
+1
Submodule RaspberryIO_26 added at 97ca122560
+1
Submodule StreamDeckSharp added at 308ba282fb
Submodule
+1
Submodule TelegramBot added at 17393a47d3
Submodule
+1
Submodule litjson added at 63561dc90d
-25
View File
@@ -1,25 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2010
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "litjson_4.7.1", "litjson\litjson_4.7.1.csproj", "{91A14CD2-2940-4500-8193-56D37EDDDBAA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{91A14CD2-2940-4500-8193-56D37EDDDBAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{91A14CD2-2940-4500-8193-56D37EDDDBAA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{91A14CD2-2940-4500-8193-56D37EDDDBAA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{91A14CD2-2940-4500-8193-56D37EDDDBAA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AF2398AC-1EAA-4615-B21A-33C68CD44849}
EndGlobalSection
EndGlobal
-60
View File
@@ -1,60 +0,0 @@
#region Header
/**
* IJsonWrapper.cs
* Interface that represents a type capable of handling all kinds of JSON
* data. This is mainly used when mapping objects through JsonMapper, and
* it's implemented by JsonData.
*
* The authors disclaim copyright to this source code. For more details, see
* the COPYING file included with this distribution.
**/
#endregion
using System.Collections;
using System.Collections.Specialized;
namespace LitJson
{
public enum JsonType
{
None,
Object,
Array,
String,
Int,
Long,
Double,
Boolean
}
public interface IJsonWrapper : IList, IOrderedDictionary
{
bool IsArray { get; }
bool IsBoolean { get; }
bool IsDouble { get; }
bool IsInt { get; }
bool IsLong { get; }
bool IsObject { get; }
bool IsString { get; }
bool GetBoolean ();
double GetDouble ();
int GetInt ();
JsonType GetJsonType ();
long GetLong ();
string GetString ();
void SetBoolean (bool val);
void SetDouble (double val);
void SetInt (int val);
void SetJsonType (JsonType type);
void SetLong (long val);
void SetString (string val);
string ToJson ();
void ToJson (JsonWriter writer);
}
}
File diff suppressed because it is too large Load Diff
-65
View File
@@ -1,65 +0,0 @@
#region Header
/**
* JsonException.cs
* Base class throwed by LitJSON when a parsing error occurs.
*
* The authors disclaim copyright to this source code. For more details, see
* the COPYING file included with this distribution.
**/
#endregion
using System;
namespace LitJson
{
public class JsonException :
#if NETSTANDARD1_5
Exception
#else
ApplicationException
#endif
{
public JsonException () : base ()
{
}
internal JsonException (ParserToken token) :
base (String.Format (
"Invalid token '{0}' in input string", token))
{
}
internal JsonException (ParserToken token,
Exception inner_exception) :
base (String.Format (
"Invalid token '{0}' in input string", token),
inner_exception)
{
}
internal JsonException (int c) :
base (String.Format (
"Invalid character '{0}' in input string", (char) c))
{
}
internal JsonException (int c, Exception inner_exception) :
base (String.Format (
"Invalid character '{0}' in input string", (char) c),
inner_exception)
{
}
public JsonException (string message) : base (message)
{
}
public JsonException (string message, Exception inner_exception) :
base (message, inner_exception)
{
}
}
}
-857
View File
@@ -1,857 +0,0 @@
#region Header
/**
* JsonMapper.cs
* JSON to .Net object and object to JSON conversions.
*
* The authors disclaim copyright to this source code. For more details, see
* the COPYING file included with this distribution.
**/
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
namespace LitJson {
internal struct PropertyMetadata {
public MemberInfo Info;
public Boolean IsField;
public Type Type;
}
internal struct ArrayMetadata {
private Type element_type;
public Type ElementType {
get {
if (this.element_type == null) {
return typeof(JsonData);
}
return this.element_type;
}
set { this.element_type = value; }
}
public Boolean IsArray { get; set; }
public Boolean IsList { get; set; }
}
internal struct ObjectMetadata {
private Type element_type;
public Type ElementType {
get {
if (this.element_type == null) {
return typeof(JsonData);
}
return this.element_type;
}
set { this.element_type = value; }
}
public Boolean IsDictionary { get; set; }
public IDictionary<String, PropertyMetadata> Properties { get; set; }
}
internal delegate void ExporterFunc(Object obj, JsonWriter writer);
public delegate void ExporterFunc<T>(T obj, JsonWriter writer);
internal delegate Object ImporterFunc(Object input);
public delegate TValue ImporterFunc<TJson, TValue>(TJson input);
public delegate IJsonWrapper WrapperFactory();
public class JsonMapper {
#region Fields
private static readonly Int32 max_nesting_depth;
private static readonly IFormatProvider datetime_format;
private static readonly IDictionary<Type, ExporterFunc> base_exporters_table;
private static readonly IDictionary<Type, ExporterFunc> custom_exporters_table;
private static readonly IDictionary<Type, IDictionary<Type, ImporterFunc>> base_importers_table;
private static readonly IDictionary<Type, IDictionary<Type, ImporterFunc>> custom_importers_table;
private static readonly IDictionary<Type, ArrayMetadata> array_metadata;
private static readonly Object array_metadata_lock = new Object();
private static readonly IDictionary<Type, IDictionary<Type, MethodInfo>> conv_ops;
private static readonly Object conv_ops_lock = new Object();
private static readonly IDictionary<Type, ObjectMetadata> object_metadata;
private static readonly Object object_metadata_lock = new Object();
private static readonly IDictionary<Type, IList<PropertyMetadata>> type_properties;
private static readonly Object type_properties_lock = new Object();
private static readonly JsonWriter static_writer;
private static readonly Object static_writer_lock = new Object();
#endregion
#region Constructors
static JsonMapper() {
max_nesting_depth = 100;
array_metadata = new Dictionary<Type, ArrayMetadata>();
conv_ops = new Dictionary<Type, IDictionary<Type, MethodInfo>>();
object_metadata = new Dictionary<Type, ObjectMetadata>();
type_properties = new Dictionary<Type, IList<PropertyMetadata>>();
static_writer = new JsonWriter();
datetime_format = DateTimeFormatInfo.InvariantInfo;
base_exporters_table = new Dictionary<Type, ExporterFunc>();
custom_exporters_table = new Dictionary<Type, ExporterFunc>();
base_importers_table = new Dictionary<Type, IDictionary<Type, ImporterFunc>>();
custom_importers_table = new Dictionary<Type, IDictionary<Type, ImporterFunc>>();
RegisterBaseExporters();
RegisterBaseImporters();
}
#endregion
#region Private Methods
private static void AddArrayMetadata(Type type) {
if (array_metadata.ContainsKey(type)) {
return;
}
ArrayMetadata data = new ArrayMetadata {
IsArray = type.IsArray
};
if (type.GetInterface("System.Collections.IList") != null) {
data.IsList = true;
}
foreach (PropertyInfo p_info in type.GetProperties()) {
if (p_info.Name != "Item") {
continue;
}
ParameterInfo[] parameters = p_info.GetIndexParameters();
if (parameters.Length != 1) {
continue;
}
if (parameters[0].ParameterType == typeof(Int32)) {
data.ElementType = p_info.PropertyType;
}
}
lock (array_metadata_lock) {
try {
array_metadata.Add(type, data);
} catch (ArgumentException) {
return;
}
}
}
private static void AddObjectMetadata(Type type) {
if (object_metadata.ContainsKey(type)) {
return;
}
ObjectMetadata data = new ObjectMetadata();
if (type.GetInterface("System.Collections.IDictionary") != null) {
data.IsDictionary = true;
}
data.Properties = new Dictionary<String, PropertyMetadata>();
foreach (PropertyInfo p_info in type.GetProperties()) {
if (p_info.Name == "Item") {
ParameterInfo[] parameters = p_info.GetIndexParameters();
if (parameters.Length != 1) {
continue;
}
if (parameters[0].ParameterType == typeof(String)) {
data.ElementType = p_info.PropertyType;
}
continue;
}
PropertyMetadata p_data = new PropertyMetadata {
Info = p_info,
Type = p_info.PropertyType
};
data.Properties.Add(p_info.Name, p_data);
}
foreach (FieldInfo f_info in type.GetFields()) {
PropertyMetadata p_data = new PropertyMetadata {
Info = f_info,
IsField = true,
Type = f_info.FieldType
};
data.Properties.Add(f_info.Name, p_data);
}
lock (object_metadata_lock) {
try {
object_metadata.Add(type, data);
} catch (ArgumentException) {
return;
}
}
}
private static void AddTypeProperties(Type type) {
if (type_properties.ContainsKey(type)) {
return;
}
IList<PropertyMetadata> props = new List<PropertyMetadata>();
foreach (PropertyInfo p_info in type.GetProperties()) {
if (p_info.Name == "Item") {
continue;
}
PropertyMetadata p_data = new PropertyMetadata {
Info = p_info,
IsField = false
};
props.Add(p_data);
}
foreach (FieldInfo f_info in type.GetFields()) {
PropertyMetadata p_data = new PropertyMetadata {
Info = f_info,
IsField = true
};
props.Add(p_data);
}
lock (type_properties_lock) {
try {
type_properties.Add(type, props);
} catch (ArgumentException) {
return;
}
}
}
private static MethodInfo GetConvOp(Type t1, Type t2) {
lock (conv_ops_lock) {
if (!conv_ops.ContainsKey(t1)) {
conv_ops.Add(t1, new Dictionary<Type, MethodInfo>());
}
}
if (conv_ops[t1].ContainsKey(t2)) {
return conv_ops[t1][t2];
}
MethodInfo op = t1.GetMethod("op_Implicit", new Type[] { t2 });
lock (conv_ops_lock) {
try {
conv_ops[t1].Add(t2, op);
} catch (ArgumentException) {
return conv_ops[t1][t2];
}
}
return op;
}
private static Object ReadValue(Type inst_type, JsonReader reader) {
reader.Read();
if (reader.Token == JsonToken.ArrayEnd) {
return null;
}
Type underlying_type = Nullable.GetUnderlyingType(inst_type);
Type value_type = underlying_type ?? inst_type;
if (reader.Token == JsonToken.Null) {
#if NETSTANDARD1_5
if (inst_type.IsClass() || underlying_type != null) {
return null;
}
#else
if (inst_type.IsClass || underlying_type != null) {
return null;
}
#endif
throw new JsonException(String.Format("Can't assign null to an instance of type {0}", inst_type));
}
if (reader.Token == JsonToken.Double ||
reader.Token == JsonToken.Int ||
reader.Token == JsonToken.Long ||
reader.Token == JsonToken.String ||
reader.Token == JsonToken.Boolean) {
Type json_type = reader.Value.GetType();
if (value_type.IsAssignableFrom(json_type)) {
return reader.Value;
}
// If there's a custom importer that fits, use it
if (custom_importers_table.ContainsKey(json_type) &&
custom_importers_table[json_type].ContainsKey(
value_type)) {
ImporterFunc importer =
custom_importers_table[json_type][value_type];
return importer(reader.Value);
}
// Maybe there's a base importer that works
if (base_importers_table.ContainsKey(json_type) &&
base_importers_table[json_type].ContainsKey(
value_type)) {
ImporterFunc importer =
base_importers_table[json_type][value_type];
return importer(reader.Value);
}
// Maybe it's an enum
#if NETSTANDARD1_5
if (value_type.IsEnum())
return Enum.ToObject (value_type, reader.Value);
#else
if (value_type.IsEnum) {
return Enum.ToObject(value_type, reader.Value);
}
#endif
// Try using an implicit conversion operator
MethodInfo conv_op = GetConvOp(value_type, json_type);
if (conv_op != null) {
return conv_op.Invoke(null, new Object[] { reader.Value });
}
// No luck
throw new JsonException(String.Format("Can't assign value '{0}' (type {1}) to type {2}", reader.Value, json_type, inst_type));
}
Object instance = null;
if (reader.Token == JsonToken.ArrayStart) {
AddArrayMetadata(inst_type);
ArrayMetadata t_data = array_metadata[inst_type];
if (!t_data.IsArray && !t_data.IsList) {
throw new JsonException(String.Format("Type {0} can't act as an array", inst_type));
}
IList list;
Type elem_type;
if (!t_data.IsArray) {
list = (IList)Activator.CreateInstance(inst_type);
elem_type = t_data.ElementType;
} else {
list = new ArrayList();
elem_type = inst_type.GetElementType();
}
while (true) {
Object item = ReadValue(elem_type, reader);
if (item == null && reader.Token == JsonToken.ArrayEnd) {
break;
}
list.Add(item);
}
if (t_data.IsArray) {
Int32 n = list.Count;
instance = Array.CreateInstance(elem_type, n);
for (Int32 i = 0; i < n; i++) {
((Array)instance).SetValue(list[i], i);
}
} else {
instance = list;
}
} else if (reader.Token == JsonToken.ObjectStart) {
AddObjectMetadata(value_type);
ObjectMetadata t_data = object_metadata[value_type];
instance = Activator.CreateInstance(value_type);
while (true) {
reader.Read();
if (reader.Token == JsonToken.ObjectEnd) {
break;
}
String property = (String)reader.Value;
if (t_data.Properties.ContainsKey(property)) {
PropertyMetadata prop_data = t_data.Properties[property];
if (prop_data.IsField) {
((FieldInfo)prop_data.Info).SetValue(instance, ReadValue(prop_data.Type, reader));
} else {
PropertyInfo p_info = (PropertyInfo)prop_data.Info;
if (p_info.CanWrite) {
p_info.SetValue(instance, ReadValue(prop_data.Type, reader), null);
} else {
ReadValue(prop_data.Type, reader);
}
}
} else {
if (!t_data.IsDictionary) {
if (!reader.SkipNonMembers) {
throw new JsonException(String.Format("The type {0} doesn't have the property '{1}'", inst_type, property));
} else {
ReadSkip(reader);
continue;
}
}
((IDictionary)instance).Add(property, ReadValue(t_data.ElementType, reader));
}
}
}
return instance;
}
private static IJsonWrapper ReadValue(WrapperFactory factory, JsonReader reader) {
reader.Read();
if (reader.Token == JsonToken.ArrayEnd ||
reader.Token == JsonToken.Null) {
return null;
}
IJsonWrapper instance = factory();
if (reader.Token == JsonToken.String) {
instance.SetString((String)reader.Value);
return instance;
}
if (reader.Token == JsonToken.Double) {
instance.SetDouble((Double)reader.Value);
return instance;
}
if (reader.Token == JsonToken.Int) {
instance.SetInt((Int32)reader.Value);
return instance;
}
if (reader.Token == JsonToken.Long) {
instance.SetLong((Int64)reader.Value);
return instance;
}
if (reader.Token == JsonToken.Boolean) {
instance.SetBoolean((Boolean)reader.Value);
return instance;
}
if (reader.Token == JsonToken.ArrayStart) {
instance.SetJsonType(JsonType.Array);
while (true) {
IJsonWrapper item = ReadValue(factory, reader);
if (item == null && reader.Token == JsonToken.ArrayEnd) {
break;
}
instance.Add(item);
}
} else if (reader.Token == JsonToken.ObjectStart) {
instance.SetJsonType(JsonType.Object);
while (true) {
reader.Read();
if (reader.Token == JsonToken.ObjectEnd) {
break;
}
String property = (String)reader.Value;
instance[property] = ReadValue(factory, reader);
}
}
return instance;
}
private static void ReadSkip(JsonReader reader) {
ToWrapper(delegate { return new JsonMockWrapper(); }, reader);
}
private static void RegisterBaseExporters() {
base_exporters_table[typeof(Byte)] = delegate (Object obj, JsonWriter writer) {
writer.Write(Convert.ToInt32((Byte)obj));
};
base_exporters_table[typeof(Char)] = delegate (Object obj, JsonWriter writer) {
writer.Write(Convert.ToString((Char)obj));
};
base_exporters_table[typeof(DateTime)] = delegate (Object obj, JsonWriter writer) {
writer.Write(Convert.ToString((DateTime)obj, datetime_format));
};
base_exporters_table[typeof(TimeSpan)] = delegate (Object obj, JsonWriter writer) {
writer.Write(Convert.ToString((TimeSpan)obj, datetime_format));
};
base_exporters_table[typeof(Decimal)] = delegate (Object obj, JsonWriter writer) {
writer.Write((Decimal)obj);
};
base_exporters_table[typeof(SByte)] = delegate (Object obj, JsonWriter writer) {
writer.Write(Convert.ToInt32((SByte)obj));
};
base_exporters_table[typeof(Int16)] = delegate (Object obj, JsonWriter writer) {
writer.Write(Convert.ToInt32((Int16)obj));
};
base_exporters_table[typeof(UInt16)] = delegate (Object obj, JsonWriter writer) {
writer.Write(Convert.ToInt32((UInt16)obj));
};
base_exporters_table[typeof(UInt32)] = delegate (Object obj, JsonWriter writer) {
writer.Write(Convert.ToUInt64((UInt32)obj));
};
base_exporters_table[typeof(UInt64)] = delegate (Object obj, JsonWriter writer) {
writer.Write((UInt64)obj);
};
}
private static void RegisterBaseImporters() {
ImporterFunc importer;
importer = delegate (Object input) {
return Convert.ToByte((Int32)input);
};
RegisterImporter(base_importers_table, typeof(Int32), typeof(Byte), importer);
importer = delegate (Object input) {
return Convert.ToUInt64((Int32)input);
};
RegisterImporter(base_importers_table, typeof(Int32), typeof(UInt64), importer);
importer = delegate (Object input) {
return Convert.ToSByte((Int32)input);
};
RegisterImporter(base_importers_table, typeof(Int32), typeof(SByte), importer);
importer = delegate (Object input) {
return Convert.ToInt16((Int32)input);
};
RegisterImporter(base_importers_table, typeof(Int32), typeof(Int16), importer);
importer = delegate (Object input) {
return Convert.ToUInt16((Int32)input);
};
RegisterImporter(base_importers_table, typeof(Int32), typeof(UInt16), importer);
importer = delegate (Object input) {
return Convert.ToUInt32((Int32)input);
};
RegisterImporter(base_importers_table, typeof(Int32), typeof(UInt32), importer);
importer = delegate (Object input) {
return Convert.ToSingle((Int32)input);
};
RegisterImporter(base_importers_table, typeof(Int32), typeof(Single), importer);
importer = delegate (Object input) {
return Convert.ToDouble((Int32)input);
};
RegisterImporter(base_importers_table, typeof(Int32), typeof(Double), importer);
importer = delegate (Object input) {
return Convert.ToDecimal((Double)input);
};
RegisterImporter(base_importers_table, typeof(Double), typeof(Decimal), importer);
importer = delegate (Object input) {
return Convert.ToUInt32((Int64)input);
};
RegisterImporter(base_importers_table, typeof(Int64), typeof(UInt32), importer);
importer = delegate (Object input) {
return Convert.ToChar((String)input);
};
RegisterImporter(base_importers_table, typeof(String), typeof(Char), importer);
importer = delegate (Object input) {
return Convert.ToDateTime((String)input, datetime_format);
};
RegisterImporter(base_importers_table, typeof(String), typeof(DateTime), importer);
}
private static void RegisterImporter(IDictionary<Type, IDictionary<Type, ImporterFunc>> table, Type json_type, Type value_type, ImporterFunc importer) {
if (!table.ContainsKey(json_type)) {
table.Add(json_type, new Dictionary<Type, ImporterFunc>());
}
table[json_type][value_type] = importer;
}
private static void WriteValue(Object obj, JsonWriter writer, Boolean writer_is_private, Int32 depth) {
if (depth > max_nesting_depth) {
throw new JsonException(String.Format("Max allowed object depth reached while trying to export from type {0}", obj.GetType()));
}
if (obj == null) {
writer.Write(null);
return;
}
if (obj is IJsonWrapper) {
if (writer_is_private) {
writer.TextWriter.Write(((IJsonWrapper)obj).ToJson());
} else {
((IJsonWrapper)obj).ToJson(writer);
}
return;
}
if (obj is String) {
writer.Write((String)obj);
return;
}
if (obj is Double) {
writer.Write((Double)obj);
return;
}
if (obj is Int32) {
writer.Write((Int32)obj);
return;
}
if (obj is Boolean) {
writer.Write((Boolean)obj);
return;
}
if (obj is Int64) {
writer.Write((Int64)obj);
return;
}
if (obj is Array) {
writer.WriteArrayStart();
foreach (Object elem in (Array)obj) {
WriteValue(elem, writer, writer_is_private, depth + 1);
}
writer.WriteArrayEnd();
return;
}
if (obj is IList) {
writer.WriteArrayStart();
foreach (Object elem in (IList)obj) {
WriteValue(elem, writer, writer_is_private, depth + 1);
}
writer.WriteArrayEnd();
return;
}
if (obj is IDictionary) {
writer.WriteObjectStart();
foreach (DictionaryEntry entry in (IDictionary)obj) {
writer.WritePropertyName((String)entry.Key);
WriteValue(entry.Value, writer, writer_is_private,
depth + 1);
}
writer.WriteObjectEnd();
return;
}
Type obj_type = obj.GetType();
// See if there's a custom exporter for the object
if (custom_exporters_table.ContainsKey(obj_type)) {
ExporterFunc exporter = custom_exporters_table[obj_type];
exporter(obj, writer);
return;
}
// If not, maybe there's a base exporter
if (base_exporters_table.ContainsKey(obj_type)) {
ExporterFunc exporter = base_exporters_table[obj_type];
exporter(obj, writer);
return;
}
// Last option, let's see if it's an enum
if (obj is Enum) {
Type e_type = Enum.GetUnderlyingType(obj_type);
if (e_type == typeof(Int64)
|| e_type == typeof(UInt32)
|| e_type == typeof(UInt64)) {
writer.Write((UInt64)obj);
} else {
writer.Write((Int32)obj);
}
return;
}
// Okay, so it looks like the input should be exported as an
// object
AddTypeProperties(obj_type);
IList<PropertyMetadata> props = type_properties[obj_type];
writer.WriteObjectStart();
foreach (PropertyMetadata p_data in props) {
if (p_data.IsField) {
writer.WritePropertyName(p_data.Info.Name);
WriteValue(((FieldInfo)p_data.Info).GetValue(obj),
writer, writer_is_private, depth + 1);
} else {
PropertyInfo p_info = (PropertyInfo)p_data.Info;
if (p_info.CanRead) {
writer.WritePropertyName(p_data.Info.Name);
WriteValue(p_info.GetValue(obj, null),
writer, writer_is_private, depth + 1);
}
}
}
writer.WriteObjectEnd();
}
#endregion
public static String ToJson(Object obj) {
lock (static_writer_lock) {
static_writer.Reset();
WriteValue(obj, static_writer, true, 0);
return static_writer.ToString();
}
}
public static void ToJson(Object obj, JsonWriter writer) {
WriteValue(obj, writer, false, 0);
}
public static JsonData ToObject(JsonReader reader) {
return (JsonData)ToWrapper(delegate { return new JsonData(); }, reader);
}
public static JsonData ToObject(TextReader reader) {
JsonReader json_reader = new JsonReader(reader);
return (JsonData)ToWrapper(delegate { return new JsonData(); }, json_reader);
}
public static JsonData ToObject(String json) {
return (JsonData)ToWrapper(delegate { return new JsonData(); }, json);
}
public static T ToObject<T>(JsonReader reader) {
return (T)ReadValue(typeof(T), reader);
}
public static T ToObject<T>(TextReader reader) {
JsonReader json_reader = new JsonReader(reader);
return (T)ReadValue(typeof(T), json_reader);
}
public static T ToObject<T>(String json) {
JsonReader reader = new JsonReader(json);
return (T)ReadValue(typeof(T), reader);
}
public static Object ToObject(String json, Type ConvertType) {
JsonReader reader = new JsonReader(json);
return ReadValue(ConvertType, reader);
}
public static IJsonWrapper ToWrapper(WrapperFactory factory, JsonReader reader) {
return ReadValue(factory, reader);
}
public static IJsonWrapper ToWrapper(WrapperFactory factory, String json) {
JsonReader reader = new JsonReader(json);
return ReadValue(factory, reader);
}
public static void RegisterExporter<T>(ExporterFunc<T> exporter) {
ExporterFunc exporter_wrapper = delegate (Object obj, JsonWriter writer) {
exporter((T)obj, writer);
};
custom_exporters_table[typeof(T)] = exporter_wrapper;
}
public static void RegisterImporter<TJson, TValue>(ImporterFunc<TJson, TValue> importer) {
ImporterFunc importer_wrapper = delegate (Object input) {
return importer((TJson)input);
};
RegisterImporter(custom_importers_table, typeof(TJson), typeof(TValue), importer_wrapper);
}
public static void UnregisterExporters() {
custom_exporters_table.Clear();
}
public static void UnregisterImporters() {
custom_importers_table.Clear();
}
}
}
-105
View File
@@ -1,105 +0,0 @@
#region Header
/**
* JsonMockWrapper.cs
* Mock object implementing IJsonWrapper, to facilitate actions like
* skipping data more efficiently.
*
* The authors disclaim copyright to this source code. For more details, see
* the COPYING file included with this distribution.
**/
#endregion
using System;
using System.Collections;
using System.Collections.Specialized;
namespace LitJson
{
public class JsonMockWrapper : IJsonWrapper
{
public bool IsArray { get { return false; } }
public bool IsBoolean { get { return false; } }
public bool IsDouble { get { return false; } }
public bool IsInt { get { return false; } }
public bool IsLong { get { return false; } }
public bool IsObject { get { return false; } }
public bool IsString { get { return false; } }
public bool GetBoolean () { return false; }
public double GetDouble () { return 0.0; }
public int GetInt () { return 0; }
public JsonType GetJsonType () { return JsonType.None; }
public long GetLong () { return 0L; }
public string GetString () { return ""; }
public void SetBoolean (bool val) {}
public void SetDouble (double val) {}
public void SetInt (int val) {}
public void SetJsonType (JsonType type) {}
public void SetLong (long val) {}
public void SetString (string val) {}
public string ToJson () { return ""; }
public void ToJson (JsonWriter writer) {}
bool IList.IsFixedSize { get { return true; } }
bool IList.IsReadOnly { get { return true; } }
object IList.this[int index] {
get { return null; }
set {}
}
int IList.Add (object value) { return 0; }
void IList.Clear () {}
bool IList.Contains (object value) { return false; }
int IList.IndexOf (object value) { return -1; }
void IList.Insert (int i, object v) {}
void IList.Remove (object value) {}
void IList.RemoveAt (int index) {}
int ICollection.Count { get { return 0; } }
bool ICollection.IsSynchronized { get { return false; } }
object ICollection.SyncRoot { get { return null; } }
void ICollection.CopyTo (Array array, int index) {}
IEnumerator IEnumerable.GetEnumerator () { return null; }
bool IDictionary.IsFixedSize { get { return true; } }
bool IDictionary.IsReadOnly { get { return true; } }
ICollection IDictionary.Keys { get { return null; } }
ICollection IDictionary.Values { get { return null; } }
object IDictionary.this[object key] {
get { return null; }
set {}
}
void IDictionary.Add (object k, object v) {}
void IDictionary.Clear () {}
bool IDictionary.Contains (object key) { return false; }
void IDictionary.Remove (object key) {}
IDictionaryEnumerator IDictionary.GetEnumerator () { return null; }
object IOrderedDictionary.this[int idx] {
get { return null; }
set {}
}
IDictionaryEnumerator IOrderedDictionary.GetEnumerator () {
return null;
}
void IOrderedDictionary.Insert (int i, object k, object v) {}
void IOrderedDictionary.RemoveAt (int i) {}
}
}
-478
View File
@@ -1,478 +0,0 @@
#region Header
/**
* JsonReader.cs
* Stream-like access to JSON text.
*
* The authors disclaim copyright to this source code. For more details, see
* the COPYING file included with this distribution.
**/
#endregion
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
namespace LitJson
{
public enum JsonToken
{
None,
ObjectStart,
PropertyName,
ObjectEnd,
ArrayStart,
ArrayEnd,
Int,
Long,
Double,
String,
Boolean,
Null
}
public class JsonReader
{
#region Fields
private static readonly IDictionary<int, IDictionary<int, int[]>> parse_table;
private Stack<int> automaton_stack;
private int current_input;
private int current_symbol;
private bool end_of_json;
private bool end_of_input;
private Lexer lexer;
private bool parser_in_string;
private bool parser_return;
private bool read_started;
private TextReader reader;
private bool reader_is_owned;
private bool skip_non_members;
private object token_value;
private JsonToken token;
#endregion
#region Public Properties
public bool AllowComments {
get { return lexer.AllowComments; }
set { lexer.AllowComments = value; }
}
public bool AllowSingleQuotedStrings {
get { return lexer.AllowSingleQuotedStrings; }
set { lexer.AllowSingleQuotedStrings = value; }
}
public bool SkipNonMembers {
get { return skip_non_members; }
set { skip_non_members = value; }
}
public bool EndOfInput {
get { return end_of_input; }
}
public bool EndOfJson {
get { return end_of_json; }
}
public JsonToken Token {
get { return token; }
}
public object Value {
get { return token_value; }
}
#endregion
#region Constructors
static JsonReader ()
{
parse_table = PopulateParseTable ();
}
public JsonReader (string json_text) :
this (new StringReader (json_text), true)
{
}
public JsonReader (TextReader reader) :
this (reader, false)
{
}
private JsonReader (TextReader reader, bool owned)
{
if (reader == null)
throw new ArgumentNullException ("reader");
parser_in_string = false;
parser_return = false;
read_started = false;
automaton_stack = new Stack<int> ();
automaton_stack.Push ((int) ParserToken.End);
automaton_stack.Push ((int) ParserToken.Text);
lexer = new Lexer (reader);
end_of_input = false;
end_of_json = false;
skip_non_members = true;
this.reader = reader;
reader_is_owned = owned;
}
#endregion
#region Static Methods
private static IDictionary<int, IDictionary<int, int[]>> PopulateParseTable ()
{
// See section A.2. of the manual for details
IDictionary<int, IDictionary<int, int[]>> parse_table = new Dictionary<int, IDictionary<int, int[]>> ();
TableAddRow (parse_table, ParserToken.Array);
TableAddCol (parse_table, ParserToken.Array, '[',
'[',
(int) ParserToken.ArrayPrime);
TableAddRow (parse_table, ParserToken.ArrayPrime);
TableAddCol (parse_table, ParserToken.ArrayPrime, '"',
(int) ParserToken.Value,
(int) ParserToken.ValueRest,
']');
TableAddCol (parse_table, ParserToken.ArrayPrime, '[',
(int) ParserToken.Value,
(int) ParserToken.ValueRest,
']');
TableAddCol (parse_table, ParserToken.ArrayPrime, ']',
']');
TableAddCol (parse_table, ParserToken.ArrayPrime, '{',
(int) ParserToken.Value,
(int) ParserToken.ValueRest,
']');
TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.Number,
(int) ParserToken.Value,
(int) ParserToken.ValueRest,
']');
TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.True,
(int) ParserToken.Value,
(int) ParserToken.ValueRest,
']');
TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.False,
(int) ParserToken.Value,
(int) ParserToken.ValueRest,
']');
TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.Null,
(int) ParserToken.Value,
(int) ParserToken.ValueRest,
']');
TableAddRow (parse_table, ParserToken.Object);
TableAddCol (parse_table, ParserToken.Object, '{',
'{',
(int) ParserToken.ObjectPrime);
TableAddRow (parse_table, ParserToken.ObjectPrime);
TableAddCol (parse_table, ParserToken.ObjectPrime, '"',
(int) ParserToken.Pair,
(int) ParserToken.PairRest,
'}');
TableAddCol (parse_table, ParserToken.ObjectPrime, '}',
'}');
TableAddRow (parse_table, ParserToken.Pair);
TableAddCol (parse_table, ParserToken.Pair, '"',
(int) ParserToken.String,
':',
(int) ParserToken.Value);
TableAddRow (parse_table, ParserToken.PairRest);
TableAddCol (parse_table, ParserToken.PairRest, ',',
',',
(int) ParserToken.Pair,
(int) ParserToken.PairRest);
TableAddCol (parse_table, ParserToken.PairRest, '}',
(int) ParserToken.Epsilon);
TableAddRow (parse_table, ParserToken.String);
TableAddCol (parse_table, ParserToken.String, '"',
'"',
(int) ParserToken.CharSeq,
'"');
TableAddRow (parse_table, ParserToken.Text);
TableAddCol (parse_table, ParserToken.Text, '[',
(int) ParserToken.Array);
TableAddCol (parse_table, ParserToken.Text, '{',
(int) ParserToken.Object);
TableAddRow (parse_table, ParserToken.Value);
TableAddCol (parse_table, ParserToken.Value, '"',
(int) ParserToken.String);
TableAddCol (parse_table, ParserToken.Value, '[',
(int) ParserToken.Array);
TableAddCol (parse_table, ParserToken.Value, '{',
(int) ParserToken.Object);
TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.Number,
(int) ParserToken.Number);
TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.True,
(int) ParserToken.True);
TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.False,
(int) ParserToken.False);
TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.Null,
(int) ParserToken.Null);
TableAddRow (parse_table, ParserToken.ValueRest);
TableAddCol (parse_table, ParserToken.ValueRest, ',',
',',
(int) ParserToken.Value,
(int) ParserToken.ValueRest);
TableAddCol (parse_table, ParserToken.ValueRest, ']',
(int) ParserToken.Epsilon);
return parse_table;
}
private static void TableAddCol (IDictionary<int, IDictionary<int, int[]>> parse_table, ParserToken row, int col,
params int[] symbols)
{
parse_table[(int) row].Add (col, symbols);
}
private static void TableAddRow (IDictionary<int, IDictionary<int, int[]>> parse_table, ParserToken rule)
{
parse_table.Add ((int) rule, new Dictionary<int, int[]> ());
}
#endregion
#region Private Methods
private void ProcessNumber (string number)
{
if (number.IndexOf ('.') != -1 ||
number.IndexOf ('e') != -1 ||
number.IndexOf ('E') != -1) {
double n_double;
if (double.TryParse (number, NumberStyles.Any, CultureInfo.InvariantCulture, out n_double)) {
token = JsonToken.Double;
token_value = n_double;
return;
}
}
int n_int32;
if (int.TryParse (number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_int32)) {
token = JsonToken.Int;
token_value = n_int32;
return;
}
long n_int64;
if (long.TryParse (number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_int64)) {
token = JsonToken.Long;
token_value = n_int64;
return;
}
ulong n_uint64;
if (ulong.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_uint64))
{
token = JsonToken.Long;
token_value = n_uint64;
return;
}
// Shouldn't happen, but just in case, return something
token = JsonToken.Int;
token_value = 0;
}
private void ProcessSymbol ()
{
if (current_symbol == '[') {
token = JsonToken.ArrayStart;
parser_return = true;
} else if (current_symbol == ']') {
token = JsonToken.ArrayEnd;
parser_return = true;
} else if (current_symbol == '{') {
token = JsonToken.ObjectStart;
parser_return = true;
} else if (current_symbol == '}') {
token = JsonToken.ObjectEnd;
parser_return = true;
} else if (current_symbol == '"') {
if (parser_in_string) {
parser_in_string = false;
parser_return = true;
} else {
if (token == JsonToken.None)
token = JsonToken.String;
parser_in_string = true;
}
} else if (current_symbol == (int) ParserToken.CharSeq) {
token_value = lexer.StringValue;
} else if (current_symbol == (int) ParserToken.False) {
token = JsonToken.Boolean;
token_value = false;
parser_return = true;
} else if (current_symbol == (int) ParserToken.Null) {
token = JsonToken.Null;
parser_return = true;
} else if (current_symbol == (int) ParserToken.Number) {
ProcessNumber (lexer.StringValue);
parser_return = true;
} else if (current_symbol == (int) ParserToken.Pair) {
token = JsonToken.PropertyName;
} else if (current_symbol == (int) ParserToken.True) {
token = JsonToken.Boolean;
token_value = true;
parser_return = true;
}
}
private bool ReadToken ()
{
if (end_of_input)
return false;
lexer.NextToken ();
if (lexer.EndOfInput) {
Close ();
return false;
}
current_input = lexer.Token;
return true;
}
#endregion
public void Close ()
{
if (end_of_input)
return;
end_of_input = true;
end_of_json = true;
if (reader_is_owned)
{
using(reader){}
}
reader = null;
}
public bool Read ()
{
if (end_of_input)
return false;
if (end_of_json) {
end_of_json = false;
automaton_stack.Clear ();
automaton_stack.Push ((int) ParserToken.End);
automaton_stack.Push ((int) ParserToken.Text);
}
parser_in_string = false;
parser_return = false;
token = JsonToken.None;
token_value = null;
if (! read_started) {
read_started = true;
if (! ReadToken ())
return false;
}
int[] entry_symbols;
while (true) {
if (parser_return) {
if (automaton_stack.Peek () == (int) ParserToken.End)
end_of_json = true;
return true;
}
current_symbol = automaton_stack.Pop ();
ProcessSymbol ();
if (current_symbol == current_input) {
if (! ReadToken ()) {
if (automaton_stack.Peek () != (int) ParserToken.End)
throw new JsonException (
"Input doesn't evaluate to proper JSON text");
if (parser_return)
return true;
return false;
}
continue;
}
try {
entry_symbols =
parse_table[current_symbol][current_input];
} catch (KeyNotFoundException e) {
throw new JsonException ((ParserToken) current_input, e);
}
if (entry_symbols[0] == (int) ParserToken.Epsilon)
continue;
for (int i = entry_symbols.Length - 1; i >= 0; i--)
automaton_stack.Push (entry_symbols[i]);
}
}
}
}
-465
View File
@@ -1,465 +0,0 @@
#region Header
/**
* JsonWriter.cs
* Stream-like facility to output JSON text.
*
* The authors disclaim copyright to this source code. For more details, see
* the COPYING file included with this distribution.
**/
#endregion
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
namespace LitJson
{
internal enum Condition
{
InArray,
InObject,
NotAProperty,
Property,
Value
}
internal class WriterContext
{
public Int32 Count;
public Boolean InArray;
public Boolean InObject;
public Boolean ExpectingValue;
public Int32 Padding;
}
public class JsonWriter {
#region Fields
private static readonly NumberFormatInfo number_format;
private WriterContext context;
private Stack<WriterContext> ctx_stack;
private Boolean has_reached_end;
private Char[] hex_seq;
private Int32 indentation;
private Int32 indent_value;
private StringBuilder inst_string_builder;
private Boolean pretty_print;
private Boolean validate;
private Boolean lower_case_properties;
private TextWriter writer;
#endregion
#region Properties
public Int32 IndentValue {
get { return this.indent_value; }
set {
this.indentation = (this.indentation / this.indent_value) * value;
this.indent_value = value;
}
}
public Boolean PrettyPrint {
get { return this.pretty_print; }
set { this.pretty_print = value; }
}
public TextWriter TextWriter {
get { return this.writer; }
}
public Boolean Validate {
get { return this.validate; }
set { this.validate = value; }
}
public Boolean LowerCaseProperties {
get { return this.lower_case_properties; }
set { this.lower_case_properties = value; }
}
#endregion
#region Constructors
static JsonWriter() {
number_format = NumberFormatInfo.InvariantInfo;
}
public JsonWriter() {
this.inst_string_builder = new StringBuilder();
this.writer = new StringWriter(this.inst_string_builder);
Init();
}
public JsonWriter(StringBuilder sb) :
this(new StringWriter(sb)) {
}
public JsonWriter(TextWriter writer) {
this.writer = writer ?? throw new ArgumentNullException("writer");
Init();
}
#endregion
#region Private Methods
private void DoValidation(Condition cond) {
if (!this.context.ExpectingValue) {
this.context.Count++;
}
if (!this.validate) {
return;
}
if (this.has_reached_end) {
throw new JsonException(
"A complete JSON symbol has already been written");
}
switch (cond) {
case Condition.InArray:
if (!this.context.InArray) {
throw new JsonException(
"Can't close an array here");
}
break;
case Condition.InObject:
if (!this.context.InObject || this.context.ExpectingValue) {
throw new JsonException(
"Can't close an object here");
}
break;
case Condition.NotAProperty:
if (this.context.InObject && !this.context.ExpectingValue) {
throw new JsonException(
"Expected a property");
}
break;
case Condition.Property:
if (!this.context.InObject || this.context.ExpectingValue) {
throw new JsonException(
"Can't add a property here");
}
break;
case Condition.Value:
if (!this.context.InArray &&
(!this.context.InObject || !this.context.ExpectingValue)) {
throw new JsonException(
"Can't add a value here");
}
break;
}
}
private void Init() {
this.has_reached_end = false;
this.hex_seq = new Char[4];
this.indentation = 0;
this.indent_value = 4;
this.pretty_print = false;
this.validate = true;
this.lower_case_properties = false;
this.ctx_stack = new Stack<WriterContext>();
this.context = new WriterContext();
this.ctx_stack.Push(this.context);
}
private static void IntToHex(Int32 n, Char[] hex) {
Int32 num;
for (Int32 i = 0; i < 4; i++) {
num = n % 16;
if (num < 10) {
hex[3 - i] = (Char)('0' + num);
} else {
hex[3 - i] = (Char)('A' + (num - 10));
}
n >>= 4;
}
}
private void Indent() {
if (this.pretty_print) {
this.indentation += this.indent_value;
}
}
private void Put(String str) {
if (this.pretty_print && !this.context.ExpectingValue) {
for (Int32 i = 0; i < this.indentation; i++) {
this.writer.Write(' ');
}
}
this.writer.Write(str);
}
private void PutNewline() {
PutNewline(true);
}
private void PutNewline(Boolean add_comma) {
if (add_comma && !this.context.ExpectingValue &&
this.context.Count > 1) {
this.writer.Write(',');
}
if (this.pretty_print && !this.context.ExpectingValue) {
this.writer.Write(Environment.NewLine);
}
}
private void PutString(String str) {
Put(String.Empty);
this.writer.Write('"');
Int32 n = str.Length;
for (Int32 i = 0; i < n; i++) {
switch (str[i]) {
case '\n':
this.writer.Write("\\n");
continue;
case '\r':
this.writer.Write("\\r");
continue;
case '\t':
this.writer.Write("\\t");
continue;
case '"':
case '\\':
this.writer.Write('\\');
this.writer.Write(str[i]);
continue;
case '\f':
this.writer.Write("\\f");
continue;
case '\b':
this.writer.Write("\\b");
continue;
}
if (str[i] >= 32 && str[i] <= 126) {
this.writer.Write(str[i]);
continue;
}
// Default, turn into a \uXXXX sequence
IntToHex(str[i], this.hex_seq);
this.writer.Write("\\u");
this.writer.Write(this.hex_seq);
}
this.writer.Write('"');
}
private void Unindent() {
if (this.pretty_print) {
this.indentation -= this.indent_value;
}
}
#endregion
public override String ToString() {
if (this.inst_string_builder == null) {
return String.Empty;
}
return this.inst_string_builder.ToString();
}
public void Reset() {
this.has_reached_end = false;
this.ctx_stack.Clear();
this.context = new WriterContext();
this.ctx_stack.Push(this.context);
if (this.inst_string_builder != null) {
this.inst_string_builder.Remove(0, this.inst_string_builder.Length);
}
}
public void Write(Boolean boolean) {
DoValidation(Condition.Value);
PutNewline();
Put(boolean ? "true" : "false");
this.context.ExpectingValue = false;
}
public void Write(Decimal number) {
DoValidation(Condition.Value);
PutNewline();
Put(Convert.ToString(number, number_format));
this.context.ExpectingValue = false;
}
public void Write(Double number) {
DoValidation(Condition.Value);
PutNewline();
String str = Convert.ToString(number, number_format);
Put(str);
if (str.IndexOf('.') == -1 && str.IndexOf('E') == -1) {
this.writer.Write(".0");
}
this.context.ExpectingValue = false;
}
public void Write(Int32 number) {
DoValidation(Condition.Value);
PutNewline();
Put(Convert.ToString(number, number_format));
this.context.ExpectingValue = false;
}
public void Write(Int64 number) {
DoValidation(Condition.Value);
PutNewline();
Put(Convert.ToString(number, number_format));
this.context.ExpectingValue = false;
}
public void Write(String str) {
DoValidation(Condition.Value);
PutNewline();
if (str == null) {
Put("null");
} else {
PutString(str);
}
this.context.ExpectingValue = false;
}
// [CLSCompliant(false)]
public void Write(UInt64 number) {
DoValidation(Condition.Value);
PutNewline();
Put(Convert.ToString(number, number_format));
this.context.ExpectingValue = false;
}
public void WriteArrayEnd() {
DoValidation(Condition.InArray);
PutNewline(false);
this.ctx_stack.Pop();
if (this.ctx_stack.Count == 1) {
this.has_reached_end = true;
} else {
this.context = this.ctx_stack.Peek();
this.context.ExpectingValue = false;
}
Unindent();
Put("]");
}
public void WriteArrayStart() {
DoValidation(Condition.NotAProperty);
PutNewline();
Put("[");
this.context = new WriterContext {
InArray = true
};
this.ctx_stack.Push(this.context);
Indent();
}
public void WriteObjectEnd() {
DoValidation(Condition.InObject);
PutNewline(false);
this.ctx_stack.Pop();
if (this.ctx_stack.Count == 1) {
this.has_reached_end = true;
} else {
this.context = this.ctx_stack.Peek();
this.context.ExpectingValue = false;
}
Unindent();
Put("}");
}
public void WriteObjectStart() {
DoValidation(Condition.NotAProperty);
PutNewline();
Put("{");
this.context = new WriterContext {
InObject = true
};
this.ctx_stack.Push(this.context);
Indent();
}
public void WritePropertyName(String property_name) {
DoValidation(Condition.Property);
PutNewline();
String propertyName = (property_name == null || !this.lower_case_properties) ? property_name : property_name.ToLowerInvariant();
PutString(propertyName);
if (this.pretty_print) {
if (propertyName.Length > this.context.Padding) {
this.context.Padding = propertyName.Length;
}
for (Int32 i = this.context.Padding - propertyName.Length;
i >= 0; i--) {
this.writer.Write(' ');
}
this.writer.Write(": ");
} else {
this.writer.Write(':');
}
this.context.ExpectingValue = true;
}
}
}
-912
View File
@@ -1,912 +0,0 @@
#region Header
/**
* Lexer.cs
* JSON lexer implementation based on a finite state machine.
*
* The authors disclaim copyright to this source code. For more details, see
* the COPYING file included with this distribution.
**/
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace LitJson
{
internal class FsmContext
{
public bool Return;
public int NextState;
public Lexer L;
public int StateStack;
}
internal class Lexer
{
#region Fields
private delegate bool StateHandler (FsmContext ctx);
private static readonly int[] fsm_return_table;
private static readonly StateHandler[] fsm_handler_table;
private bool allow_comments;
private bool allow_single_quoted_strings;
private bool end_of_input;
private FsmContext fsm_context;
private int input_buffer;
private int input_char;
private TextReader reader;
private int state;
private StringBuilder string_buffer;
private string string_value;
private int token;
private int unichar;
#endregion
#region Properties
public bool AllowComments {
get { return allow_comments; }
set { allow_comments = value; }
}
public bool AllowSingleQuotedStrings {
get { return allow_single_quoted_strings; }
set { allow_single_quoted_strings = value; }
}
public bool EndOfInput {
get { return end_of_input; }
}
public int Token {
get { return token; }
}
public string StringValue {
get { return string_value; }
}
#endregion
#region Constructors
static Lexer ()
{
PopulateFsmTables (out fsm_handler_table, out fsm_return_table);
}
public Lexer (TextReader reader)
{
allow_comments = true;
allow_single_quoted_strings = true;
input_buffer = 0;
string_buffer = new StringBuilder (128);
state = 1;
end_of_input = false;
this.reader = reader;
fsm_context = new FsmContext ();
fsm_context.L = this;
}
#endregion
#region Static Methods
private static int HexValue (int digit)
{
switch (digit) {
case 'a':
case 'A':
return 10;
case 'b':
case 'B':
return 11;
case 'c':
case 'C':
return 12;
case 'd':
case 'D':
return 13;
case 'e':
case 'E':
return 14;
case 'f':
case 'F':
return 15;
default:
return digit - '0';
}
}
private static void PopulateFsmTables (out StateHandler[] fsm_handler_table, out int[] fsm_return_table)
{
// See section A.1. of the manual for details of the finite
// state machine.
fsm_handler_table = new StateHandler[28] {
State1,
State2,
State3,
State4,
State5,
State6,
State7,
State8,
State9,
State10,
State11,
State12,
State13,
State14,
State15,
State16,
State17,
State18,
State19,
State20,
State21,
State22,
State23,
State24,
State25,
State26,
State27,
State28
};
fsm_return_table = new int[28] {
(int) ParserToken.Char,
0,
(int) ParserToken.Number,
(int) ParserToken.Number,
0,
(int) ParserToken.Number,
0,
(int) ParserToken.Number,
0,
0,
(int) ParserToken.True,
0,
0,
0,
(int) ParserToken.False,
0,
0,
(int) ParserToken.Null,
(int) ParserToken.CharSeq,
(int) ParserToken.Char,
0,
0,
(int) ParserToken.CharSeq,
(int) ParserToken.Char,
0,
0,
0,
0
};
}
private static char ProcessEscChar (int esc_char)
{
switch (esc_char) {
case '"':
case '\'':
case '\\':
case '/':
return Convert.ToChar (esc_char);
case 'n':
return '\n';
case 't':
return '\t';
case 'r':
return '\r';
case 'b':
return '\b';
case 'f':
return '\f';
default:
// Unreachable
return '?';
}
}
private static bool State1 (FsmContext ctx)
{
while (ctx.L.GetChar ()) {
if (ctx.L.input_char == ' ' ||
ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r')
continue;
if (ctx.L.input_char >= '1' && ctx.L.input_char <= '9') {
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
ctx.NextState = 3;
return true;
}
switch (ctx.L.input_char) {
case '"':
ctx.NextState = 19;
ctx.Return = true;
return true;
case ',':
case ':':
case '[':
case ']':
case '{':
case '}':
ctx.NextState = 1;
ctx.Return = true;
return true;
case '-':
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
ctx.NextState = 2;
return true;
case '0':
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
ctx.NextState = 4;
return true;
case 'f':
ctx.NextState = 12;
return true;
case 'n':
ctx.NextState = 16;
return true;
case 't':
ctx.NextState = 9;
return true;
case '\'':
if (! ctx.L.allow_single_quoted_strings)
return false;
ctx.L.input_char = '"';
ctx.NextState = 23;
ctx.Return = true;
return true;
case '/':
if (! ctx.L.allow_comments)
return false;
ctx.NextState = 25;
return true;
default:
return false;
}
}
return true;
}
private static bool State2 (FsmContext ctx)
{
ctx.L.GetChar ();
if (ctx.L.input_char >= '1' && ctx.L.input_char<= '9') {
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
ctx.NextState = 3;
return true;
}
switch (ctx.L.input_char) {
case '0':
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
ctx.NextState = 4;
return true;
default:
return false;
}
}
private static bool State3 (FsmContext ctx)
{
while (ctx.L.GetChar ()) {
if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') {
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
continue;
}
if (ctx.L.input_char == ' ' ||
ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') {
ctx.Return = true;
ctx.NextState = 1;
return true;
}
switch (ctx.L.input_char) {
case ',':
case ']':
case '}':
ctx.L.UngetChar ();
ctx.Return = true;
ctx.NextState = 1;
return true;
case '.':
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
ctx.NextState = 5;
return true;
case 'e':
case 'E':
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
ctx.NextState = 7;
return true;
default:
return false;
}
}
return true;
}
private static bool State4 (FsmContext ctx)
{
ctx.L.GetChar ();
if (ctx.L.input_char == ' ' ||
ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') {
ctx.Return = true;
ctx.NextState = 1;
return true;
}
switch (ctx.L.input_char) {
case ',':
case ']':
case '}':
ctx.L.UngetChar ();
ctx.Return = true;
ctx.NextState = 1;
return true;
case '.':
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
ctx.NextState = 5;
return true;
case 'e':
case 'E':
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
ctx.NextState = 7;
return true;
default:
return false;
}
}
private static bool State5 (FsmContext ctx)
{
ctx.L.GetChar ();
if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') {
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
ctx.NextState = 6;
return true;
}
return false;
}
private static bool State6 (FsmContext ctx)
{
while (ctx.L.GetChar ()) {
if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') {
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
continue;
}
if (ctx.L.input_char == ' ' ||
ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') {
ctx.Return = true;
ctx.NextState = 1;
return true;
}
switch (ctx.L.input_char) {
case ',':
case ']':
case '}':
ctx.L.UngetChar ();
ctx.Return = true;
ctx.NextState = 1;
return true;
case 'e':
case 'E':
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
ctx.NextState = 7;
return true;
default:
return false;
}
}
return true;
}
private static bool State7 (FsmContext ctx)
{
ctx.L.GetChar ();
if (ctx.L.input_char >= '0' && ctx.L.input_char<= '9') {
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
ctx.NextState = 8;
return true;
}
switch (ctx.L.input_char) {
case '+':
case '-':
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
ctx.NextState = 8;
return true;
default:
return false;
}
}
private static bool State8 (FsmContext ctx)
{
while (ctx.L.GetChar ()) {
if (ctx.L.input_char >= '0' && ctx.L.input_char<= '9') {
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
continue;
}
if (ctx.L.input_char == ' ' ||
ctx.L.input_char >= '\t' && ctx.L.input_char<= '\r') {
ctx.Return = true;
ctx.NextState = 1;
return true;
}
switch (ctx.L.input_char) {
case ',':
case ']':
case '}':
ctx.L.UngetChar ();
ctx.Return = true;
ctx.NextState = 1;
return true;
default:
return false;
}
}
return true;
}
private static bool State9 (FsmContext ctx)
{
ctx.L.GetChar ();
switch (ctx.L.input_char) {
case 'r':
ctx.NextState = 10;
return true;
default:
return false;
}
}
private static bool State10 (FsmContext ctx)
{
ctx.L.GetChar ();
switch (ctx.L.input_char) {
case 'u':
ctx.NextState = 11;
return true;
default:
return false;
}
}
private static bool State11 (FsmContext ctx)
{
ctx.L.GetChar ();
switch (ctx.L.input_char) {
case 'e':
ctx.Return = true;
ctx.NextState = 1;
return true;
default:
return false;
}
}
private static bool State12 (FsmContext ctx)
{
ctx.L.GetChar ();
switch (ctx.L.input_char) {
case 'a':
ctx.NextState = 13;
return true;
default:
return false;
}
}
private static bool State13 (FsmContext ctx)
{
ctx.L.GetChar ();
switch (ctx.L.input_char) {
case 'l':
ctx.NextState = 14;
return true;
default:
return false;
}
}
private static bool State14 (FsmContext ctx)
{
ctx.L.GetChar ();
switch (ctx.L.input_char) {
case 's':
ctx.NextState = 15;
return true;
default:
return false;
}
}
private static bool State15 (FsmContext ctx)
{
ctx.L.GetChar ();
switch (ctx.L.input_char) {
case 'e':
ctx.Return = true;
ctx.NextState = 1;
return true;
default:
return false;
}
}
private static bool State16 (FsmContext ctx)
{
ctx.L.GetChar ();
switch (ctx.L.input_char) {
case 'u':
ctx.NextState = 17;
return true;
default:
return false;
}
}
private static bool State17 (FsmContext ctx)
{
ctx.L.GetChar ();
switch (ctx.L.input_char) {
case 'l':
ctx.NextState = 18;
return true;
default:
return false;
}
}
private static bool State18 (FsmContext ctx)
{
ctx.L.GetChar ();
switch (ctx.L.input_char) {
case 'l':
ctx.Return = true;
ctx.NextState = 1;
return true;
default:
return false;
}
}
private static bool State19 (FsmContext ctx)
{
while (ctx.L.GetChar ()) {
switch (ctx.L.input_char) {
case '"':
ctx.L.UngetChar ();
ctx.Return = true;
ctx.NextState = 20;
return true;
case '\\':
ctx.StateStack = 19;
ctx.NextState = 21;
return true;
default:
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
continue;
}
}
return true;
}
private static bool State20 (FsmContext ctx)
{
ctx.L.GetChar ();
switch (ctx.L.input_char) {
case '"':
ctx.Return = true;
ctx.NextState = 1;
return true;
default:
return false;
}
}
private static bool State21 (FsmContext ctx)
{
ctx.L.GetChar ();
switch (ctx.L.input_char) {
case 'u':
ctx.NextState = 22;
return true;
case '"':
case '\'':
case '/':
case '\\':
case 'b':
case 'f':
case 'n':
case 'r':
case 't':
ctx.L.string_buffer.Append (
ProcessEscChar (ctx.L.input_char));
ctx.NextState = ctx.StateStack;
return true;
default:
return false;
}
}
private static bool State22 (FsmContext ctx)
{
int counter = 0;
int mult = 4096;
ctx.L.unichar = 0;
while (ctx.L.GetChar ()) {
if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9' ||
ctx.L.input_char >= 'A' && ctx.L.input_char <= 'F' ||
ctx.L.input_char >= 'a' && ctx.L.input_char <= 'f') {
ctx.L.unichar += HexValue (ctx.L.input_char) * mult;
counter++;
mult /= 16;
if (counter == 4) {
ctx.L.string_buffer.Append (
Convert.ToChar (ctx.L.unichar));
ctx.NextState = ctx.StateStack;
return true;
}
continue;
}
return false;
}
return true;
}
private static bool State23 (FsmContext ctx)
{
while (ctx.L.GetChar ()) {
switch (ctx.L.input_char) {
case '\'':
ctx.L.UngetChar ();
ctx.Return = true;
ctx.NextState = 24;
return true;
case '\\':
ctx.StateStack = 23;
ctx.NextState = 21;
return true;
default:
ctx.L.string_buffer.Append ((char) ctx.L.input_char);
continue;
}
}
return true;
}
private static bool State24 (FsmContext ctx)
{
ctx.L.GetChar ();
switch (ctx.L.input_char) {
case '\'':
ctx.L.input_char = '"';
ctx.Return = true;
ctx.NextState = 1;
return true;
default:
return false;
}
}
private static bool State25 (FsmContext ctx)
{
ctx.L.GetChar ();
switch (ctx.L.input_char) {
case '*':
ctx.NextState = 27;
return true;
case '/':
ctx.NextState = 26;
return true;
default:
return false;
}
}
private static bool State26 (FsmContext ctx)
{
while (ctx.L.GetChar ()) {
if (ctx.L.input_char == '\n') {
ctx.NextState = 1;
return true;
}
}
return true;
}
private static bool State27 (FsmContext ctx)
{
while (ctx.L.GetChar ()) {
if (ctx.L.input_char == '*') {
ctx.NextState = 28;
return true;
}
}
return true;
}
private static bool State28 (FsmContext ctx)
{
while (ctx.L.GetChar ()) {
if (ctx.L.input_char == '*')
continue;
if (ctx.L.input_char == '/') {
ctx.NextState = 1;
return true;
}
ctx.NextState = 27;
return true;
}
return true;
}
#endregion
private bool GetChar ()
{
if ((input_char = NextChar ()) != -1)
return true;
end_of_input = true;
return false;
}
private int NextChar ()
{
if (input_buffer != 0) {
int tmp = input_buffer;
input_buffer = 0;
return tmp;
}
return reader.Read ();
}
public bool NextToken ()
{
StateHandler handler;
fsm_context.Return = false;
while (true) {
handler = fsm_handler_table[state - 1];
if (! handler (fsm_context))
throw new JsonException (input_char);
if (end_of_input)
return false;
if (fsm_context.Return) {
string_value = string_buffer.ToString ();
string_buffer.Remove (0, string_buffer.Length);
token = fsm_return_table[state - 1];
if (token == (int) ParserToken.Char)
token = input_char;
state = fsm_context.NextState;
return true;
}
state = fsm_context.NextState;
}
}
private void UngetChar ()
{
input_buffer = input_char;
}
}
}
-24
View File
@@ -1,24 +0,0 @@
#if NETSTANDARD1_5
using System;
using System.Reflection;
namespace LitJson
{
internal static class Netstandard15Polyfill
{
internal static Type GetInterface(this Type type, string name)
{
return type.GetTypeInfo().GetInterface(name);
}
internal static bool IsClass(this Type type)
{
return type.GetTypeInfo().IsClass;
}
internal static bool IsEnum(this Type type)
{
return type.GetTypeInfo().IsEnum;
}
}
}
#endif
-44
View File
@@ -1,44 +0,0 @@
#region Header
/**
* ParserToken.cs
* Internal representation of the tokens used by the lexer and the parser.
*
* The authors disclaim copyright to this source code. For more details, see
* the COPYING file included with this distribution.
**/
#endregion
namespace LitJson
{
internal enum ParserToken
{
// Lexer tokens (see section A.1.1. of the manual)
None = System.Char.MaxValue + 1,
Number,
True,
False,
Null,
CharSeq,
// Single char
Char,
// Parser Rules (see section A.2.1 of the manual)
Text,
Object,
ObjectPrime,
Pair,
PairRest,
Array,
ArrayPrime,
Value,
ValueRest,
String,
// End of input
End,
// The empty rule
Epsilon
}
}
@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
// die einer Assembly zugeordnet sind.
[assembly: AssemblyTitle("LitJson")]
[assembly: AssemblyDescription("LitJSON library")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LitJSON")]
[assembly: AssemblyCopyright("The authors disclaim copyright to this source code")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von
// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
[assembly: ComVisible(false)]
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
[assembly: Guid("91a14cd2-2940-4500-8193-56d37edddbaa")]
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
//
// Hauptversion
// Nebenversion
// Buildnummer
// Revision
//
// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
// indem Sie "*" wie unten gezeigt eingeben:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.12.0")]
[assembly: AssemblyFileVersion("0.12.0")]
-57
View File
@@ -1,57 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{91A14CD2-2940-4500-8193-56D37EDDDBAA}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>LitJson</RootNamespace>
<AssemblyName>litjson</AssemblyName>
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\4.7.1\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\4.7.1\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="IJsonWrapper.cs" />
<Compile Include="JsonData.cs" />
<Compile Include="JsonException.cs" />
<Compile Include="JsonMapper.cs" />
<Compile Include="JsonMockWrapper.cs" />
<Compile Include="JsonReader.cs" />
<Compile Include="JsonWriter.cs" />
<Compile Include="Lexer.cs" />
<Compile Include="Netstandard15Polyfill.cs" />
<Compile Include="ParserToken.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
Submodule
+1
Submodule mqtt added at 0a913efc4a
@@ -1,132 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
namespace uPLibrary.Networking.M2Mqtt.Exceptions
{
/// <summary>
/// MQTT client exception
/// </summary>
public class MqttClientException : Exception
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="code">Error code</param>
public MqttClientException(MqttClientErrorCode errorCode)
{
this.errorCode = errorCode;
}
// error code
private MqttClientErrorCode errorCode;
/// <summary>
/// Error code
/// </summary>
public MqttClientErrorCode ErrorCode
{
get { return this.errorCode; }
set { this.errorCode = value; }
}
}
/// <summary>
/// MQTT client erroro code
/// </summary>
public enum MqttClientErrorCode
{
/// <summary>
/// Will error (topic, message or QoS level)
/// </summary>
WillWrong = 1,
/// <summary>
/// Keep alive period too large
/// </summary>
KeepAliveWrong,
/// <summary>
/// Topic contains wildcards
/// </summary>
TopicWildcard,
/// <summary>
/// Topic length wrong
/// </summary>
TopicLength,
/// <summary>
/// QoS level not allowed
/// </summary>
QosNotAllowed,
/// <summary>
/// Topics list empty for subscribe
/// </summary>
TopicsEmpty,
/// <summary>
/// Qos levels list empty for subscribe
/// </summary>
QosLevelsEmpty,
/// <summary>
/// Topics / Qos Levels not match in subscribe
/// </summary>
TopicsQosLevelsNotMatch,
/// <summary>
/// Wrong message from broker
/// </summary>
WrongBrokerMessage,
/// <summary>
/// Wrong Message Id
/// </summary>
WrongMessageId,
/// <summary>
/// Inflight queue is full
/// </summary>
InflightQueueFull,
// [v3.1.1]
/// <summary>
/// Invalid flag bits received
/// </summary>
InvalidFlagBits,
// [v3.1.1]
/// <summary>
/// Invalid connect flags received
/// </summary>
InvalidConnectFlags,
// [v3.1.1]
/// <summary>
/// Invalid client id
/// </summary>
InvalidClientId,
// [v3.1.1]
/// <summary>
/// Invalid protocol name
/// </summary>
InvalidProtocolName
}
}
@@ -1,42 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
namespace uPLibrary.Networking.M2Mqtt.Exceptions
{
/// <summary>
/// Exception due to error communication with broker on socket
/// </summary>
public class MqttCommunicationException : Exception
{
/// <summary>
/// Default constructor
/// </summary>
public MqttCommunicationException()
{
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="e">Inner Exception</param>
public MqttCommunicationException(Exception e)
: base(String.Empty, e)
{
}
}
}
@@ -1,31 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
namespace uPLibrary.Networking.M2Mqtt.Exceptions
{
/// <summary>
/// Connection to the broker exception
/// </summary>
public class MqttConnectionException : Exception
{
public MqttConnectionException(string message, Exception innerException)
: base(message, innerException)
{
}
}
}
@@ -1,27 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
namespace uPLibrary.Networking.M2Mqtt.Exceptions
{
/// <summary>
/// Timeout on receiving from broker exception
/// </summary>
public class MqttTimeoutException : Exception
{
}
}
-69
View File
@@ -1,69 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
using System.Text;
namespace uPLibrary.Networking.M2Mqtt
{
/// <summary>
/// Interface for channel under MQTT library
/// </summary>
public interface IMqttNetworkChannel
{
/// <summary>
/// Data available on channel
/// </summary>
bool DataAvailable { get; }
/// <summary>
/// Receive data from the network channel
/// </summary>
/// <param name="buffer">Data buffer for receiving data</param>
/// <returns>Number of bytes received</returns>
int Receive(byte[] buffer);
/// <summary>
/// Receive data from the network channel with a specified timeout
/// </summary>
/// <param name="buffer">Data buffer for receiving data</param>
/// <param name="timeout">Timeout on receiving (in milliseconds)</param>
/// <returns>Number of bytes received</returns>
int Receive(byte[] buffer, int timeout);
/// <summary>
/// Send data on the network channel to the broker
/// </summary>
/// <param name="buffer">Data buffer to send</param>
/// <returns>Number of byte sent</returns>
int Send(byte[] buffer);
/// <summary>
/// Close the network channel
/// </summary>
void Close();
/// <summary>
/// Connect to remote server
/// </summary>
void Connect();
/// <summary>
/// Accept client connection
/// </summary>
void Accept();
}
}
-25
View File
@@ -1,25 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
namespace uPLibrary.Networking.M2Mqtt.Internal
{
/// <summary>
/// Generic internal event for dispatching
/// </summary>
public abstract class InternalEvent
{
}
}
-51
View File
@@ -1,51 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using uPLibrary.Networking.M2Mqtt.Messages;
namespace uPLibrary.Networking.M2Mqtt.Internal
{
/// <summary>
/// Internal event with a message
/// </summary>
public class MsgInternalEvent : InternalEvent
{
#region Properties ...
/// <summary>
/// Related message
/// </summary>
public MqttMsgBase Message
{
get { return this.msg; }
set { this.msg = value; }
}
#endregion
// related message
protected MqttMsgBase msg;
/// <summary>
/// Constructor
/// </summary>
/// <param name="msg">Related message</param>
public MsgInternalEvent(MqttMsgBase msg)
{
this.msg = msg;
}
}
}
@@ -1,53 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using uPLibrary.Networking.M2Mqtt.Messages;
namespace uPLibrary.Networking.M2Mqtt.Internal
{
/// <summary>
/// Internal event for a published message
/// </summary>
public class MsgPublishedInternalEvent : MsgInternalEvent
{
#region Properties...
/// <summary>
/// Message published (or failed due to retries)
/// </summary>
public bool IsPublished
{
get { return this.isPublished; }
internal set { this.isPublished = value; }
}
#endregion
// published flag
bool isPublished;
/// <summary>
/// Constructor
/// </summary>
/// <param name="msg">Message published</param>
/// <param name="isPublished">Publish flag</param>
public MsgPublishedInternalEvent(MqttMsgBase msg, bool isPublished)
: base(msg)
{
this.isPublished = isPublished;
}
}
}
-93
View File
@@ -1,93 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{A11AEF5A-B246-4FE8-8330-06DB73CC8074}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>uPLibrary.Networking.M2Mqtt</RootNamespace>
<AssemblyName>M2Mqtt</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\2.0\</OutputPath>
<DefineConstants>TRACE;DEBUG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\2.0\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Exceptions\MqttClientException.cs" />
<Compile Include="Exceptions\MqttCommunicationException.cs" />
<Compile Include="Exceptions\MqttConnectionException.cs" />
<Compile Include="Exceptions\MqttTimeoutException.cs" />
<Compile Include="IMqttNetworkChannel.cs" />
<Compile Include="Internal\InternalEvent.cs" />
<Compile Include="Internal\MsgInternalEvent.cs" />
<Compile Include="Internal\MsgPublishedInternalEvent.cs" />
<Compile Include="Messages\MqttMsgBase.cs" />
<Compile Include="Messages\MqttMsgConnack.cs" />
<Compile Include="Messages\MqttMsgConnect.cs" />
<Compile Include="Messages\MqttMsgConnectEventArgs.cs" />
<Compile Include="Messages\MqttMsgContext.cs" />
<Compile Include="Messages\MqttMsgDisconnect.cs" />
<Compile Include="Messages\MqttMsgPingReq.cs" />
<Compile Include="Messages\MqttMsgPingResp.cs" />
<Compile Include="Messages\MqttMsgPuback.cs" />
<Compile Include="Messages\MqttMsgPubcomp.cs" />
<Compile Include="Messages\MqttMsgPublish.cs" />
<Compile Include="Messages\MqttMsgPublishedEventArgs.cs" />
<Compile Include="Messages\MqttMsgPublishEventArgs.cs" />
<Compile Include="Messages\MqttMsgPubrec.cs" />
<Compile Include="Messages\MqttMsgPubrel.cs" />
<Compile Include="Messages\MqttMsgSuback.cs" />
<Compile Include="Messages\MqttMsgSubscribe.cs" />
<Compile Include="Messages\MqttMsgSubscribedEventArgs.cs" />
<Compile Include="Messages\MqttMsgSubscribeEventArgs.cs" />
<Compile Include="Messages\MqttMsgUnsuback.cs" />
<Compile Include="Messages\MqttMsgUnsubscribe.cs" />
<Compile Include="Messages\MqttMsgUnsubscribedEventArgs.cs" />
<Compile Include="Messages\MqttMsgUnsubscribeEventArgs.cs" />
<Compile Include="MqttClient.cs" />
<Compile Include="MqttSecurity.cs" />
<Compile Include="Net\Fx.cs" />
<Compile Include="Net\MqttNetworkChannel.cs" />
<Compile Include="MqttSettings.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Session\MqttBrokerSession.cs" />
<Compile Include="Session\MqttClientSession.cs" />
<Compile Include="Session\MqttSession.cs" />
<Compile Include="Utility\Trace.cs" />
<Compile Include="Utility\QueueExtension.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
-93
View File
@@ -1,93 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{A11AEF5A-B246-4FE8-8330-06DB73CC8074}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>uPLibrary.Networking.M2Mqtt</RootNamespace>
<AssemblyName>M2Mqtt</AssemblyName>
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\4.7.1\</OutputPath>
<DefineConstants>TRACE;DEBUG;SSL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\4.7.1\</OutputPath>
<DefineConstants>TRACE;SSL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Exceptions\MqttClientException.cs" />
<Compile Include="Exceptions\MqttCommunicationException.cs" />
<Compile Include="Exceptions\MqttConnectionException.cs" />
<Compile Include="Exceptions\MqttTimeoutException.cs" />
<Compile Include="IMqttNetworkChannel.cs" />
<Compile Include="Internal\InternalEvent.cs" />
<Compile Include="Internal\MsgInternalEvent.cs" />
<Compile Include="Internal\MsgPublishedInternalEvent.cs" />
<Compile Include="Messages\MqttMsgBase.cs" />
<Compile Include="Messages\MqttMsgConnack.cs" />
<Compile Include="Messages\MqttMsgConnect.cs" />
<Compile Include="Messages\MqttMsgConnectEventArgs.cs" />
<Compile Include="Messages\MqttMsgContext.cs" />
<Compile Include="Messages\MqttMsgDisconnect.cs" />
<Compile Include="Messages\MqttMsgPingReq.cs" />
<Compile Include="Messages\MqttMsgPingResp.cs" />
<Compile Include="Messages\MqttMsgPuback.cs" />
<Compile Include="Messages\MqttMsgPubcomp.cs" />
<Compile Include="Messages\MqttMsgPublish.cs" />
<Compile Include="Messages\MqttMsgPublishedEventArgs.cs" />
<Compile Include="Messages\MqttMsgPublishEventArgs.cs" />
<Compile Include="Messages\MqttMsgPubrec.cs" />
<Compile Include="Messages\MqttMsgPubrel.cs" />
<Compile Include="Messages\MqttMsgSuback.cs" />
<Compile Include="Messages\MqttMsgSubscribe.cs" />
<Compile Include="Messages\MqttMsgSubscribedEventArgs.cs" />
<Compile Include="Messages\MqttMsgSubscribeEventArgs.cs" />
<Compile Include="Messages\MqttMsgUnsuback.cs" />
<Compile Include="Messages\MqttMsgUnsubscribe.cs" />
<Compile Include="Messages\MqttMsgUnsubscribedEventArgs.cs" />
<Compile Include="Messages\MqttMsgUnsubscribeEventArgs.cs" />
<Compile Include="MqttClient.cs" />
<Compile Include="MqttSecurity.cs" />
<Compile Include="Net\Fx.cs" />
<Compile Include="Net\MqttNetworkChannel.cs" />
<Compile Include="MqttSettings.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Session\MqttBrokerSession.cs" />
<Compile Include="Session\MqttClientSession.cs" />
<Compile Include="Session\MqttSession.cs" />
<Compile Include="Utility\Trace.cs" />
<Compile Include="Utility\QueueExtension.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
-275
View File
@@ -1,275 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
using System.Text;
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Base class for all MQTT messages
/// </summary>
public abstract class MqttMsgBase
{
#region Constants...
// mask, offset and size for fixed header fields
internal const byte MSG_TYPE_MASK = 0xF0;
internal const byte MSG_TYPE_OFFSET = 0x04;
internal const byte MSG_TYPE_SIZE = 0x04;
internal const byte MSG_FLAG_BITS_MASK = 0x0F; // [v3.1.1]
internal const byte MSG_FLAG_BITS_OFFSET = 0x00; // [v3.1.1]
internal const byte MSG_FLAG_BITS_SIZE = 0x04; // [v3.1.1]
internal const byte DUP_FLAG_MASK = 0x08;
internal const byte DUP_FLAG_OFFSET = 0x03;
internal const byte DUP_FLAG_SIZE = 0x01;
internal const byte QOS_LEVEL_MASK = 0x06;
internal const byte QOS_LEVEL_OFFSET = 0x01;
internal const byte QOS_LEVEL_SIZE = 0x02;
internal const byte RETAIN_FLAG_MASK = 0x01;
internal const byte RETAIN_FLAG_OFFSET = 0x00;
internal const byte RETAIN_FLAG_SIZE = 0x01;
// MQTT message types
internal const byte MQTT_MSG_CONNECT_TYPE = 0x01;
internal const byte MQTT_MSG_CONNACK_TYPE = 0x02;
internal const byte MQTT_MSG_PUBLISH_TYPE = 0x03;
internal const byte MQTT_MSG_PUBACK_TYPE = 0x04;
internal const byte MQTT_MSG_PUBREC_TYPE = 0x05;
internal const byte MQTT_MSG_PUBREL_TYPE = 0x06;
internal const byte MQTT_MSG_PUBCOMP_TYPE = 0x07;
internal const byte MQTT_MSG_SUBSCRIBE_TYPE = 0x08;
internal const byte MQTT_MSG_SUBACK_TYPE = 0x09;
internal const byte MQTT_MSG_UNSUBSCRIBE_TYPE = 0x0A;
internal const byte MQTT_MSG_UNSUBACK_TYPE = 0x0B;
internal const byte MQTT_MSG_PINGREQ_TYPE = 0x0C;
internal const byte MQTT_MSG_PINGRESP_TYPE = 0x0D;
internal const byte MQTT_MSG_DISCONNECT_TYPE = 0x0E;
// [v3.1.1] MQTT flag bits
internal const byte MQTT_MSG_CONNECT_FLAG_BITS = 0x00;
internal const byte MQTT_MSG_CONNACK_FLAG_BITS = 0x00;
internal const byte MQTT_MSG_PUBLISH_FLAG_BITS = 0x00; // just defined as 0x00 but depends on publish props (dup, qos, retain)
internal const byte MQTT_MSG_PUBACK_FLAG_BITS = 0x00;
internal const byte MQTT_MSG_PUBREC_FLAG_BITS = 0x00;
internal const byte MQTT_MSG_PUBREL_FLAG_BITS = 0x02;
internal const byte MQTT_MSG_PUBCOMP_FLAG_BITS = 0x00;
internal const byte MQTT_MSG_SUBSCRIBE_FLAG_BITS = 0x02;
internal const byte MQTT_MSG_SUBACK_FLAG_BITS = 0x00;
internal const byte MQTT_MSG_UNSUBSCRIBE_FLAG_BITS = 0x02;
internal const byte MQTT_MSG_UNSUBACK_FLAG_BITS = 0x00;
internal const byte MQTT_MSG_PINGREQ_FLAG_BITS = 0x00;
internal const byte MQTT_MSG_PINGRESP_FLAG_BITS = 0x00;
internal const byte MQTT_MSG_DISCONNECT_FLAG_BITS = 0x00;
// QOS levels
public const byte QOS_LEVEL_AT_MOST_ONCE = 0x00;
public const byte QOS_LEVEL_AT_LEAST_ONCE = 0x01;
public const byte QOS_LEVEL_EXACTLY_ONCE = 0x02;
// SUBSCRIBE QoS level granted failure [v3.1.1]
public const byte QOS_LEVEL_GRANTED_FAILURE = 0x80;
internal const ushort MAX_TOPIC_LENGTH = 65535;
internal const ushort MIN_TOPIC_LENGTH = 1;
internal const byte MESSAGE_ID_SIZE = 2;
#endregion
#region Properties...
/// <summary>
/// Message type
/// </summary>
public byte Type
{
get { return this.type; }
set { this.type = value; }
}
/// <summary>
/// Duplicate message flag
/// </summary>
public bool DupFlag
{
get { return this.dupFlag; }
set { this.dupFlag = value; }
}
/// <summary>
/// Quality of Service level
/// </summary>
public byte QosLevel
{
get { return this.qosLevel; }
set { this.qosLevel = value; }
}
/// <summary>
/// Retain message flag
/// </summary>
public bool Retain
{
get { return this.retain; }
set { this.retain = value; }
}
/// <summary>
/// Message identifier for the message
/// </summary>
public ushort MessageId
{
get { return this.messageId; }
set { this.messageId = value; }
}
#endregion
// message type
protected byte type;
// duplicate delivery
protected bool dupFlag;
// quality of service level
protected byte qosLevel;
// retain flag
protected bool retain;
// message identifier
protected ushort messageId;
/// <summary>
/// Returns message bytes rapresentation
/// </summary>
/// <param name="protocolVersion">Protocol version</param>
/// <returns>Bytes rapresentation</returns>
public abstract byte[] GetBytes(byte protocolVersion);
/// <summary>
/// Encode remaining length and insert it into message buffer
/// </summary>
/// <param name="remainingLength">Remaining length value to encode</param>
/// <param name="buffer">Message buffer for inserting encoded value</param>
/// <param name="index">Index from which insert encoded value into buffer</param>
/// <returns>Index updated</returns>
protected int encodeRemainingLength(int remainingLength, byte[] buffer, int index)
{
int digit = 0;
do
{
digit = remainingLength % 128;
remainingLength /= 128;
if (remainingLength > 0)
digit = digit | 0x80;
buffer[index++] = (byte)digit;
} while (remainingLength > 0);
return index;
}
/// <summary>
/// Decode remaining length reading bytes from socket
/// </summary>
/// <param name="channel">Channel from reading bytes</param>
/// <returns>Decoded remaining length</returns>
protected static int decodeRemainingLength(IMqttNetworkChannel channel)
{
int multiplier = 1;
int value = 0;
int digit = 0;
byte[] nextByte = new byte[1];
do
{
// next digit from stream
channel.Receive(nextByte);
digit = nextByte[0];
value += ((digit & 127) * multiplier);
multiplier *= 128;
} while ((digit & 128) != 0);
return value;
}
#if TRACE
/// <summary>
/// Returns a string representation of the message for tracing
/// </summary>
/// <param name="name">Message name</param>
/// <param name="fieldNames">Message fields name</param>
/// <param name="fieldValues">Message fields value</param>
/// <returns>String representation of the message</returns>
protected string GetTraceString(string name, object[] fieldNames, object[] fieldValues)
{
StringBuilder sb = new StringBuilder();
sb.Append(name);
if ((fieldNames != null) && (fieldValues != null))
{
sb.Append("(");
bool addComma = false;
for (int i = 0; i < fieldValues.Length; i++)
{
if (fieldValues[i] != null)
{
if (addComma)
{
sb.Append(",");
}
sb.Append(fieldNames[i]);
sb.Append(":");
sb.Append(GetStringObject(fieldValues[i]));
addComma = true;
}
}
sb.Append(")");
}
return sb.ToString();
}
object GetStringObject(object value)
{
byte[] binary = value as byte[];
if (binary != null)
{
string hexChars = "0123456789ABCDEF";
StringBuilder sb = new StringBuilder(binary.Length * 2);
for (int i = 0; i < binary.Length; ++i)
{
sb.Append(hexChars[binary[i] >> 4]);
sb.Append(hexChars[binary[i] & 0x0F]);
}
return sb.ToString();
}
object[] list = value as object[];
if (list != null)
{
StringBuilder sb = new StringBuilder();
sb.Append('[');
for (int i = 0; i < list.Length; ++i)
{
if (i > 0) sb.Append(',');
sb.Append(list[i]);
}
sb.Append(']');
return sb.ToString();
}
return value;
}
#endif
}
}
-191
View File
@@ -1,191 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Class for CONNACK message from broker to client
/// </summary>
public class MqttMsgConnack : MqttMsgBase
{
#region Constants...
// return codes for CONNACK message
public const byte CONN_ACCEPTED = 0x00;
public const byte CONN_REFUSED_PROT_VERS = 0x01;
public const byte CONN_REFUSED_IDENT_REJECTED = 0x02;
public const byte CONN_REFUSED_SERVER_UNAVAILABLE = 0x03;
public const byte CONN_REFUSED_USERNAME_PASSWORD = 0x04;
public const byte CONN_REFUSED_NOT_AUTHORIZED = 0x05;
private const byte TOPIC_NAME_COMP_RESP_BYTE_OFFSET = 0;
private const byte TOPIC_NAME_COMP_RESP_BYTE_SIZE = 1;
// [v3.1.1] connect acknowledge flags replace "old" topic name compression respone (not used in 3.1)
private const byte CONN_ACK_FLAGS_BYTE_OFFSET = 0;
private const byte CONN_ACK_FLAGS_BYTE_SIZE = 1;
// [v3.1.1] session present flag
private const byte SESSION_PRESENT_FLAG_MASK = 0x01;
private const byte SESSION_PRESENT_FLAG_OFFSET = 0x00;
private const byte SESSION_PRESENT_FLAG_SIZE = 0x01;
private const byte CONN_RETURN_CODE_BYTE_OFFSET = 1;
private const byte CONN_RETURN_CODE_BYTE_SIZE = 1;
#endregion
#region Properties...
// [v3.1.1] session present flag
/// <summary>
/// Session present flag
/// </summary>
public bool SessionPresent
{
get { return this.sessionPresent; }
set { this.sessionPresent = value; }
}
/// <summary>
/// Return Code
/// </summary>
public byte ReturnCode
{
get { return this.returnCode; }
set { this.returnCode = value; }
}
#endregion
// [v3.1.1] session present flag
private bool sessionPresent;
// return code for CONNACK message
private byte returnCode;
/// <summary>
/// Constructor
/// </summary>
public MqttMsgConnack()
{
this.type = MQTT_MSG_CONNACK_TYPE;
}
/// <summary>
/// Parse bytes for a CONNACK message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>CONNACK message instance</returns>
public static MqttMsgConnack Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{
byte[] buffer;
MqttMsgConnack msg = new MqttMsgConnack();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_CONNACK_FLAG_BITS)
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
buffer = new byte[remainingLength];
// read bytes from socket...
channel.Receive(buffer);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{
// [v3.1.1] ... set session present flag ...
msg.sessionPresent = (buffer[CONN_ACK_FLAGS_BYTE_OFFSET] & SESSION_PRESENT_FLAG_MASK) != 0x00;
}
// ...and set return code from broker
msg.returnCode = buffer[CONN_RETURN_CODE_BYTE_OFFSET];
return msg;
}
public override byte[] GetBytes(byte ProtocolVersion)
{
int fixedHeaderSize = 0;
int varHeaderSize = 0;
int payloadSize = 0;
int remainingLength = 0;
byte[] buffer;
int index = 0;
if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
// flags byte and connect return code
varHeaderSize += (CONN_ACK_FLAGS_BYTE_SIZE + CONN_RETURN_CODE_BYTE_SIZE);
else
// topic name compression response and connect return code
varHeaderSize += (TOPIC_NAME_COMP_RESP_BYTE_SIZE + CONN_RETURN_CODE_BYTE_SIZE);
remainingLength += (varHeaderSize + payloadSize);
// first byte of fixed header
fixedHeaderSize = 1;
int temp = remainingLength;
// increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
do
{
fixedHeaderSize++;
temp = temp / 128;
} while (temp > 0);
// allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte
if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
buffer[index++] = (MQTT_MSG_CONNACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_CONNACK_FLAG_BITS; // [v.3.1.1]
else
buffer[index++] = (byte)(MQTT_MSG_CONNACK_TYPE << MSG_TYPE_OFFSET);
// encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index);
if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
// [v3.1.1] session present flag
buffer[index++] = this.sessionPresent ? (byte)(1 << SESSION_PRESENT_FLAG_OFFSET) : (byte)0x00;
else
// topic name compression response (reserved values. not used);
buffer[index++] = 0x00;
// connect return code
buffer[index++] = this.returnCode;
return buffer;
}
public override string ToString()
{
#if TRACE
return this.GetTraceString(
"CONNACK",
new object[] { "returnCode" },
new object[] { this.returnCode });
#else
return base.ToString();
#endif
}
}
}
-582
View File
@@ -1,582 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
using System.Text;
using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Class for CONNECT message from client to broker
/// </summary>
public class MqttMsgConnect : MqttMsgBase
{
#region Constants...
// protocol name supported
internal const string PROTOCOL_NAME_V3_1 = "MQIsdp";
internal const string PROTOCOL_NAME_V3_1_1 = "MQTT"; // [v.3.1.1]
// max length for client id (removed in 3.1.1)
internal const int CLIENT_ID_MAX_LENGTH = 23;
// variable header fields
internal const byte PROTOCOL_NAME_LEN_SIZE = 2;
internal const byte PROTOCOL_NAME_V3_1_SIZE = 6;
internal const byte PROTOCOL_NAME_V3_1_1_SIZE = 4; // [v.3.1.1]
internal const byte PROTOCOL_VERSION_SIZE = 1;
internal const byte CONNECT_FLAGS_SIZE = 1;
internal const byte KEEP_ALIVE_TIME_SIZE = 2;
internal const byte PROTOCOL_VERSION_V3_1 = 0x03;
internal const byte PROTOCOL_VERSION_V3_1_1 = 0x04; // [v.3.1.1]
internal const ushort KEEP_ALIVE_PERIOD_DEFAULT = 60; // seconds
internal const ushort MAX_KEEP_ALIVE = 65535; // 16 bit
// connect flags
internal const byte USERNAME_FLAG_MASK = 0x80;
internal const byte USERNAME_FLAG_OFFSET = 0x07;
internal const byte USERNAME_FLAG_SIZE = 0x01;
internal const byte PASSWORD_FLAG_MASK = 0x40;
internal const byte PASSWORD_FLAG_OFFSET = 0x06;
internal const byte PASSWORD_FLAG_SIZE = 0x01;
internal const byte WILL_RETAIN_FLAG_MASK = 0x20;
internal const byte WILL_RETAIN_FLAG_OFFSET = 0x05;
internal const byte WILL_RETAIN_FLAG_SIZE = 0x01;
internal const byte WILL_QOS_FLAG_MASK = 0x18;
internal const byte WILL_QOS_FLAG_OFFSET = 0x03;
internal const byte WILL_QOS_FLAG_SIZE = 0x02;
internal const byte WILL_FLAG_MASK = 0x04;
internal const byte WILL_FLAG_OFFSET = 0x02;
internal const byte WILL_FLAG_SIZE = 0x01;
internal const byte CLEAN_SESSION_FLAG_MASK = 0x02;
internal const byte CLEAN_SESSION_FLAG_OFFSET = 0x01;
internal const byte CLEAN_SESSION_FLAG_SIZE = 0x01;
// [v.3.1.1] lsb (reserved) must be now 0
internal const byte RESERVED_FLAG_MASK = 0x01;
internal const byte RESERVED_FLAG_OFFSET = 0x00;
internal const byte RESERVED_FLAG_SIZE = 0x01;
#endregion
#region Properties...
/// <summary>
/// Protocol name
/// </summary>
public string ProtocolName
{
get { return this.protocolName; }
set { this.protocolName = value; }
}
/// <summary>
/// Protocol version
/// </summary>
public byte ProtocolVersion
{
get { return this.protocolVersion; }
set { this.protocolVersion = value; }
}
/// <summary>
/// Client identifier
/// </summary>
public string ClientId
{
get { return this.clientId; }
set { this.clientId = value; }
}
/// <summary>
/// Will retain flag
/// </summary>
public bool WillRetain
{
get { return this.willRetain; }
set { this.willRetain = value; }
}
/// <summary>
/// Will QOS level
/// </summary>
public byte WillQosLevel
{
get { return this.willQosLevel; }
set { this.willQosLevel = value; }
}
/// <summary>
/// Will flag
/// </summary>
public bool WillFlag
{
get { return this.willFlag; }
set { this.willFlag = value; }
}
/// <summary>
/// Will topic
/// </summary>
public string WillTopic
{
get { return this.willTopic; }
set { this.willTopic = value; }
}
/// <summary>
/// Will message
/// </summary>
public string WillMessage
{
get { return this.willMessage; }
set { this.willMessage = value; }
}
/// <summary>
/// Username
/// </summary>
public string Username
{
get { return this.username; }
set { this.username = value; }
}
/// <summary>
/// Password
/// </summary>
public string Password
{
get { return this.password; }
set { this.password = value; }
}
/// <summary>
/// Clean session flag
/// </summary>
public bool CleanSession
{
get { return this.cleanSession; }
set { this.cleanSession = value; }
}
/// <summary>
/// Keep alive period
/// </summary>
public ushort KeepAlivePeriod
{
get { return this.keepAlivePeriod; }
set { this.keepAlivePeriod = value; }
}
#endregion
// protocol name
private string protocolName;
// protocol version
private byte protocolVersion;
// client identifier
private string clientId;
// will retain flag
protected bool willRetain;
// will quality of service level
protected byte willQosLevel;
// will flag
private bool willFlag;
// will topic
private string willTopic;
// will message
private string willMessage;
// username
private string username;
// password
private string password;
// clean session flag
private bool cleanSession;
// keep alive period (in sec)
private ushort keepAlivePeriod;
/// <summary>
/// Constructor
/// </summary>
public MqttMsgConnect()
{
this.type = MQTT_MSG_CONNECT_TYPE;
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="clientId">Client identifier</param>
public MqttMsgConnect(string clientId) :
this(clientId, null, null, false, QOS_LEVEL_AT_LEAST_ONCE, false, null, null, true, KEEP_ALIVE_PERIOD_DEFAULT, PROTOCOL_VERSION_V3_1_1)
{
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="clientId">Client identifier</param>
/// <param name="username">Username</param>
/// <param name="password">Password</param>
/// <param name="willRetain">Will retain flag</param>
/// <param name="willQosLevel">Will QOS level</param>
/// <param name="willFlag">Will flag</param>
/// <param name="willTopic">Will topic</param>
/// <param name="willMessage">Will message</param>
/// <param name="cleanSession">Clean sessione flag</param>
/// <param name="keepAlivePeriod">Keep alive period</param>
/// <param name="protocolVersion">Protocol version</param>
public MqttMsgConnect(string clientId,
string username,
string password,
bool willRetain,
byte willQosLevel,
bool willFlag,
string willTopic,
string willMessage,
bool cleanSession,
ushort keepAlivePeriod,
byte protocolVersion
)
{
this.type = MQTT_MSG_CONNECT_TYPE;
this.clientId = clientId;
this.username = username;
this.password = password;
this.willRetain = willRetain;
this.willQosLevel = willQosLevel;
this.willFlag = willFlag;
this.willTopic = willTopic;
this.willMessage = willMessage;
this.cleanSession = cleanSession;
this.keepAlivePeriod = keepAlivePeriod;
// [v.3.1.1] added new protocol name and version
this.protocolVersion = protocolVersion;
this.protocolName = (this.protocolVersion == PROTOCOL_VERSION_V3_1_1) ? PROTOCOL_NAME_V3_1_1 : PROTOCOL_NAME_V3_1;
}
/// <summary>
/// Parse bytes for a CONNECT message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>CONNECT message instance</returns>
public static MqttMsgConnect Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{
byte[] buffer;
int index = 0;
int protNameUtf8Length;
byte[] protNameUtf8;
bool isUsernameFlag;
bool isPasswordFlag;
int clientIdUtf8Length;
byte[] clientIdUtf8;
int willTopicUtf8Length;
byte[] willTopicUtf8;
int willMessageUtf8Length;
byte[] willMessageUtf8;
int usernameUtf8Length;
byte[] usernameUtf8;
int passwordUtf8Length;
byte[] passwordUtf8;
MqttMsgConnect msg = new MqttMsgConnect();
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
buffer = new byte[remainingLength];
// read bytes from socket...
channel.Receive(buffer);
// protocol name
protNameUtf8Length = ((buffer[index++] << 8) & 0xFF00);
protNameUtf8Length |= buffer[index++];
protNameUtf8 = new byte[protNameUtf8Length];
Array.Copy(buffer, index, protNameUtf8, 0, protNameUtf8Length);
index += protNameUtf8Length;
msg.protocolName = new String(Encoding.UTF8.GetChars(protNameUtf8));
// [v3.1.1] wrong protocol name
if (!msg.protocolName.Equals(PROTOCOL_NAME_V3_1) && !msg.protocolName.Equals(PROTOCOL_NAME_V3_1_1))
throw new MqttClientException(MqttClientErrorCode.InvalidProtocolName);
// protocol version
msg.protocolVersion = buffer[index];
index += PROTOCOL_VERSION_SIZE;
// connect flags
// [v3.1.1] check lsb (reserved) must be 0
if ((msg.protocolVersion == PROTOCOL_VERSION_V3_1_1) &&
((buffer[index] & RESERVED_FLAG_MASK) != 0x00))
throw new MqttClientException(MqttClientErrorCode.InvalidConnectFlags);
isUsernameFlag = (buffer[index] & USERNAME_FLAG_MASK) != 0x00;
isPasswordFlag = (buffer[index] & PASSWORD_FLAG_MASK) != 0x00;
msg.willRetain = (buffer[index] & WILL_RETAIN_FLAG_MASK) != 0x00;
msg.willQosLevel = (byte)((buffer[index] & WILL_QOS_FLAG_MASK) >> WILL_QOS_FLAG_OFFSET);
msg.willFlag = (buffer[index] & WILL_FLAG_MASK) != 0x00;
msg.cleanSession = (buffer[index] & CLEAN_SESSION_FLAG_MASK) != 0x00;
index += CONNECT_FLAGS_SIZE;
// keep alive timer
msg.keepAlivePeriod = (ushort)((buffer[index++] << 8) & 0xFF00);
msg.keepAlivePeriod |= buffer[index++];
// client identifier [v3.1.1] it may be zero bytes long (empty string)
clientIdUtf8Length = ((buffer[index++] << 8) & 0xFF00);
clientIdUtf8Length |= buffer[index++];
clientIdUtf8 = new byte[clientIdUtf8Length];
Array.Copy(buffer, index, clientIdUtf8, 0, clientIdUtf8Length);
index += clientIdUtf8Length;
msg.clientId = new String(Encoding.UTF8.GetChars(clientIdUtf8));
// [v3.1.1] if client identifier is zero bytes long, clean session must be true
if ((msg.protocolVersion == PROTOCOL_VERSION_V3_1_1) && (clientIdUtf8Length == 0) && (!msg.cleanSession))
throw new MqttClientException(MqttClientErrorCode.InvalidClientId);
// will topic and will message
if (msg.willFlag)
{
willTopicUtf8Length = ((buffer[index++] << 8) & 0xFF00);
willTopicUtf8Length |= buffer[index++];
willTopicUtf8 = new byte[willTopicUtf8Length];
Array.Copy(buffer, index, willTopicUtf8, 0, willTopicUtf8Length);
index += willTopicUtf8Length;
msg.willTopic = new String(Encoding.UTF8.GetChars(willTopicUtf8));
willMessageUtf8Length = ((buffer[index++] << 8) & 0xFF00);
willMessageUtf8Length |= buffer[index++];
willMessageUtf8 = new byte[willMessageUtf8Length];
Array.Copy(buffer, index, willMessageUtf8, 0, willMessageUtf8Length);
index += willMessageUtf8Length;
msg.willMessage = new String(Encoding.UTF8.GetChars(willMessageUtf8));
}
// username
if (isUsernameFlag)
{
usernameUtf8Length = ((buffer[index++] << 8) & 0xFF00);
usernameUtf8Length |= buffer[index++];
usernameUtf8 = new byte[usernameUtf8Length];
Array.Copy(buffer, index, usernameUtf8, 0, usernameUtf8Length);
index += usernameUtf8Length;
msg.username = new String(Encoding.UTF8.GetChars(usernameUtf8));
}
// password
if (isPasswordFlag)
{
passwordUtf8Length = ((buffer[index++] << 8) & 0xFF00);
passwordUtf8Length |= buffer[index++];
passwordUtf8 = new byte[passwordUtf8Length];
Array.Copy(buffer, index, passwordUtf8, 0, passwordUtf8Length);
index += passwordUtf8Length;
msg.password = new String(Encoding.UTF8.GetChars(passwordUtf8));
}
return msg;
}
public override byte[] GetBytes(byte protocolVersion)
{
int fixedHeaderSize = 0;
int varHeaderSize = 0;
int payloadSize = 0;
int remainingLength = 0;
byte[] buffer;
int index = 0;
byte[] clientIdUtf8 = Encoding.UTF8.GetBytes(this.clientId);
byte[] willTopicUtf8 = (this.willFlag && (this.willTopic != null)) ? Encoding.UTF8.GetBytes(this.willTopic) : null;
byte[] willMessageUtf8 = (this.willFlag && (this.willMessage != null)) ? Encoding.UTF8.GetBytes(this.willMessage) : null;
byte[] usernameUtf8 = ((this.username != null) && (this.username.Length > 0)) ? Encoding.UTF8.GetBytes(this.username) : null;
byte[] passwordUtf8 = ((this.password != null) && (this.password.Length > 0)) ? Encoding.UTF8.GetBytes(this.password) : null;
// [v3.1.1]
if (this.protocolVersion == PROTOCOL_VERSION_V3_1_1)
{
// will flag set, will topic and will message MUST be present
if (this.willFlag && ((this.willQosLevel >= 0x03) ||
(willTopicUtf8 == null) || (willMessageUtf8 == null) ||
((willTopicUtf8 != null) && (willTopicUtf8.Length == 0)) ||
((willMessageUtf8 != null) && (willMessageUtf8.Length == 0))))
throw new MqttClientException(MqttClientErrorCode.WillWrong);
// willflag not set, retain must be 0 and will topic and message MUST NOT be present
else if (!this.willFlag && ((this.willRetain) ||
(willTopicUtf8 != null) || (willMessageUtf8 != null) ||
((willTopicUtf8 != null) && (willTopicUtf8.Length != 0)) ||
((willMessageUtf8 != null) && (willMessageUtf8.Length != 0))))
throw new MqttClientException(MqttClientErrorCode.WillWrong);
}
if (this.keepAlivePeriod > MAX_KEEP_ALIVE)
throw new MqttClientException(MqttClientErrorCode.KeepAliveWrong);
// check on will QoS Level
if ((this.willQosLevel < MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE) ||
(this.willQosLevel > MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE))
throw new MqttClientException(MqttClientErrorCode.WillWrong);
// protocol name field size
// MQTT version 3.1
if (this.protocolVersion == PROTOCOL_VERSION_V3_1)
{
varHeaderSize += (PROTOCOL_NAME_LEN_SIZE + PROTOCOL_NAME_V3_1_SIZE);
}
// MQTT version 3.1.1
else
{
varHeaderSize += (PROTOCOL_NAME_LEN_SIZE + PROTOCOL_NAME_V3_1_1_SIZE);
}
// protocol level field size
varHeaderSize += PROTOCOL_VERSION_SIZE;
// connect flags field size
varHeaderSize += CONNECT_FLAGS_SIZE;
// keep alive timer field size
varHeaderSize += KEEP_ALIVE_TIME_SIZE;
// client identifier field size
payloadSize += clientIdUtf8.Length + 2;
// will topic field size
payloadSize += (willTopicUtf8 != null) ? (willTopicUtf8.Length + 2) : 0;
// will message field size
payloadSize += (willMessageUtf8 != null) ? (willMessageUtf8.Length + 2) : 0;
// username field size
payloadSize += (usernameUtf8 != null) ? (usernameUtf8.Length + 2) : 0;
// password field size
payloadSize += (passwordUtf8 != null) ? (passwordUtf8.Length + 2) : 0;
remainingLength += (varHeaderSize + payloadSize);
// first byte of fixed header
fixedHeaderSize = 1;
int temp = remainingLength;
// increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
do
{
fixedHeaderSize++;
temp = temp / 128;
} while (temp > 0);
// allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte
buffer[index++] = (MQTT_MSG_CONNECT_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_CONNECT_FLAG_BITS; // [v.3.1.1]
// encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index);
// protocol name
buffer[index++] = 0; // MSB protocol name size
// MQTT version 3.1
if (this.protocolVersion == PROTOCOL_VERSION_V3_1)
{
buffer[index++] = PROTOCOL_NAME_V3_1_SIZE; // LSB protocol name size
Array.Copy(Encoding.UTF8.GetBytes(PROTOCOL_NAME_V3_1), 0, buffer, index, PROTOCOL_NAME_V3_1_SIZE);
index += PROTOCOL_NAME_V3_1_SIZE;
// protocol version
buffer[index++] = PROTOCOL_VERSION_V3_1;
}
// MQTT version 3.1.1
else
{
buffer[index++] = PROTOCOL_NAME_V3_1_1_SIZE; // LSB protocol name size
Array.Copy(Encoding.UTF8.GetBytes(PROTOCOL_NAME_V3_1_1), 0, buffer, index, PROTOCOL_NAME_V3_1_1_SIZE);
index += PROTOCOL_NAME_V3_1_1_SIZE;
// protocol version
buffer[index++] = PROTOCOL_VERSION_V3_1_1;
}
// connect flags
byte connectFlags = 0x00;
connectFlags |= (usernameUtf8 != null) ? (byte)(1 << USERNAME_FLAG_OFFSET) : (byte)0x00;
connectFlags |= (passwordUtf8 != null) ? (byte)(1 << PASSWORD_FLAG_OFFSET) : (byte)0x00;
connectFlags |= (this.willRetain) ? (byte)(1 << WILL_RETAIN_FLAG_OFFSET) : (byte)0x00;
// only if will flag is set, we have to use will QoS level (otherwise is MUST be 0)
if (this.willFlag)
connectFlags |= (byte)(this.willQosLevel << WILL_QOS_FLAG_OFFSET);
connectFlags |= (this.willFlag) ? (byte)(1 << WILL_FLAG_OFFSET) : (byte)0x00;
connectFlags |= (this.cleanSession) ? (byte)(1 << CLEAN_SESSION_FLAG_OFFSET) : (byte)0x00;
buffer[index++] = connectFlags;
// keep alive period
buffer[index++] = (byte)((this.keepAlivePeriod >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(this.keepAlivePeriod & 0x00FF); // LSB
// client identifier
buffer[index++] = (byte)((clientIdUtf8.Length >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(clientIdUtf8.Length & 0x00FF); // LSB
Array.Copy(clientIdUtf8, 0, buffer, index, clientIdUtf8.Length);
index += clientIdUtf8.Length;
// will topic
if (this.willFlag && (willTopicUtf8 != null))
{
buffer[index++] = (byte)((willTopicUtf8.Length >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(willTopicUtf8.Length & 0x00FF); // LSB
Array.Copy(willTopicUtf8, 0, buffer, index, willTopicUtf8.Length);
index += willTopicUtf8.Length;
}
// will message
if (this.willFlag && (willMessageUtf8 != null))
{
buffer[index++] = (byte)((willMessageUtf8.Length >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(willMessageUtf8.Length & 0x00FF); // LSB
Array.Copy(willMessageUtf8, 0, buffer, index, willMessageUtf8.Length);
index += willMessageUtf8.Length;
}
// username
if (usernameUtf8 != null)
{
buffer[index++] = (byte)((usernameUtf8.Length >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(usernameUtf8.Length & 0x00FF); // LSB
Array.Copy(usernameUtf8, 0, buffer, index, usernameUtf8.Length);
index += usernameUtf8.Length;
}
// password
if (passwordUtf8 != null)
{
buffer[index++] = (byte)((passwordUtf8.Length >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(passwordUtf8.Length & 0x00FF); // LSB
Array.Copy(passwordUtf8, 0, buffer, index, passwordUtf8.Length);
index += passwordUtf8.Length;
}
return buffer;
}
public override string ToString()
{
#if TRACE
return this.GetTraceString(
"CONNECT",
new object[] { "protocolName", "protocolVersion", "clientId", "willFlag", "willRetain", "willQosLevel", "willTopic", "willMessage", "username", "password", "cleanSession", "keepAlivePeriod" },
new object[] { this.protocolName, this.protocolVersion, this.clientId, this.willFlag, this.willRetain, this.willQosLevel, this.willTopic, this.willMessage, this.username, this.password, this.cleanSession, this.keepAlivePeriod });
#else
return base.ToString();
#endif
}
}
}
@@ -1,44 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
using System;
#else
using Microsoft.SPOT;
#endif
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Event Args class for CONNECT message received from client
/// </summary>
public class MqttMsgConnectEventArgs : EventArgs
{
/// <summary>
/// Message received from client
/// </summary>
public MqttMsgConnect Message { get; private set; }
/// <summary>
/// Constructor
/// </summary>
/// <param name="msg">CONNECT message received from client</param>
public MqttMsgConnectEventArgs(MqttMsgConnect connect)
{
this.Message = connect;
}
}
}
-159
View File
@@ -1,159 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
using System.Text;
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Context for MQTT message
/// </summary>
public class MqttMsgContext
{
/// <summary>
/// MQTT message
/// </summary>
public MqttMsgBase Message { get; set; }
/// <summary>
/// MQTT message state
/// </summary>
public MqttMsgState State { get; set; }
/// <summary>
/// Flow of the message
/// </summary>
public MqttMsgFlow Flow { get; set; }
/// <summary>
/// Timestamp in ticks (for retry)
/// </summary>
public int Timestamp { get; set; }
/// <summary>
/// Attempt (for retry)
/// </summary>
public int Attempt { get; set; }
/// <summary>
/// Unique key
/// </summary>
public string Key
{
get { return this.Flow + "_" + this.Message.MessageId; }
}
}
/// <summary>
/// Flow of the message
/// </summary>
public enum MqttMsgFlow
{
/// <summary>
/// To publish to subscribers
/// </summary>
ToPublish,
/// <summary>
/// To acknowledge to publisher
/// </summary>
ToAcknowledge
}
/// <summary>
/// MQTT message state
/// </summary>
public enum MqttMsgState
{
/// <summary>
/// QOS = 0, Message queued
/// </summary>
QueuedQos0,
/// <summary>
/// QOS = 1, Message queued
/// </summary>
QueuedQos1,
/// <summary>
/// QOS = 2, Message queued
/// </summary>
QueuedQos2,
/// <summary>
/// QOS = 1, PUBLISH sent, wait for PUBACK
/// </summary>
WaitForPuback,
/// <summary>
/// QOS = 2, PUBLISH sent, wait for PUBREC
/// </summary>
WaitForPubrec,
/// <summary>
/// QOS = 2, PUBREC sent, wait for PUBREL
/// </summary>
WaitForPubrel,
/// <summary>
/// QOS = 2, PUBREL sent, wait for PUBCOMP
/// </summary>
WaitForPubcomp,
/// <summary>
/// QOS = 2, start first phase handshake send PUBREC
/// </summary>
SendPubrec,
/// <summary>
/// QOS = 2, start second phase handshake send PUBREL
/// </summary>
SendPubrel,
/// <summary>
/// QOS = 2, end second phase handshake send PUBCOMP
/// </summary>
SendPubcomp,
/// <summary>
/// QOS = 1, PUBLISH received, send PUBACK
/// </summary>
SendPuback,
// [v3.1.1] SUBSCRIBE isn't "officially" QOS = 1
/// <summary>
/// Send SUBSCRIBE message
/// </summary>
SendSubscribe,
// [v3.1.1] UNSUBSCRIBE isn't "officially" QOS = 1
/// <summary>
/// Send UNSUBSCRIBE message
/// </summary>
SendUnsubscribe,
/// <summary>
/// (QOS = 1), SUBSCRIBE sent, wait for SUBACK
/// </summary>
WaitForSuback,
/// <summary>
/// (QOS = 1), UNSUBSCRIBE sent, wait for UNSUBACK
/// </summary>
WaitForUnsuback
}
}
-86
View File
@@ -1,86 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Class for DISCONNECT message from client to broker
/// </summary>
public class MqttMsgDisconnect : MqttMsgBase
{
/// <summary>
/// Constructor
/// </summary>
public MqttMsgDisconnect()
{
this.type = MQTT_MSG_DISCONNECT_TYPE;
}
/// <summary>
/// Parse bytes for a DISCONNECT message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>DISCONNECT message instance</returns>
public static MqttMsgDisconnect Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{
MqttMsgDisconnect msg = new MqttMsgDisconnect();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_DISCONNECT_FLAG_BITS)
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
// NOTE : remainingLength must be 0
return msg;
}
public override byte[] GetBytes(byte protocolVersion)
{
byte[] buffer = new byte[2];
int index = 0;
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
buffer[index++] = (MQTT_MSG_DISCONNECT_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_DISCONNECT_FLAG_BITS; // [v.3.1.1]
else
buffer[index++] = (MQTT_MSG_DISCONNECT_TYPE << MSG_TYPE_OFFSET);
buffer[index++] = 0x00;
return buffer;
}
public override string ToString()
{
#if TRACE
return this.GetTraceString(
"DISCONNECT",
null,
null);
#else
return base.ToString();
#endif
}
}
}
-86
View File
@@ -1,86 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Class for PINGREQ message from client to broker
/// </summary>
public class MqttMsgPingReq : MqttMsgBase
{
/// <summary>
/// Constructor
/// </summary>
public MqttMsgPingReq()
{
this.type = MQTT_MSG_PINGREQ_TYPE;
}
public override byte[] GetBytes(byte protocolVersion)
{
byte[] buffer = new byte[2];
int index = 0;
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
buffer[index++] = (MQTT_MSG_PINGREQ_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PINGREQ_FLAG_BITS; // [v.3.1.1]
else
buffer[index++] = (MQTT_MSG_PINGREQ_TYPE << MSG_TYPE_OFFSET);
buffer[index++] = 0x00;
return buffer;
}
/// <summary>
/// Parse bytes for a PINGREQ message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>PINGREQ message instance</returns>
public static MqttMsgPingReq Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{
MqttMsgPingReq msg = new MqttMsgPingReq();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGREQ_FLAG_BITS)
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
// already know remaininglength is zero (MQTT specification),
// so it isn't necessary to read other data from socket
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
return msg;
}
public override string ToString()
{
#if TRACE
return this.GetTraceString(
"PINGREQ",
null,
null);
#else
return base.ToString();
#endif
}
}
}
-87
View File
@@ -1,87 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Class for PINGRESP message from client to broker
/// </summary>
public class MqttMsgPingResp : MqttMsgBase
{
/// <summary>
/// Constructor
/// </summary>
public MqttMsgPingResp()
{
this.type = MQTT_MSG_PINGRESP_TYPE;
}
/// <summary>
/// Parse bytes for a PINGRESP message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>PINGRESP message instance</returns>
public static MqttMsgPingResp Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{
MqttMsgPingResp msg = new MqttMsgPingResp();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGRESP_FLAG_BITS)
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
// already know remaininglength is zero (MQTT specification),
// so it isn't necessary to read other data from socket
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
return msg;
}
public override byte[] GetBytes(byte protocolVersion)
{
byte[] buffer = new byte[2];
int index = 0;
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
buffer[index++] = (MQTT_MSG_PINGRESP_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PINGRESP_FLAG_BITS; // [v.3.1.1]
else
buffer[index++] = (MQTT_MSG_PINGRESP_TYPE << MSG_TYPE_OFFSET);
buffer[index++] = 0x00;
return buffer;
}
public override string ToString()
{
#if TRACE
return this.GetTraceString(
"PINGRESP",
null,
null);
#else
return base.ToString();
#endif
}
}
}
-125
View File
@@ -1,125 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Class for PUBACK message from broker to client
/// </summary>
public class MqttMsgPuback : MqttMsgBase
{
/// <summary>
/// Constructor
/// </summary>
public MqttMsgPuback()
{
this.type = MQTT_MSG_PUBACK_TYPE;
}
public override byte[] GetBytes(byte protocolVersion)
{
int fixedHeaderSize = 0;
int varHeaderSize = 0;
int payloadSize = 0;
int remainingLength = 0;
byte[] buffer;
int index = 0;
// message identifier
varHeaderSize += MESSAGE_ID_SIZE;
remainingLength += (varHeaderSize + payloadSize);
// first byte of fixed header
fixedHeaderSize = 1;
int temp = remainingLength;
// increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
do
{
fixedHeaderSize++;
temp = temp / 128;
} while (temp > 0);
// allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
buffer[index++] = (MQTT_MSG_PUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBACK_FLAG_BITS; // [v.3.1.1]
else
buffer[index++] = (MQTT_MSG_PUBACK_TYPE << MSG_TYPE_OFFSET);
// encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index);
// get message identifier
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB
return buffer;
}
/// <summary>
/// Parse bytes for a PUBACK message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>PUBACK message instance</returns>
public static MqttMsgPuback Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{
byte[] buffer;
int index = 0;
MqttMsgPuback msg = new MqttMsgPuback();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBACK_FLAG_BITS)
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
buffer = new byte[remainingLength];
// read bytes from socket...
channel.Receive(buffer);
// message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]);
return msg;
}
public override string ToString()
{
#if TRACE
return this.GetTraceString(
"PUBACK",
new object[] { "messageId" },
new object[] { this.messageId });
#else
return base.ToString();
#endif
}
}
}
-125
View File
@@ -1,125 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Class for PUBCOMP message from broker to client
/// </summary>
public class MqttMsgPubcomp : MqttMsgBase
{
/// <summary>
/// Constructor
/// </summary>
public MqttMsgPubcomp()
{
this.type = MQTT_MSG_PUBCOMP_TYPE;
}
public override byte[] GetBytes(byte protocolVersion)
{
int fixedHeaderSize = 0;
int varHeaderSize = 0;
int payloadSize = 0;
int remainingLength = 0;
byte[] buffer;
int index = 0;
// message identifier
varHeaderSize += MESSAGE_ID_SIZE;
remainingLength += (varHeaderSize + payloadSize);
// first byte of fixed header
fixedHeaderSize = 1;
int temp = remainingLength;
// increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
do
{
fixedHeaderSize++;
temp = temp / 128;
} while (temp > 0);
// allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
buffer[index++] = (MQTT_MSG_PUBCOMP_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBCOMP_FLAG_BITS; // [v.3.1.1]
else
buffer[index++] = (MQTT_MSG_PUBCOMP_TYPE << MSG_TYPE_OFFSET);
// encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index);
// get message identifier
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB
return buffer;
}
/// <summary>
/// Parse bytes for a PUBCOMP message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>PUBCOMP message instance</returns>
public static MqttMsgPubcomp Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{
byte[] buffer;
int index = 0;
MqttMsgPubcomp msg = new MqttMsgPubcomp();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBCOMP_FLAG_BITS)
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
buffer = new byte[remainingLength];
// read bytes from socket...
channel.Receive(buffer);
// message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]);
return msg;
}
public override string ToString()
{
#if TRACE
return this.GetTraceString(
"PUBCOMP",
new object[] { "messageId" },
new object[] { this.messageId });
#else
return base.ToString();
#endif
}
}
}
-249
View File
@@ -1,249 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
using System.Text;
using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages {
/// <summary>
/// Class for PUBLISH message from client to broker
/// </summary>
public class MqttMsgPublish : MqttMsgBase {
#region Properties...
/// <summary>
/// Message topic
/// </summary>
public String Topic { get; set; }
/// <summary>
/// Message data
/// </summary>
public Byte[] Message { get; set; }
#endregion
/// <summary>
/// Constructor
/// </summary>
public MqttMsgPublish() {
this.type = MQTT_MSG_PUBLISH_TYPE;
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="topic">Message topic</param>
/// <param name="message">Message data</param>
public MqttMsgPublish(String topic, Byte[] message) : this(topic, message, false, QOS_LEVEL_AT_MOST_ONCE, false) {
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="topic">Message topic</param>
/// <param name="message">Message data</param>
/// <param name="dupFlag">Duplicate flag</param>
/// <param name="qosLevel">Quality of Service level</param>
/// <param name="retain">Retain flag</param>
public MqttMsgPublish(String topic, Byte[] message, Boolean dupFlag, Byte qosLevel, Boolean retain) : base() {
this.type = MQTT_MSG_PUBLISH_TYPE;
this.Topic = topic;
this.Message = message;
this.dupFlag = dupFlag;
this.qosLevel = qosLevel;
this.retain = retain;
this.messageId = 0;
}
public override Byte[] GetBytes(Byte protocolVersion) {
Int32 fixedHeaderSize = 0;
Int32 varHeaderSize = 0;
Int32 payloadSize = 0;
Int32 remainingLength = 0;
Byte[] buffer;
Int32 index = 0;
// topic can't contain wildcards
if ((this.Topic.IndexOf('#') != -1) || (this.Topic.IndexOf('+') != -1)) {
throw new MqttClientException(MqttClientErrorCode.TopicWildcard);
}
// check topic length
if ((this.Topic.Length < MIN_TOPIC_LENGTH) || (this.Topic.Length > MAX_TOPIC_LENGTH)) {
throw new MqttClientException(MqttClientErrorCode.TopicLength);
}
// check wrong QoS level (both bits can't be set 1)
if (this.qosLevel > QOS_LEVEL_EXACTLY_ONCE) {
throw new MqttClientException(MqttClientErrorCode.QosNotAllowed);
}
Byte[] topicUtf8 = Encoding.UTF8.GetBytes(this.Topic);
// topic name
varHeaderSize += topicUtf8.Length + 2;
// message id is valid only with QOS level 1 or QOS level 2
if ((this.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) || (this.qosLevel == QOS_LEVEL_EXACTLY_ONCE)) {
varHeaderSize += MESSAGE_ID_SIZE;
}
// check on message with zero length
if (this.Message != null) {
// message data
payloadSize += this.Message.Length;
}
remainingLength += (varHeaderSize + payloadSize);
// first byte of fixed header
fixedHeaderSize = 1;
Int32 temp = remainingLength;
// increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
do {
fixedHeaderSize++;
temp = temp / 128;
} while (temp > 0);
// allocate buffer for message
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte
buffer[index] = (Byte)((MQTT_MSG_PUBLISH_TYPE << MSG_TYPE_OFFSET) | (this.qosLevel << QOS_LEVEL_OFFSET));
buffer[index] |= this.dupFlag ? (Byte)(1 << DUP_FLAG_OFFSET) : (Byte)0x00;
buffer[index] |= this.retain ? (Byte)(1 << RETAIN_FLAG_OFFSET) : (Byte)0x00;
index++;
// encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index);
// topic name
buffer[index++] = (Byte)((topicUtf8.Length >> 8) & 0x00FF); // MSB
buffer[index++] = (Byte)(topicUtf8.Length & 0x00FF); // LSB
Array.Copy(topicUtf8, 0, buffer, index, topicUtf8.Length);
index += topicUtf8.Length;
// message id is valid only with QOS level 1 or QOS level 2
if ((this.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) ||
(this.qosLevel == QOS_LEVEL_EXACTLY_ONCE)) {
// check message identifier assigned
if (this.messageId == 0) {
throw new MqttClientException(MqttClientErrorCode.WrongMessageId);
}
buffer[index++] = (Byte)((this.messageId >> 8) & 0x00FF); // MSB
buffer[index++] = (Byte)(this.messageId & 0x00FF); // LSB
}
// check on message with zero length
if (this.Message != null) {
// message data
Array.Copy(this.Message, 0, buffer, index, this.Message.Length);
index += this.Message.Length;
}
return buffer;
}
/// <summary>
/// Parse bytes for a PUBLISH message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>PUBLISH message instance</returns>
public static MqttMsgPublish Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
Byte[] buffer;
Int32 index = 0;
Byte[] topicUtf8;
Int32 topicUtf8Length;
MqttMsgPublish msg = new MqttMsgPublish();
// get remaining length and allocate buffer
Int32 remainingLength = decodeRemainingLength(channel);
buffer = new Byte[remainingLength];
// read bytes from socket...
Int32 received = channel.Receive(buffer);
// topic name
topicUtf8Length = ((buffer[index++] << 8) & 0xFF00);
topicUtf8Length |= buffer[index++];
topicUtf8 = new Byte[topicUtf8Length];
Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length);
index += topicUtf8Length;
msg.Topic = new String(Encoding.UTF8.GetChars(topicUtf8));
// read QoS level from fixed header
msg.qosLevel = (Byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
// check wrong QoS level (both bits can't be set 1)
if (msg.qosLevel > QOS_LEVEL_EXACTLY_ONCE) {
throw new MqttClientException(MqttClientErrorCode.QosNotAllowed);
}
// read DUP flag from fixed header
msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
// read retain flag from fixed header
msg.retain = (((fixedHeaderFirstByte & RETAIN_FLAG_MASK) >> RETAIN_FLAG_OFFSET) == 0x01);
// message id is valid only with QOS level 1 or QOS level 2
if ((msg.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) ||
(msg.qosLevel == QOS_LEVEL_EXACTLY_ONCE)) {
// message id
msg.messageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]);
}
// get payload with message data
Int32 messageSize = remainingLength - index;
Int32 remaining = messageSize;
Int32 messageOffset = 0;
msg.Message = new Byte[messageSize];
// BUG FIX 26/07/2013 : receiving large payload
// copy first part of payload data received
Array.Copy(buffer, index, msg.Message, messageOffset, received - index);
remaining -= (received - index);
messageOffset += (received - index);
// if payload isn't finished
while (remaining > 0) {
// receive other payload data
received = channel.Receive(buffer);
Array.Copy(buffer, 0, msg.Message, messageOffset, received);
remaining -= received;
messageOffset += received;
}
return msg;
}
public override String ToString() {
#if TRACE
return this.GetTraceString(
"PUBLISH",
new Object[] { "messageId", "topic", "message" },
new Object[] { this.messageId, this.Topic, this.Message });
#else
return base.ToString();
#endif
}
}
}
@@ -1,111 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
using System;
#else
using Microsoft.SPOT;
#endif
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Event Args class for PUBLISH message received from broker
/// </summary>
public class MqttMsgPublishEventArgs : EventArgs
{
#region Properties...
/// <summary>
/// Message topic
/// </summary>
public string Topic
{
get { return this.topic; }
internal set { this.topic = value; }
}
/// <summary>
/// Message data
/// </summary>
public byte[] Message
{
get { return this.message; }
internal set { this.message = value; }
}
/// <summary>
/// Duplicate message flag
/// </summary>
public bool DupFlag
{
get { return this.dupFlag; }
set { this.dupFlag = value; }
}
/// <summary>
/// Quality of Service level
/// </summary>
public byte QosLevel
{
get { return this.qosLevel; }
internal set { this.qosLevel = value; }
}
/// <summary>
/// Retain message flag
/// </summary>
public bool Retain
{
get { return this.retain; }
internal set { this.retain = value; }
}
#endregion
// message topic
private string topic;
// message data
private byte[] message;
// duplicate delivery
private bool dupFlag;
// quality of service level
private byte qosLevel;
// retain flag
private bool retain;
/// <summary>
/// Constructor
/// </summary>
/// <param name="topic">Message topic</param>
/// <param name="message">Message data</param>
/// <param name="dupFlag">Duplicate delivery flag</param>
/// <param name="qosLevel">Quality of Service level</param>
/// <param name="retain">Retain flag</param>
public MqttMsgPublishEventArgs(string topic,
byte[] message,
bool dupFlag,
byte qosLevel,
bool retain)
{
this.topic = topic;
this.message = message;
this.dupFlag = dupFlag;
this.qosLevel = qosLevel;
this.retain = retain;
}
}
}
@@ -1,78 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
using System;
#else
using Microsoft.SPOT;
#endif
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Event Args class for published message
/// </summary>
public class MqttMsgPublishedEventArgs : EventArgs
{
#region Properties...
/// <summary>
/// Message identifier
/// </summary>
public ushort MessageId
{
get { return this.messageId; }
internal set { this.messageId = value; }
}
/// <summary>
/// Message published (or failed due to retries)
/// </summary>
public bool IsPublished
{
get { return this.isPublished; }
internal set { this.isPublished = value; }
}
#endregion
// message identifier
ushort messageId;
// published flag
bool isPublished;
/// <summary>
/// Constructor (published message)
/// </summary>
/// <param name="messageId">Message identifier published</param>
public MqttMsgPublishedEventArgs(ushort messageId)
: this(messageId, true)
{
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="messageId">Message identifier</param>
/// <param name="isPublished">Publish flag</param>
public MqttMsgPublishedEventArgs(ushort messageId, bool isPublished)
{
this.messageId = messageId;
this.isPublished = isPublished;
}
}
}
-125
View File
@@ -1,125 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Class for PUBREC message from broker to client
/// </summary>
public class MqttMsgPubrec : MqttMsgBase
{
/// <summary>
/// Constructor
/// </summary>
public MqttMsgPubrec()
{
this.type = MQTT_MSG_PUBREC_TYPE;
}
public override byte[] GetBytes(byte protocolVersion)
{
int fixedHeaderSize = 0;
int varHeaderSize = 0;
int payloadSize = 0;
int remainingLength = 0;
byte[] buffer;
int index = 0;
// message identifier
varHeaderSize += MESSAGE_ID_SIZE;
remainingLength += (varHeaderSize + payloadSize);
// first byte of fixed header
fixedHeaderSize = 1;
int temp = remainingLength;
// increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
do
{
fixedHeaderSize++;
temp = temp / 128;
} while (temp > 0);
// allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
buffer[index++] = (MQTT_MSG_PUBREC_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBREC_FLAG_BITS; // [v.3.1.1]
else
buffer[index++] = (MQTT_MSG_PUBREC_TYPE << MSG_TYPE_OFFSET);
// encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index);
// get message identifier
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB
return buffer;
}
/// <summary>
/// Parse bytes for a PUBREC message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>PUBREC message instance</returns>
public static MqttMsgPubrec Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{
byte[] buffer;
int index = 0;
MqttMsgPubrec msg = new MqttMsgPubrec();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBREC_FLAG_BITS)
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
buffer = new byte[remainingLength];
// read bytes from socket...
channel.Receive(buffer);
// message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]);
return msg;
}
public override string ToString()
{
#if TRACE
return this.GetTraceString(
"PUBREC",
new object[] { "messageId" },
new object[] { this.messageId });
#else
return base.ToString();
#endif
}
}
}
-142
View File
@@ -1,142 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Class for PUBREL message from client top broker
/// </summary>
public class MqttMsgPubrel : MqttMsgBase
{
/// <summary>
/// Constructor
/// </summary>
public MqttMsgPubrel()
{
this.type = MQTT_MSG_PUBREL_TYPE;
// PUBREL message use QoS Level 1 (not "officially" in 3.1.1)
this.qosLevel = QOS_LEVEL_AT_LEAST_ONCE;
}
public override byte[] GetBytes(byte protocolVersion)
{
int fixedHeaderSize = 0;
int varHeaderSize = 0;
int payloadSize = 0;
int remainingLength = 0;
byte[] buffer;
int index = 0;
// message identifier
varHeaderSize += MESSAGE_ID_SIZE;
remainingLength += (varHeaderSize + payloadSize);
// first byte of fixed header
fixedHeaderSize = 1;
int temp = remainingLength;
// increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
do
{
fixedHeaderSize++;
temp = temp / 128;
} while (temp > 0);
// allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
buffer[index++] = (MQTT_MSG_PUBREL_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBREL_FLAG_BITS; // [v.3.1.1]
else
{
buffer[index] = (byte)((MQTT_MSG_PUBREL_TYPE << MSG_TYPE_OFFSET) |
(this.qosLevel << QOS_LEVEL_OFFSET));
buffer[index] |= this.dupFlag ? (byte)(1 << DUP_FLAG_OFFSET) : (byte)0x00;
index++;
}
// encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index);
// get next message identifier
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB
return buffer;
}
/// <summary>
/// Parse bytes for a PUBREL message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>PUBREL message instance</returns>
public static MqttMsgPubrel Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{
byte[] buffer;
int index = 0;
MqttMsgPubrel msg = new MqttMsgPubrel();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBREL_FLAG_BITS)
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
buffer = new byte[remainingLength];
// read bytes from socket...
channel.Receive(buffer);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1)
{
// only 3.1.0
// read QoS level from fixed header (would be QoS Level 1)
msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
// read DUP flag from fixed header
msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
}
// message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]);
return msg;
}
public override string ToString()
{
#if TRACE
return this.GetTraceString(
"PUBREL",
new object[] { "messageId" },
new object[] { this.messageId });
#else
return base.ToString();
#endif
}
}
}
-162
View File
@@ -1,162 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Class for SUBACK message from broker to client
/// </summary>
public class MqttMsgSuback : MqttMsgBase
{
#region Properties...
/// <summary>
/// List of granted QOS Levels
/// </summary>
public byte[] GrantedQoSLevels
{
get { return this.grantedQosLevels; }
set { this.grantedQosLevels = value; }
}
#endregion
// granted QOS levels
byte[] grantedQosLevels;
/// <summary>
/// Constructor
/// </summary>
public MqttMsgSuback()
{
this.type = MQTT_MSG_SUBACK_TYPE;
}
/// <summary>
/// Parse bytes for a SUBACK message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>SUBACK message instance</returns>
public static MqttMsgSuback Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{
byte[] buffer;
int index = 0;
MqttMsgSuback msg = new MqttMsgSuback();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBACK_FLAG_BITS)
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
buffer = new byte[remainingLength];
// read bytes from socket...
channel.Receive(buffer);
// message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]);
// payload contains QoS levels granted
msg.grantedQosLevels = new byte[remainingLength - MESSAGE_ID_SIZE];
int qosIdx = 0;
do
{
msg.grantedQosLevels[qosIdx++] = buffer[index++];
} while (index < remainingLength);
return msg;
}
public override byte[] GetBytes(byte protocolVersion)
{
int fixedHeaderSize = 0;
int varHeaderSize = 0;
int payloadSize = 0;
int remainingLength = 0;
byte[] buffer;
int index = 0;
// message identifier
varHeaderSize += MESSAGE_ID_SIZE;
int grantedQosIdx = 0;
for (grantedQosIdx = 0; grantedQosIdx < this.grantedQosLevels.Length; grantedQosIdx++)
{
payloadSize++;
}
remainingLength += (varHeaderSize + payloadSize);
// first byte of fixed header
fixedHeaderSize = 1;
int temp = remainingLength;
// increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
do
{
fixedHeaderSize++;
temp = temp / 128;
} while (temp > 0);
// allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
buffer[index++] = (MQTT_MSG_SUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_SUBACK_FLAG_BITS; // [v.3.1.1]
else
buffer[index++] = (byte)(MQTT_MSG_SUBACK_TYPE << MSG_TYPE_OFFSET);
// encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index);
// message id
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB
// payload contains QoS levels granted
for (grantedQosIdx = 0; grantedQosIdx < this.grantedQosLevels.Length; grantedQosIdx++)
{
buffer[index++] = this.grantedQosLevels[grantedQosIdx];
}
return buffer;
}
public override string ToString()
{
#if TRACE
return this.GetTraceString(
"SUBACK",
new object[] { "messageId", "grantedQosLevels" },
new object[] { this.messageId, this.grantedQosLevels });
#else
return base.ToString();
#endif
}
}
}
-272
View File
@@ -1,272 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
// if NOT .Net Micro Framework
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
using System.Collections.Generic;
#endif
using System.Collections;
using System.Text;
using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Class for SUBSCRIBE message from client to broker
/// </summary>
public class MqttMsgSubscribe : MqttMsgBase
{
#region Properties...
/// <summary>
/// List of topics to subscribe
/// </summary>
public string[] Topics
{
get { return this.topics; }
set { this.topics = value; }
}
/// <summary>
/// List of QOS Levels related to topics
/// </summary>
public byte[] QoSLevels
{
get { return this.qosLevels; }
set { this.qosLevels = value; }
}
#endregion
// topics to subscribe
string[] topics;
// QOS levels related to topics
byte[] qosLevels;
/// <summary>
/// Constructor
/// </summary>
public MqttMsgSubscribe()
{
this.type = MQTT_MSG_SUBSCRIBE_TYPE;
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="topics">List of topics to subscribe</param>
/// <param name="qosLevels">List of QOS Levels related to topics</param>
public MqttMsgSubscribe(string[] topics, byte[] qosLevels)
{
this.type = MQTT_MSG_SUBSCRIBE_TYPE;
this.topics = topics;
this.qosLevels = qosLevels;
// SUBSCRIBE message uses QoS Level 1 (not "officially" in 3.1.1)
this.qosLevel = QOS_LEVEL_AT_LEAST_ONCE;
}
/// <summary>
/// Parse bytes for a SUBSCRIBE message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>SUBSCRIBE message instance</returns>
public static MqttMsgSubscribe Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{
byte[] buffer;
int index = 0;
byte[] topicUtf8;
int topicUtf8Length;
MqttMsgSubscribe msg = new MqttMsgSubscribe();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBSCRIBE_FLAG_BITS)
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
buffer = new byte[remainingLength];
// read bytes from socket...
int received = channel.Receive(buffer);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1)
{
// only 3.1.0
// read QoS level from fixed header
msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
// read DUP flag from fixed header
msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
// retain flag not used
msg.retain = false;
}
// message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]);
// payload contains topics and QoS levels
// NOTE : before, I don't know how many topics will be in the payload (so use List)
// if .Net Micro Framework
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
IList tmpTopics = new ArrayList();
IList tmpQosLevels = new ArrayList();
// else other frameworks (.Net, .Net Compact, Mono, Windows Phone)
#else
IList<String> tmpTopics = new List<String>();
IList<byte> tmpQosLevels = new List<byte>();
#endif
do
{
// topic name
topicUtf8Length = ((buffer[index++] << 8) & 0xFF00);
topicUtf8Length |= buffer[index++];
topicUtf8 = new byte[topicUtf8Length];
Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length);
index += topicUtf8Length;
tmpTopics.Add(new String(Encoding.UTF8.GetChars(topicUtf8)));
// QoS level
tmpQosLevels.Add(buffer[index++]);
} while (index < remainingLength);
// copy from list to array
msg.topics = new string[tmpTopics.Count];
msg.qosLevels = new byte[tmpQosLevels.Count];
for (int i = 0; i < tmpTopics.Count; i++)
{
msg.topics[i] = (string)tmpTopics[i];
msg.qosLevels[i] = (byte)tmpQosLevels[i];
}
return msg;
}
public override byte[] GetBytes(byte protocolVersion)
{
int fixedHeaderSize = 0;
int varHeaderSize = 0;
int payloadSize = 0;
int remainingLength = 0;
byte[] buffer;
int index = 0;
// topics list empty
if ((this.topics == null) || (this.topics.Length == 0))
throw new MqttClientException(MqttClientErrorCode.TopicsEmpty);
// qos levels list empty
if ((this.qosLevels == null) || (this.qosLevels.Length == 0))
throw new MqttClientException(MqttClientErrorCode.QosLevelsEmpty);
// topics and qos levels lists length don't match
if (this.topics.Length != this.qosLevels.Length)
throw new MqttClientException(MqttClientErrorCode.TopicsQosLevelsNotMatch);
// message identifier
varHeaderSize += MESSAGE_ID_SIZE;
int topicIdx = 0;
byte[][] topicsUtf8 = new byte[this.topics.Length][];
for (topicIdx = 0; topicIdx < this.topics.Length; topicIdx++)
{
// check topic length
if ((this.topics[topicIdx].Length < MIN_TOPIC_LENGTH) || (this.topics[topicIdx].Length > MAX_TOPIC_LENGTH))
throw new MqttClientException(MqttClientErrorCode.TopicLength);
topicsUtf8[topicIdx] = Encoding.UTF8.GetBytes(this.topics[topicIdx]);
payloadSize += 2; // topic size (MSB, LSB)
payloadSize += topicsUtf8[topicIdx].Length;
payloadSize++; // byte for QoS
}
remainingLength += (varHeaderSize + payloadSize);
// first byte of fixed header
fixedHeaderSize = 1;
int temp = remainingLength;
// increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
do
{
fixedHeaderSize++;
temp = temp / 128;
} while (temp > 0);
// allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
buffer[index++] = (MQTT_MSG_SUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_SUBSCRIBE_FLAG_BITS; // [v.3.1.1]
else
{
buffer[index] = (byte)((MQTT_MSG_SUBSCRIBE_TYPE << MSG_TYPE_OFFSET) |
(this.qosLevel << QOS_LEVEL_OFFSET));
buffer[index] |= this.dupFlag ? (byte)(1 << DUP_FLAG_OFFSET) : (byte)0x00;
index++;
}
// encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index);
// check message identifier assigned (SUBSCRIBE uses QoS Level 1, so message id is mandatory)
if (this.messageId == 0)
throw new MqttClientException(MqttClientErrorCode.WrongMessageId);
buffer[index++] = (byte)((messageId >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(messageId & 0x00FF); // LSB
topicIdx = 0;
for (topicIdx = 0; topicIdx < this.topics.Length; topicIdx++)
{
// topic name
buffer[index++] = (byte)((topicsUtf8[topicIdx].Length >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(topicsUtf8[topicIdx].Length & 0x00FF); // LSB
Array.Copy(topicsUtf8[topicIdx], 0, buffer, index, topicsUtf8[topicIdx].Length);
index += topicsUtf8[topicIdx].Length;
// requested QoS
buffer[index++] = this.qosLevels[topicIdx];
}
return buffer;
}
public override string ToString()
{
#if TRACE
return this.GetTraceString(
"SUBSCRIBE",
new object[] { "messageId", "topics", "qosLevels" },
new object[] { this.messageId, this.topics, this.qosLevels });
#else
return base.ToString();
#endif
}
}
}
@@ -1,81 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
using System;
#else
using Microsoft.SPOT;
#endif
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Event Args class for subscribe request on topics
/// </summary>
public class MqttMsgSubscribeEventArgs : EventArgs
{
#region Properties...
/// <summary>
/// Message identifier
/// </summary>
public ushort MessageId
{
get { return this.messageId; }
internal set { this.messageId = value; }
}
/// <summary>
/// Topics requested to subscribe
/// </summary>
public string[] Topics
{
get { return this.topics; }
internal set { this.topics = value; }
}
/// <summary>
/// List of QOS Levels requested
/// </summary>
public byte[] QoSLevels
{
get { return this.qosLevels; }
internal set { this.qosLevels = value; }
}
#endregion
// message identifier
ushort messageId;
// topics requested to subscribe
string[] topics;
// QoS levels requested
byte[] qosLevels;
/// <summary>
/// Constructor
/// </summary>
/// <param name="messageId">Message identifier for subscribe topics request</param>
/// <param name="topics">Topics requested to subscribe</param>
/// <param name="qosLevels">List of QOS Levels requested</param>
public MqttMsgSubscribeEventArgs(ushort messageId, string[] topics, byte[] qosLevels)
{
this.messageId = messageId;
this.topics = topics;
this.qosLevels = qosLevels;
}
}
}
@@ -1,68 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
using System;
#else
using Microsoft.SPOT;
#endif
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Event Args class for subscribed topics
/// </summary>
public class MqttMsgSubscribedEventArgs : EventArgs
{
#region Properties...
/// <summary>
/// Message identifier
/// </summary>
public ushort MessageId
{
get { return this.messageId; }
internal set { this.messageId = value; }
}
/// <summary>
/// List of granted QOS Levels
/// </summary>
public byte[] GrantedQoSLevels
{
get { return this.grantedQosLevels; }
internal set { this.grantedQosLevels = value; }
}
#endregion
// message identifier
ushort messageId;
// granted QOS levels
byte[] grantedQosLevels;
/// <summary>
/// Constructor
/// </summary>
/// <param name="messageId">Message identifier for subscribed topics</param>
/// <param name="grantedQosLevels">List of granted QOS Levels</param>
public MqttMsgSubscribedEventArgs(ushort messageId, byte[] grantedQosLevels)
{
this.messageId = messageId;
this.grantedQosLevels = grantedQosLevels;
}
}
}
-126
View File
@@ -1,126 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Class for UNSUBACK message from broker to client
/// </summary>
public class MqttMsgUnsuback : MqttMsgBase
{
/// <summary>
/// Constructor
/// </summary>
public MqttMsgUnsuback()
{
this.type = MQTT_MSG_UNSUBACK_TYPE;
}
/// <summary>
/// Parse bytes for a UNSUBACK message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>UNSUBACK message instance</returns>
public static MqttMsgUnsuback Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{
byte[] buffer;
int index = 0;
MqttMsgUnsuback msg = new MqttMsgUnsuback();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBACK_FLAG_BITS)
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
buffer = new byte[remainingLength];
// read bytes from socket...
channel.Receive(buffer);
// message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]);
return msg;
}
public override byte[] GetBytes(byte protocolVersion)
{
int fixedHeaderSize = 0;
int varHeaderSize = 0;
int payloadSize = 0;
int remainingLength = 0;
byte[] buffer;
int index = 0;
// message identifier
varHeaderSize += MESSAGE_ID_SIZE;
remainingLength += (varHeaderSize + payloadSize);
// first byte of fixed header
fixedHeaderSize = 1;
int temp = remainingLength;
// increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
do
{
fixedHeaderSize++;
temp = temp / 128;
} while (temp > 0);
// allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
buffer[index++] = (MQTT_MSG_UNSUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_UNSUBACK_FLAG_BITS; // [v.3.1.1]
else
buffer[index++] = (byte)(MQTT_MSG_UNSUBACK_TYPE << MSG_TYPE_OFFSET);
// encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index);
// message id
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB
return buffer;
}
public override string ToString()
{
#if TRACE
return this.GetTraceString(
"UNSUBACK",
new object[] { "messageId" },
new object[] { this.messageId });
#else
return base.ToString();
#endif
}
}
}
-239
View File
@@ -1,239 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
// if NOT .Net Micro Framework
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
using System.Collections.Generic;
#endif
using System.Collections;
using System.Text;
using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Class for UNSUBSCRIBE message from client to broker
/// </summary>
public class MqttMsgUnsubscribe : MqttMsgBase
{
#region Properties...
/// <summary>
/// List of topics to unsubscribe
/// </summary>
public string[] Topics
{
get { return this.topics; }
set { this.topics = value; }
}
#endregion
// topics to unsubscribe
string[] topics;
/// <summary>
/// Constructor
/// </summary>
public MqttMsgUnsubscribe()
{
this.type = MQTT_MSG_UNSUBSCRIBE_TYPE;
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="topics">List of topics to unsubscribe</param>
public MqttMsgUnsubscribe(string[] topics)
{
this.type = MQTT_MSG_UNSUBSCRIBE_TYPE;
this.topics = topics;
// UNSUBSCRIBE message uses QoS Level 1 (not "officially" in 3.1.1)
this.qosLevel = QOS_LEVEL_AT_LEAST_ONCE;
}
/// <summary>
/// Parse bytes for a UNSUBSCRIBE message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>UNSUBSCRIBE message instance</returns>
public static MqttMsgUnsubscribe Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{
byte[] buffer;
int index = 0;
byte[] topicUtf8;
int topicUtf8Length;
MqttMsgUnsubscribe msg = new MqttMsgUnsubscribe();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBSCRIBE_FLAG_BITS)
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
buffer = new byte[remainingLength];
// read bytes from socket...
int received = channel.Receive(buffer);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1)
{
// only 3.1.0
// read QoS level from fixed header
msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
// read DUP flag from fixed header
msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
// retain flag not used
msg.retain = false;
}
// message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]);
// payload contains topics
// NOTE : before, I don't know how many topics will be in the payload (so use List)
// if .Net Micro Framework
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
IList tmpTopics = new ArrayList();
// else other frameworks (.Net, .Net Compact, Mono, Windows Phone)
#else
IList<String> tmpTopics = new List<String>();
#endif
do
{
// topic name
topicUtf8Length = ((buffer[index++] << 8) & 0xFF00);
topicUtf8Length |= buffer[index++];
topicUtf8 = new byte[topicUtf8Length];
Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length);
index += topicUtf8Length;
tmpTopics.Add(new String(Encoding.UTF8.GetChars(topicUtf8)));
} while (index < remainingLength);
// copy from list to array
msg.topics = new string[tmpTopics.Count];
for (int i = 0; i < tmpTopics.Count; i++)
{
msg.topics[i] = (string)tmpTopics[i];
}
return msg;
}
public override byte[] GetBytes(byte protocolVersion)
{
int fixedHeaderSize = 0;
int varHeaderSize = 0;
int payloadSize = 0;
int remainingLength = 0;
byte[] buffer;
int index = 0;
// topics list empty
if ((this.topics == null) || (this.topics.Length == 0))
throw new MqttClientException(MqttClientErrorCode.TopicsEmpty);
// message identifier
varHeaderSize += MESSAGE_ID_SIZE;
int topicIdx = 0;
byte[][] topicsUtf8 = new byte[this.topics.Length][];
for (topicIdx = 0; topicIdx < this.topics.Length; topicIdx++)
{
// check topic length
if ((this.topics[topicIdx].Length < MIN_TOPIC_LENGTH) || (this.topics[topicIdx].Length > MAX_TOPIC_LENGTH))
throw new MqttClientException(MqttClientErrorCode.TopicLength);
topicsUtf8[topicIdx] = Encoding.UTF8.GetBytes(this.topics[topicIdx]);
payloadSize += 2; // topic size (MSB, LSB)
payloadSize += topicsUtf8[topicIdx].Length;
}
remainingLength += (varHeaderSize + payloadSize);
// first byte of fixed header
fixedHeaderSize = 1;
int temp = remainingLength;
// increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
do
{
fixedHeaderSize++;
temp = temp / 128;
} while (temp > 0);
// allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
buffer[index++] = (MQTT_MSG_UNSUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_UNSUBSCRIBE_FLAG_BITS; // [v.3.1.1]
else
{
buffer[index] = (byte)((MQTT_MSG_UNSUBSCRIBE_TYPE << MSG_TYPE_OFFSET) |
(this.qosLevel << QOS_LEVEL_OFFSET));
buffer[index] |= this.dupFlag ? (byte)(1 << DUP_FLAG_OFFSET) : (byte)0x00;
index++;
}
// encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index);
// check message identifier assigned
if (this.messageId == 0)
throw new MqttClientException(MqttClientErrorCode.WrongMessageId);
buffer[index++] = (byte)((messageId >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(messageId & 0x00FF); // LSB
topicIdx = 0;
for (topicIdx = 0; topicIdx < this.topics.Length; topicIdx++)
{
// topic name
buffer[index++] = (byte)((topicsUtf8[topicIdx].Length >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(topicsUtf8[topicIdx].Length & 0x00FF); // LSB
Array.Copy(topicsUtf8[topicIdx], 0, buffer, index, topicsUtf8[topicIdx].Length);
index += topicsUtf8[topicIdx].Length;
}
return buffer;
}
public override string ToString()
{
#if TRACE
return this.GetTraceString(
"UNSUBSCRIBE",
new object[] { "messageId", "topics" },
new object[] { this.messageId, this.topics });
#else
return base.ToString();
#endif
}
}
}
@@ -1,68 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
using System;
#else
using Microsoft.SPOT;
#endif
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Event Args class for unsubscribe request on topics
/// </summary>
public class MqttMsgUnsubscribeEventArgs : EventArgs
{
#region Properties...
/// <summary>
/// Message identifier
/// </summary>
public ushort MessageId
{
get { return this.messageId; }
internal set { this.messageId = value; }
}
/// <summary>
/// Topics requested to subscribe
/// </summary>
public string[] Topics
{
get { return this.topics; }
internal set { this.topics = value; }
}
#endregion
// message identifier
ushort messageId;
// topics requested to unsubscribe
string[] topics;
/// <summary>
/// Constructor
/// </summary>
/// <param name="messageId">Message identifier for subscribed topics</param>
/// <param name="topics">Topics requested to subscribe</param>
public MqttMsgUnsubscribeEventArgs(ushort messageId, string[] topics)
{
this.messageId = messageId;
this.topics = topics;
}
}
}
@@ -1,55 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
using System;
#else
using Microsoft.SPOT;
#endif
namespace uPLibrary.Networking.M2Mqtt.Messages
{
/// <summary>
/// Event Args class for unsubscribed topic
/// </summary>
public class MqttMsgUnsubscribedEventArgs : EventArgs
{
#region Properties...
/// <summary>
/// Message identifier
/// </summary>
public ushort MessageId
{
get { return this.messageId; }
internal set { this.messageId = value; }
}
#endregion
// message identifier
ushort messageId;
/// <summary>
/// Constructor
/// </summary>
/// <param name="messageId">Message identifier for unsubscribed topic</param>
public MqttMsgUnsubscribedEventArgs(ushort messageId)
{
this.messageId = messageId;
}
}
}
File diff suppressed because it is too large Load Diff
-30
View File
@@ -1,30 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
namespace uPLibrary.Networking.M2Mqtt
{
/// <summary>
/// Supported SSL/TLS protocol versions
/// </summary>
public enum MqttSslProtocols
{
None,
SSLv3,
TLSv1_0,
TLSv1_1,
TLSv1_2
}
}
-104
View File
@@ -1,104 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
namespace uPLibrary.Networking.M2Mqtt
{
/// <summary>
/// Settings class for the MQTT broker
/// </summary>
public class MqttSettings
{
// default port for MQTT protocol
public const int MQTT_BROKER_DEFAULT_PORT = 1883;
public const int MQTT_BROKER_DEFAULT_SSL_PORT = 8883;
// default timeout on receiving from client
public const int MQTT_DEFAULT_TIMEOUT = 30000;
// max publish, subscribe and unsubscribe retry for QoS Level 1 or 2
public const int MQTT_ATTEMPTS_RETRY = 3;
// delay for retry publish, subscribe and unsubscribe for QoS Level 1 or 2
public const int MQTT_DELAY_RETRY = 10000;
// broker need to receive the first message (CONNECT)
// within a reasonable amount of time after TCP/IP connection
public const int MQTT_CONNECT_TIMEOUT = 30000;
// default inflight queue size
public const int MQTT_MAX_INFLIGHT_QUEUE_SIZE = int.MaxValue;
/// <summary>
/// Listening connection port
/// </summary>
public int Port { get; internal set; }
/// <summary>
/// Listening connection SSL port
/// </summary>
public int SslPort { get; internal set; }
/// <summary>
/// Timeout on client connection (before receiving CONNECT message)
/// </summary>
public int TimeoutOnConnection { get; internal set; }
/// <summary>
/// Timeout on receiving
/// </summary>
public int TimeoutOnReceiving { get; internal set; }
/// <summary>
/// Attempts on retry
/// </summary>
public int AttemptsOnRetry { get; internal set; }
/// <summary>
/// Delay on retry
/// </summary>
public int DelayOnRetry { get; internal set; }
/// <summary>
/// Inflight queue size
/// </summary>
public int InflightQueueSize { get; set; }
/// <summary>
/// Singleton instance of settings
/// </summary>
public static MqttSettings Instance
{
get
{
if (instance == null)
instance = new MqttSettings();
return instance;
}
}
// singleton instance
private static MqttSettings instance;
/// <summary>
/// Constructor
/// </summary>
private MqttSettings()
{
this.Port = MQTT_BROKER_DEFAULT_PORT;
this.SslPort = MQTT_BROKER_DEFAULT_SSL_PORT;
this.TimeoutOnReceiving = MQTT_DEFAULT_TIMEOUT;
this.AttemptsOnRetry = MQTT_ATTEMPTS_RETRY;
this.DelayOnRetry = MQTT_DELAY_RETRY;
this.TimeoutOnConnection = MQTT_CONNECT_TIMEOUT;
this.InflightQueueSize = MQTT_MAX_INFLIGHT_QUEUE_SIZE;
}
}
}
-36
View File
@@ -1,36 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System.Threading;
namespace uPLibrary.Networking.M2Mqtt
{
/// <summary>
/// Support methods fos specific framework
/// </summary>
public class Fx
{
public static void StartThread(ThreadStart threadStart)
{
new Thread(threadStart).Start();
}
public static void SleepThread(int millisecondsTimeout)
{
Thread.Sleep(millisecondsTimeout);
}
}
}
-472
View File
@@ -1,472 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
#if SSL
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
using Microsoft.SPOT.Net.Security;
#else
using System.Net.Security;
using System.Security.Authentication;
#endif
#endif
using System.Net.Sockets;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System;
//using System.Security.Authentication;
//using System.Net.Security;
namespace uPLibrary.Networking.M2Mqtt
{
/// <summary>
/// Channel to communicate over the network
/// </summary>
public class MqttNetworkChannel : IMqttNetworkChannel
{
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
private readonly RemoteCertificateValidationCallback userCertificateValidationCallback;
private readonly LocalCertificateSelectionCallback userCertificateSelectionCallback;
#endif
// remote host information
private string remoteHostName;
private IPAddress remoteIpAddress;
private int remotePort;
// socket for communication
private Socket socket;
// using SSL
private bool secure;
// CA certificate (on client)
private X509Certificate caCert;
// Server certificate (on broker)
private X509Certificate serverCert;
// client certificate (on client)
private X509Certificate clientCert;
// SSL/TLS protocol version
private MqttSslProtocols sslProtocol;
/// <summary>
/// Remote host name
/// </summary>
public string RemoteHostName { get { return this.remoteHostName; } }
/// <summary>
/// Remote IP address
/// </summary>
public IPAddress RemoteIpAddress { get { return this.remoteIpAddress; } }
/// <summary>
/// Remote port
/// </summary>
public int RemotePort { get { return this.remotePort; } }
#if SSL
// SSL stream
private SslStream sslStream;
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
private NetworkStream netStream;
#endif
#endif
/// <summary>
/// Data available on the channel
/// </summary>
public bool DataAvailable
{
get
{
#if SSL
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
if (secure)
return this.sslStream.DataAvailable;
else
return (this.socket.Available > 0);
#else
if (secure)
return this.netStream.DataAvailable;
else
return (this.socket.Available > 0);
#endif
#else
return (this.socket.Available > 0);
#endif
}
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="socket">Socket opened with the client</param>
public MqttNetworkChannel(Socket socket)
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
: this(socket, false, null, MqttSslProtocols.None, null, null)
#else
: this(socket, false, null, MqttSslProtocols.None)
#endif
{
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="socket">Socket opened with the client</param>
/// <param name="secure">Secure connection (SSL/TLS)</param>
/// <param name="serverCert">Server X509 certificate for secure connection</param>
/// <param name="sslProtocol">SSL/TLS protocol version</param>
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
/// <param name="userCertificateSelectionCallback">A RemoteCertificateValidationCallback delegate responsible for validating the certificate supplied by the remote party</param>
/// <param name="userCertificateValidationCallback">A LocalCertificateSelectionCallback delegate responsible for selecting the certificate used for authentication</param>
public MqttNetworkChannel(Socket socket, bool secure, X509Certificate serverCert, MqttSslProtocols sslProtocol,
RemoteCertificateValidationCallback userCertificateValidationCallback,
LocalCertificateSelectionCallback userCertificateSelectionCallback)
#else
public MqttNetworkChannel(Socket socket, bool secure, X509Certificate serverCert, MqttSslProtocols sslProtocol)
#endif
{
this.socket = socket;
this.secure = secure;
this.serverCert = serverCert;
this.sslProtocol = sslProtocol;
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
this.userCertificateValidationCallback = userCertificateValidationCallback;
this.userCertificateSelectionCallback = userCertificateSelectionCallback;
#endif
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="remoteHostName">Remote Host name</param>
/// <param name="remotePort">Remote port</param>
public MqttNetworkChannel(string remoteHostName, int remotePort)
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
: this(remoteHostName, remotePort, false, null, null, MqttSslProtocols.None, null, null)
#else
: this(remoteHostName, remotePort, false, null, null, MqttSslProtocols.None)
#endif
{
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="remoteHostName">Remote Host name</param>
/// <param name="remotePort">Remote port</param>
/// <param name="secure">Using SSL</param>
/// <param name="caCert">CA certificate</param>
/// <param name="clientCert">Client certificate</param>
/// <param name="sslProtocol">SSL/TLS protocol version</param>
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
/// <param name="userCertificateSelectionCallback">A RemoteCertificateValidationCallback delegate responsible for validating the certificate supplied by the remote party</param>
/// <param name="userCertificateValidationCallback">A LocalCertificateSelectionCallback delegate responsible for selecting the certificate used for authentication</param>
public MqttNetworkChannel(string remoteHostName, int remotePort, bool secure, X509Certificate caCert, X509Certificate clientCert, MqttSslProtocols sslProtocol,
RemoteCertificateValidationCallback userCertificateValidationCallback,
LocalCertificateSelectionCallback userCertificateSelectionCallback)
#else
public MqttNetworkChannel(string remoteHostName, int remotePort, bool secure, X509Certificate caCert, X509Certificate clientCert, MqttSslProtocols sslProtocol)
#endif
{
IPAddress remoteIpAddress = null;
try
{
// check if remoteHostName is a valid IP address and get it
remoteIpAddress = IPAddress.Parse(remoteHostName);
}
catch
{
}
// in this case the parameter remoteHostName isn't a valid IP address
if (remoteIpAddress == null)
{
IPHostEntry hostEntry = Dns.GetHostEntry(remoteHostName);
if ((hostEntry != null) && (hostEntry.AddressList.Length > 0))
{
// check for the first address not null
// it seems that with .Net Micro Framework, the IPV6 addresses aren't supported and return "null"
int i = 0;
while (hostEntry.AddressList[i] == null) i++;
remoteIpAddress = hostEntry.AddressList[i];
}
else
{
throw new Exception("No address found for the remote host name");
}
}
this.remoteHostName = remoteHostName;
this.remoteIpAddress = remoteIpAddress;
this.remotePort = remotePort;
this.secure = secure;
this.caCert = caCert;
this.clientCert = clientCert;
this.sslProtocol = sslProtocol;
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
this.userCertificateValidationCallback = userCertificateValidationCallback;
this.userCertificateSelectionCallback = userCertificateSelectionCallback;
#endif
}
/// <summary>
/// Connect to remote server
/// </summary>
public void Connect()
{
this.socket = new Socket(IPAddressUtility.GetAddressFamily(this.remoteIpAddress), SocketType.Stream, ProtocolType.Tcp);
// try connection to the broker
this.socket.Connect(new IPEndPoint(this.remoteIpAddress, this.remotePort));
#if SSL
// secure channel requested
if (secure)
{
// create SSL stream
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
this.sslStream = new SslStream(this.socket);
#else
this.netStream = new NetworkStream(this.socket);
this.sslStream = new SslStream(this.netStream, false, this.userCertificateValidationCallback, this.userCertificateSelectionCallback);
#endif
// server authentication (SSL/TLS handshake)
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
this.sslStream.AuthenticateAsClient(this.remoteHostName,
this.clientCert,
new X509Certificate[] { this.caCert },
SslVerification.CertificateRequired,
MqttSslUtility.ToSslPlatformEnum(this.sslProtocol));
#else
X509CertificateCollection clientCertificates = null;
// check if there is a client certificate to add to the collection, otherwise it's null (as empty)
if (this.clientCert != null)
clientCertificates = new X509CertificateCollection(new X509Certificate[] { this.clientCert });
this.sslStream.AuthenticateAsClient(this.remoteHostName,
clientCertificates,
MqttSslUtility.ToSslPlatformEnum(this.sslProtocol),
false);
#endif
}
#endif
}
/// <summary>
/// Send data on the network channel
/// </summary>
/// <param name="buffer">Data buffer to send</param>
/// <returns>Number of byte sent</returns>
public int Send(byte[] buffer)
{
#if SSL
if (this.secure)
{
this.sslStream.Write(buffer, 0, buffer.Length);
this.sslStream.Flush();
return buffer.Length;
}
else
return this.socket.Send(buffer, 0, buffer.Length, SocketFlags.None);
#else
return this.socket.Send(buffer, 0, buffer.Length, SocketFlags.None);
#endif
}
/// <summary>
/// Receive data from the network
/// </summary>
/// <param name="buffer">Data buffer for receiving data</param>
/// <returns>Number of bytes received</returns>
public int Receive(byte[] buffer)
{
#if SSL
if (this.secure)
{
// read all data needed (until fill buffer)
int idx = 0, read = 0;
while (idx < buffer.Length)
{
// fixed scenario with socket closed gracefully by peer/broker and
// Read return 0. Avoid infinite loop.
read = this.sslStream.Read(buffer, idx, buffer.Length - idx);
if (read == 0)
return 0;
idx += read;
}
return buffer.Length;
}
else
{
// read all data needed (until fill buffer)
int idx = 0, read = 0;
while (idx < buffer.Length)
{
// fixed scenario with socket closed gracefully by peer/broker and
// Read return 0. Avoid infinite loop.
read = this.socket.Receive(buffer, idx, buffer.Length - idx, SocketFlags.None);
if (read == 0)
return 0;
idx += read;
}
return buffer.Length;
}
#else
// read all data needed (until fill buffer)
int idx = 0, read = 0;
while (idx < buffer.Length)
{
// fixed scenario with socket closed gracefully by peer/broker and
// Read return 0. Avoid infinite loop.
read = this.socket.Receive(buffer, idx, buffer.Length - idx, SocketFlags.None);
if (read == 0)
return 0;
idx += read;
}
return buffer.Length;
#endif
}
/// <summary>
/// Receive data from the network channel with a specified timeout
/// </summary>
/// <param name="buffer">Data buffer for receiving data</param>
/// <param name="timeout">Timeout on receiving (in milliseconds)</param>
/// <returns>Number of bytes received</returns>
public int Receive(byte[] buffer, int timeout)
{
// check data availability (timeout is in microseconds)
if (this.socket.Poll(timeout * 1000, SelectMode.SelectRead))
{
return this.Receive(buffer);
}
else
{
return 0;
}
}
/// <summary>
/// Close the network channel
/// </summary>
public void Close()
{
#if SSL
if (this.secure)
{
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
this.netStream.Close();
#endif
this.sslStream.Close();
}
this.socket.Close();
#else
this.socket.Close();
#endif
}
/// <summary>
/// Accept connection from a remote client
/// </summary>
public void Accept()
{
#if SSL
// secure channel requested
if (secure)
{
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
this.netStream = new NetworkStream(this.socket);
this.sslStream = new SslStream(this.netStream, false, this.userCertificateValidationCallback, this.userCertificateSelectionCallback);
this.sslStream.AuthenticateAsServer(this.serverCert, false, MqttSslUtility.ToSslPlatformEnum(this.sslProtocol), false);
#endif
}
return;
#else
return;
#endif
}
}
/// <summary>
/// IPAddress Utility class
/// </summary>
public static class IPAddressUtility
{
/// <summary>
/// Return AddressFamily for the IP address
/// </summary>
/// <param name="ipAddress">IP address to check</param>
/// <returns>Address family</returns>
public static AddressFamily GetAddressFamily(IPAddress ipAddress)
{
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
return ipAddress.AddressFamily;
#else
return (ipAddress.ToString().IndexOf(':') != -1) ?
AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork;
#endif
}
}
/// <summary>
/// MQTT SSL utility class
/// </summary>
public static class MqttSslUtility
{
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3 && !COMPACT_FRAMEWORK)
public static SslProtocols ToSslPlatformEnum(MqttSslProtocols mqttSslProtocol)
{
switch (mqttSslProtocol)
{
case MqttSslProtocols.None:
return SslProtocols.None;
case MqttSslProtocols.SSLv3:
return SslProtocols.Ssl3;
case MqttSslProtocols.TLSv1_0:
return SslProtocols.Tls;
/*case MqttSslProtocols.TLSv1_1:
return SslProtocols.Tls11;
case MqttSslProtocols.TLSv1_2:
return SslProtocols.Tls12;*/
default:
throw new ArgumentException("SSL/TLS protocol version not supported");
}
}
#elif (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
public static SslProtocols ToSslPlatformEnum(MqttSslProtocols mqttSslProtocol)
{
switch (mqttSslProtocol)
{
case MqttSslProtocols.None:
return SslProtocols.None;
case MqttSslProtocols.SSLv3:
return SslProtocols.SSLv3;
case MqttSslProtocols.TLSv1_0:
return SslProtocols.TLSv1;
case MqttSslProtocols.TLSv1_1:
case MqttSslProtocols.TLSv1_2:
default:
throw new ArgumentException("SSL/TLS protocol version not supported");
}
}
#endif
}
}
-44
View File
@@ -1,44 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("M2Mqtt")]
[assembly: AssemblyDescription("MQTT Client Library for M2M communication")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Paolo Patierno")]
[assembly: AssemblyProduct("M2Mqtt")]
[assembly: AssemblyCopyright("Copyright © Paolo Patierno 2014")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("4.3.0.0")]
// to avoid compilation error (AssemblyFileVersionAttribute doesn't exist) under .Net CF 3.5
#if !WindowsCE
[assembly: AssemblyFileVersion("4.3.0.0")]
#endif
-65
View File
@@ -1,65 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
#if BROKER
using System.Collections;
using System.Collections.Generic;
using uPLibrary.Networking.M2Mqtt.Managers;
using uPLibrary.Networking.M2Mqtt.Messages;
namespace uPLibrary.Networking.M2Mqtt.Session
{
/// <summary>
/// MQTT Broker Session
/// </summary>
public class MqttBrokerSession : MqttSession
{
/// <summary>
/// Client related to the subscription
/// </summary>
public MqttClient Client { get; set; }
/// <summary>
/// Subscriptions for the client session
/// </summary>
public List<MqttSubscription> Subscriptions;
/// <summary>
/// Outgoing messages to publish
/// </summary>
public Queue<MqttMsgPublish> OutgoingMessages;
/// <summary>
/// Constructor
/// </summary>
public MqttBrokerSession()
: base()
{
this.Client = null;
this.Subscriptions = new List<MqttSubscription>();
this.OutgoingMessages = new Queue<MqttMsgPublish>();
}
public override void Clear()
{
base.Clear();
this.Client = null;
this.Subscriptions.Clear();
this.OutgoingMessages.Clear();
}
}
}
#endif
-33
View File
@@ -1,33 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
namespace uPLibrary.Networking.M2Mqtt.Session
{
/// <summary>
/// MQTT Client Session
/// </summary>
public class MqttClientSession : MqttSession
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="clientId">Client Id to create session</param>
public MqttClientSession(string clientId)
: base(clientId)
{
}
}
}
-63
View File
@@ -1,63 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System.Collections;
namespace uPLibrary.Networking.M2Mqtt.Session
{
/// <summary>
/// MQTT Session base class
/// </summary>
public abstract class MqttSession
{
/// <summary>
/// Client Id
/// </summary>
public string ClientId { get; set; }
/// <summary>
/// Messages inflight during session
/// </summary>
public Hashtable InflightMessages { get; set; }
/// <summary>
/// Constructor
/// </summary>
public MqttSession()
: this(null)
{
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="clientId">Client Id to create session</param>
public MqttSession(string clientId)
{
this.ClientId = clientId;
this.InflightMessages = new Hashtable();
}
/// <summary>
/// Clean session
/// </summary>
public virtual void Clear()
{
this.ClientId = null;
this.InflightMessages.Clear();
}
}
}
-50
View File
@@ -1,50 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
using System.Collections;
namespace uPLibrary.Networking.M2Mqtt.Utility
{
/// <summary>
/// Extension class for a Queue
/// </summary>
internal static class QueueExtension
{
/// <summary>
/// Predicate for searching inside a queue
/// </summary>
/// <param name="item">Item of the queue</param>
/// <returns>Result of predicate</returns>
internal delegate bool QueuePredicate(object item);
/// <summary>
/// Get (without removing) an item from queue based on predicate
/// </summary>
/// <param name="queue">Queue in which to search</param>
/// <param name="predicate">Predicate to verify to get item</param>
/// <returns>Item matches the predicate</returns>
internal static object Get(Queue queue, QueuePredicate predicate)
{
foreach (var item in queue)
{
if (predicate(item))
return item;
}
return null;
}
}
}
-86
View File
@@ -1,86 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System.Diagnostics;
namespace uPLibrary.Networking.M2Mqtt.Utility
{
/// <summary>
/// Tracing levels
/// </summary>
public enum TraceLevel
{
Error = 0x01,
Warning = 0x02,
Information = 0x04,
Verbose = 0x0F,
Frame = 0x10,
Queuing = 0x20
}
// delegate for writing trace
public delegate void WriteTrace(string format, params object[] args);
/// <summary>
/// Tracing class
/// </summary>
public static class Trace
{
public static TraceLevel TraceLevel;
public static WriteTrace TraceListener;
[Conditional("DEBUG")]
public static void Debug(string format, params object[] args)
{
if (TraceListener != null)
{
TraceListener(format, args);
}
}
public static void WriteLine(TraceLevel level, string format)
{
if (TraceListener != null && (level & TraceLevel) > 0)
{
TraceListener(format);
}
}
public static void WriteLine(TraceLevel level, string format, object arg1)
{
if (TraceListener != null && (level & TraceLevel) > 0)
{
TraceListener(format, arg1);
}
}
public static void WriteLine(TraceLevel level, string format, object arg1, object arg2)
{
if (TraceListener != null && (level & TraceLevel) > 0)
{
TraceListener(format, arg1, arg2);
}
}
public static void WriteLine(TraceLevel level, string format, object arg1, object arg2, object arg3)
{
if (TraceListener != null && (level & TraceLevel) > 0)
{
TraceListener(format, arg1, arg2, arg3);
}
}
}
}
-36
View File
@@ -1,36 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System.Threading;
using System.Threading.Tasks;
namespace uPLibrary.Networking.M2Mqtt
{
/// <summary>
/// Support methods fos specific framework
/// </summary>
public class Fx
{
public delegate void ThreadStart();
public static void StartThread(ThreadStart threadStart)
{
Task.Factory.StartNew(o => ((ThreadStart)o)(), threadStart);
}
public static void SleepThread(int millisecondsTimeout) { Task.Delay(millisecondsTimeout).RunSynchronously(); }
}
}
-27
View File
@@ -1,27 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System.Collections.Generic;
namespace uPLibrary.Networking.M2Mqtt
{
/// <summary>
/// Wrapper Hashtable class for generic Dictionary<TKey,TValue> (the only available in WinRT)
/// </summary>
public class Hashtable : Dictionary<object, object>
{
}
}
-179
View File
@@ -1,179 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Networking;
using Windows.Networking.Sockets;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Storage.Streams;
using System.Threading;
namespace uPLibrary.Networking.M2Mqtt
{
public class MqttNetworkChannel : IMqttNetworkChannel
{
// stream socket for communication
private StreamSocket socket;
// remote host information
private HostName remoteHostName;
private int remotePort;
// using SSL
private bool secure;
// SSL/TLS protocol version
private MqttSslProtocols sslProtocol;
/// <summary>
/// Constructor
/// </summary>
/// <param name="socket">Socket opened with the client</param>
public MqttNetworkChannel(StreamSocket socket)
{
this.socket = socket;
this.sslProtocol = MqttSslProtocols.None;
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="remoteHostName">Remote Host name</param>
/// <param name="remotePort">Remote port</param>
/// <param name="secure">Using SSL</param>
/// <param name="sslProtocol">SSL/TLS protocol version</param>
public MqttNetworkChannel(string remoteHostName, int remotePort, bool secure, MqttSslProtocols sslProtocol)
{
this.remoteHostName = new HostName(remoteHostName);
this.remotePort = remotePort;
this.secure = secure;
this.sslProtocol = sslProtocol;
if (secure && (sslProtocol == MqttSslProtocols.None))
throw new ArgumentException("For secure connection, an SSL/TLS protocol version is needed");
}
public bool DataAvailable
{
get { return true; }
}
public int Receive(byte[] buffer)
{
IBuffer result;
// read all data needed (until fill buffer)
int idx = 0;
while (idx < buffer.Length)
{
// fixed scenario with socket closed gracefully by peer/broker and
// Read return 0. Avoid infinite loop.
// read is executed synchronously
result = this.socket.InputStream.ReadAsync(buffer.AsBuffer(), (uint)buffer.Length, InputStreamOptions.None).AsTask().Result;
if (result.Length == 0)
return 0;
idx += (int)result.Length;
}
return buffer.Length;
}
public int Receive(byte[] buffer, int timeout)
{
CancellationTokenSource cts = new CancellationTokenSource(timeout);
try
{
IBuffer result;
// read all data needed (until fill buffer)
int idx = 0;
while (idx < buffer.Length)
{
// fixed scenario with socket closed gracefully by peer/broker and
// Read return 0. Avoid infinite loop.
// read is executed synchronously
result = this.socket.InputStream.ReadAsync(buffer.AsBuffer(), (uint)buffer.Length, InputStreamOptions.None).AsTask(cts.Token).Result;
if (result.Length == 0)
return 0;
idx += (int)result.Length;
}
return buffer.Length;
}
catch (TaskCanceledException)
{
return 0;
}
}
public int Send(byte[] buffer)
{
// send is executed synchronously
return (int)this.socket.OutputStream.WriteAsync(buffer.AsBuffer()).AsTask().Result;
}
public void Close()
{
this.socket.Dispose();
}
public void Connect()
{
this.socket = new StreamSocket();
// connection is executed synchronously
this.socket.ConnectAsync(this.remoteHostName,
this.remotePort.ToString(),
MqttSslUtility.ToSslPlatformEnum(this.sslProtocol)).AsTask().Wait();
}
public void Accept()
{
// TODO : SSL support with StreamSocket / StreamSocketListener seems to be NOT supported
return;
}
}
/// <summary>
/// MQTT SSL utility class
/// </summary>
public static class MqttSslUtility
{
public static SocketProtectionLevel ToSslPlatformEnum(MqttSslProtocols mqttSslProtocol)
{
switch (mqttSslProtocol)
{
case MqttSslProtocols.None:
return SocketProtectionLevel.PlainSocket;
case MqttSslProtocols.SSLv3:
return SocketProtectionLevel.SslAllowNullEncryption;
case MqttSslProtocols.TLSv1_0:
return SocketProtectionLevel.Tls10;
case MqttSslProtocols.TLSv1_1:
return SocketProtectionLevel.Tls11;
case MqttSslProtocols.TLSv1_2:
return SocketProtectionLevel.Tls12;
default:
throw new ArgumentException("SSL/TLS protocol version not supported");
}
}
}
}
-27
View File
@@ -1,27 +0,0 @@
/*
Copyright (c) 2013, 2014 Paolo Patierno
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System.Collections.Generic;
namespace uPLibrary.Networking.M2Mqtt
{
/// <summary>
/// Wrapper Queue class for generic Queue<T> (the only available in WinRT)
/// </summary>
public class Queue : Queue<object>
{
}
}
-25
View File
@@ -1,25 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2010
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "M2Mqtt_2", "M2Mqtt\M2Mqtt_2.csproj", "{A11AEF5A-B246-4FE8-8330-06DB73CC8074}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {135814CF-A469-4436-9C51-3CFE4B93D2FE}
EndGlobalSection
EndGlobal
-25
View File
@@ -1,25 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2010
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "M2Mqtt", "M2Mqtt\M2Mqtt_4.7.1.csproj", "{A11AEF5A-B246-4FE8-8330-06DB73CC8074}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {135814CF-A469-4436-9C51-3CFE4B93D2FE}
EndGlobalSection
EndGlobal
+39
View File
@@ -0,0 +1,39 @@
#!/bin/bash
function look_for_update() {
if [[ $1 == ./.git ]] || [[ $1 == "." ]]; then
echo "Ignore $1"
return
fi
WithoutPrefix=$(echo -n $1 | cut -c 2-)
if grep -qx "$WithoutPrefix" .gitignore; then
echo "Ignore $1, because it's in .gitignore"
return
fi
printf -v FolderNameEscaped '%q' "$1"
if [[ -f $1/update.sh ]]; then
echo "Switch to subdir $1 and run update.sh"
cd "$1"
git pull
bash -c "./update.sh nobreak"
else
if [[ -f $1/.git ]]
then
echo "Pull $1"
cd "$1"
git pull
else
echo "Checkout master for $1"
git submodule update --init -- "$1"
cd "$1"
git checkout master
fi
fi
}
export -f look_for_update
find . -maxdepth 1 -type d -exec bash -c 'look_for_update "$0"' {} \;
if [ -z $1 ]; then
read -p "Press return"
fi