Compare commits

..

5 Commits

49 changed files with 5108 additions and 5570 deletions

203
LICENSE Normal file
View File

@ -0,0 +1,203 @@
Eclipse Public License - v 1.0
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
1. DEFINITIONS
"Contribution" means:
a) in the case of the initial Contributor, the initial code and documentation
distributed under this Agreement, and
b) in the case of each subsequent Contributor:
i) changes to the Program, and
ii) additions to the Program;
where such changes and/or additions to the Program originate from and are
distributed by that particular Contributor. A Contribution 'originates'
from a Contributor if it was added to the Program by such Contributor
itself or anyone acting on such Contributor's behalf. Contributions do not
include additions to the Program which: (i) are separate modules of
software distributed in conjunction with the Program under their own
license agreement, and (ii) are not derivative works of the Program.
"Contributor" means any person or entity that distributes the Program.
"Licensed Patents" mean patent claims licensable by a Contributor which are
necessarily infringed by the use or sale of its Contribution alone or when
combined with the Program.
"Program" means the Contributions distributed in accordance with this
Agreement.
"Recipient" means anyone who receives the Program under this Agreement,
including all Contributors.
2. GRANT OF RIGHTS
a) Subject to the terms of this Agreement, each Contributor hereby grants
Recipient a non-exclusive, worldwide, royalty-free copyright license to
reproduce, prepare derivative works of, publicly display, publicly
perform, distribute and sublicense the Contribution of such Contributor,
if any, and such derivative works, in source code and object code form.
b) Subject to the terms of this Agreement, each Contributor hereby grants
Recipient a non-exclusive, worldwide, royalty-free patent license under
Licensed Patents to make, use, sell, offer to sell, import and otherwise
transfer the Contribution of such Contributor, if any, in source code and
object code form. This patent license shall apply to the combination of
the Contribution and the Program if, at the time the Contribution is
added by the Contributor, such addition of the Contribution causes such
combination to be covered by the Licensed Patents. The patent license
shall not apply to any other combinations which include the Contribution.
No hardware per se is licensed hereunder.
c) Recipient understands that although each Contributor grants the licenses
to its Contributions set forth herein, no assurances are provided by any
Contributor that the Program does not infringe the patent or other
intellectual property rights of any other entity. Each Contributor
disclaims any liability to Recipient for claims brought by any other
entity based on infringement of intellectual property rights or
otherwise. As a condition to exercising the rights and licenses granted
hereunder, each Recipient hereby assumes sole responsibility to secure
any other intellectual property rights needed, if any. For example, if a
third party patent license is required to allow Recipient to distribute
the Program, it is Recipient's responsibility to acquire that license
before distributing the Program.
d) Each Contributor represents that to its knowledge it has sufficient
copyright rights in its Contribution, if any, to grant the copyright
license set forth in this Agreement.
3. REQUIREMENTS
A Contributor may choose to distribute the Program in object code form under
its own license agreement, provided that:
a) it complies with the terms and conditions of this Agreement; and
b) its license agreement:
i) effectively disclaims on behalf of all Contributors all warranties
and conditions, express and implied, including warranties or
conditions of title and non-infringement, and implied warranties or
conditions of merchantability and fitness for a particular purpose;
ii) effectively excludes on behalf of all Contributors all liability for
damages, including direct, indirect, special, incidental and
consequential damages, such as lost profits;
iii) states that any provisions which differ from this Agreement are
offered by that Contributor alone and not by any other party; and
iv) states that source code for the Program is available from such
Contributor, and informs licensees how to obtain it in a reasonable
manner on or through a medium customarily used for software exchange.
When the Program is made available in source code form:
a) it must be made available under this Agreement; and
b) a copy of this Agreement must be included with each copy of the Program.
Contributors may not remove or alter any copyright notices contained
within the Program.
Each Contributor must identify itself as the originator of its Contribution,
if
any, in a manner that reasonably allows subsequent Recipients to identify the
originator of the Contribution.
4. COMMERCIAL DISTRIBUTION
Commercial distributors of software may accept certain responsibilities with
respect to end users, business partners and the like. While this license is
intended to facilitate the commercial use of the Program, the Contributor who
includes the Program in a commercial product offering should do so in a manner
which does not create potential liability for other Contributors. Therefore,
if a Contributor includes the Program in a commercial product offering, such
Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
every other Contributor ("Indemnified Contributor") against any losses,
damages and costs (collectively "Losses") arising from claims, lawsuits and
other legal actions brought by a third party against the Indemnified
Contributor to the extent caused by the acts or omissions of such Commercial
Contributor in connection with its distribution of the Program in a commercial
product offering. The obligations in this section do not apply to any claims
or Losses relating to any actual or alleged intellectual property
infringement. In order to qualify, an Indemnified Contributor must:
a) promptly notify the Commercial Contributor in writing of such claim, and
b) allow the Commercial Contributor to control, and cooperate with the
Commercial Contributor in, the defense and any related settlement
negotiations. The Indemnified Contributor may participate in any such claim at
its own expense.
For example, a Contributor might include the Program in a commercial product
offering, Product X. That Contributor is then a Commercial Contributor. If
that Commercial Contributor then makes performance claims, or offers
warranties related to Product X, those performance claims and warranties are
such Commercial Contributor's responsibility alone. Under this section, the
Commercial Contributor would have to defend claims against the other
Contributors related to those performance claims and warranties, and if a
court requires any other Contributor to pay any damages as a result, the
Commercial Contributor must pay those damages.
5. NO WARRANTY
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
Recipient is solely responsible for determining the appropriateness of using
and distributing the Program and assumes all risks associated with its
exercise of rights under this Agreement , including but not limited to the
risks and costs of program errors, compliance with applicable laws, damage to
or loss of data, programs or equipment, and unavailability or interruption of
operations.
6. DISCLAIMER OF LIABILITY
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGES.
7. GENERAL
If any provision of this Agreement is invalid or unenforceable under
applicable law, it shall not affect the validity or enforceability of the
remainder of the terms of this Agreement, and without further action by the
parties hereto, such provision shall be reformed to the minimum extent
necessary to make such provision valid and enforceable.
If Recipient institutes patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Program itself
(excluding combinations of the Program with other software or hardware)
infringes such Recipient's patent(s), then such Recipient's rights granted
under Section 2(b) shall terminate as of the date such litigation is filed.
All Recipient's rights under this Agreement shall terminate if it fails to
comply with any of the material terms or conditions of this Agreement and does
not cure such failure in a reasonable period of time after becoming aware of
such noncompliance. If all Recipient's rights under this Agreement terminate,
Recipient agrees to cease use and distribution of the Program as soon as
reasonably practicable. However, Recipient's obligations under this Agreement
and any licenses granted by Recipient relating to the Program shall continue
and survive.
Everyone is permitted to copy and distribute copies of this Agreement, but in
order to avoid inconsistency the Agreement is copyrighted and may only be
modified in the following manner. The Agreement Steward reserves the right to
publish new versions (including revisions) of this Agreement from time to
time. No one other than the Agreement Steward has the right to modify this
Agreement. The Eclipse Foundation is the initial Agreement Steward. The
Eclipse Foundation may assign the responsibility to serve as the Agreement
Steward to a suitable separate entity. Each new version of the Agreement will
be given a distinguishing version number. The Program (including
Contributions) may always be distributed subject to the version of the
Agreement under which it was received. In addition, after a new version of the
Agreement is published, Contributor may elect to distribute the Program
(including its Contributions) under the new version. Except as expressly
stated in Sections 2(a) and 2(b) above, Recipient receives no rights or
licenses to the intellectual property of any Contributor under this Agreement,
whether expressly, by implication, estoppel or otherwise. All rights in the
Program not expressly granted under this Agreement are reserved.
This Agreement is governed by the laws of the State of New York and the
intellectual property laws of the United States of America. No party to this
Agreement will bring a legal action under this Agreement more than one year
after the cause of action arose. Each party waives its rights to a jury trial in
any resulting litigation.

25
M2Mqtt.sln Normal file
View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29519.87
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "M2Mqtt", "M2Mqtt\M2Mqtt.csproj", "{18F706D2-7610-428C-8324-8327F9D7BE90}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{18F706D2-7610-428C-8324-8327F9D7BE90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{18F706D2-7610-428C-8324-8327F9D7BE90}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18F706D2-7610-428C-8324-8327F9D7BE90}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18F706D2-7610-428C-8324-8327F9D7BE90}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EBFDF320-2C59-4F89-8211-5B6EF9C310ED}
EndGlobalSection
EndGlobal

View File

@ -16,40 +16,27 @@ Contributors:
using System; using System;
namespace uPLibrary.Networking.M2Mqtt.Exceptions namespace uPLibrary.Networking.M2Mqtt.Exceptions {
{
/// <summary> /// <summary>
/// MQTT client exception /// MQTT client exception
/// </summary> /// </summary>
public class MqttClientException : Exception public class MqttClientException : Exception {
{
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
/// <param name="code">Error code</param> /// <param name="code">Error code</param>
public MqttClientException(MqttClientErrorCode errorCode) public MqttClientException(MqttClientErrorCode errorCode) => this.ErrorCode = errorCode;
{
this.errorCode = errorCode;
}
// error code
private MqttClientErrorCode errorCode;
/// <summary> /// <summary>
/// Error code /// Error code
/// </summary> /// </summary>
public MqttClientErrorCode ErrorCode public MqttClientErrorCode ErrorCode { get; set; }
{
get { return this.errorCode; }
set { this.errorCode = value; }
}
} }
/// <summary> /// <summary>
/// MQTT client erroro code /// MQTT client erroro code
/// </summary> /// </summary>
public enum MqttClientErrorCode public enum MqttClientErrorCode {
{
/// <summary> /// <summary>
/// Will error (topic, message or QoS level) /// Will error (topic, message or QoS level)
/// </summary> /// </summary>

View File

@ -16,18 +16,15 @@ Contributors:
using System; using System;
namespace uPLibrary.Networking.M2Mqtt.Exceptions namespace uPLibrary.Networking.M2Mqtt.Exceptions {
{
/// <summary> /// <summary>
/// Exception due to error communication with broker on socket /// Exception due to error communication with broker on socket
/// </summary> /// </summary>
public class MqttCommunicationException : Exception public class MqttCommunicationException : Exception {
{
/// <summary> /// <summary>
/// Default constructor /// Default constructor
/// </summary> /// </summary>
public MqttCommunicationException() public MqttCommunicationException() {
{
} }
/// <summary> /// <summary>
@ -35,8 +32,7 @@ namespace uPLibrary.Networking.M2Mqtt.Exceptions
/// </summary> /// </summary>
/// <param name="e">Inner Exception</param> /// <param name="e">Inner Exception</param>
public MqttCommunicationException(Exception e) public MqttCommunicationException(Exception e)
: base(String.Empty, e) : base(String.Empty, e) {
{
} }
} }
} }

View File

@ -16,16 +16,13 @@ Contributors:
using System; using System;
namespace uPLibrary.Networking.M2Mqtt.Exceptions namespace uPLibrary.Networking.M2Mqtt.Exceptions {
{
/// <summary> /// <summary>
/// Connection to the broker exception /// Connection to the broker exception
/// </summary> /// </summary>
public class MqttConnectionException : Exception public class MqttConnectionException : Exception {
{ public MqttConnectionException(String message, Exception innerException)
public MqttConnectionException(string message, Exception innerException) : base(message, innerException) {
: base(message, innerException)
{
} }
} }
} }

View File

@ -16,12 +16,10 @@ Contributors:
using System; using System;
namespace uPLibrary.Networking.M2Mqtt.Exceptions namespace uPLibrary.Networking.M2Mqtt.Exceptions {
{
/// <summary> /// <summary>
/// Timeout on receiving from broker exception /// Timeout on receiving from broker exception
/// </summary> /// </summary>
public class MqttTimeoutException : Exception public class MqttTimeoutException : Exception {
{
} }
} }

View File

@ -15,26 +15,23 @@ Contributors:
*/ */
using System; using System;
using System.Text;
namespace uPLibrary.Networking.M2Mqtt namespace uPLibrary.Networking.M2Mqtt {
{
/// <summary> /// <summary>
/// Interface for channel under MQTT library /// Interface for channel under MQTT library
/// </summary> /// </summary>
public interface IMqttNetworkChannel public interface IMqttNetworkChannel {
{
/// <summary> /// <summary>
/// Data available on channel /// Data available on channel
/// </summary> /// </summary>
bool DataAvailable { get; } Boolean DataAvailable { get; }
/// <summary> /// <summary>
/// Receive data from the network channel /// Receive data from the network channel
/// </summary> /// </summary>
/// <param name="buffer">Data buffer for receiving data</param> /// <param name="buffer">Data buffer for receiving data</param>
/// <returns>Number of bytes received</returns> /// <returns>Number of bytes received</returns>
int Receive(byte[] buffer); Int32 Receive(Byte[] buffer);
/// <summary> /// <summary>
/// Receive data from the network channel with a specified timeout /// Receive data from the network channel with a specified timeout
@ -42,14 +39,14 @@ namespace uPLibrary.Networking.M2Mqtt
/// <param name="buffer">Data buffer for receiving data</param> /// <param name="buffer">Data buffer for receiving data</param>
/// <param name="timeout">Timeout on receiving (in milliseconds)</param> /// <param name="timeout">Timeout on receiving (in milliseconds)</param>
/// <returns>Number of bytes received</returns> /// <returns>Number of bytes received</returns>
int Receive(byte[] buffer, int timeout); Int32 Receive(Byte[] buffer, Int32 timeout);
/// <summary> /// <summary>
/// Send data on the network channel to the broker /// Send data on the network channel to the broker
/// </summary> /// </summary>
/// <param name="buffer">Data buffer to send</param> /// <param name="buffer">Data buffer to send</param>
/// <returns>Number of byte sent</returns> /// <returns>Number of byte sent</returns>
int Send(byte[] buffer); Int32 Send(Byte[] buffer);
/// <summary> /// <summary>
/// Close the network channel /// Close the network channel

View File

@ -14,12 +14,10 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
namespace uPLibrary.Networking.M2Mqtt.Internal namespace uPLibrary.Networking.M2Mqtt.Internal {
{
/// <summary> /// <summary>
/// Generic internal event for dispatching /// Generic internal event for dispatching
/// </summary> /// </summary>
public abstract class InternalEvent public abstract class InternalEvent {
{
} }
} }

View File

@ -16,36 +16,26 @@ Contributors:
using uPLibrary.Networking.M2Mqtt.Messages; using uPLibrary.Networking.M2Mqtt.Messages;
namespace uPLibrary.Networking.M2Mqtt.Internal namespace uPLibrary.Networking.M2Mqtt.Internal {
{
/// <summary> /// <summary>
/// Internal event with a message /// Internal event with a message
/// </summary> /// </summary>
public class MsgInternalEvent : InternalEvent public class MsgInternalEvent : InternalEvent {
{
#region Properties ... #region Properties ...
/// <summary> /// <summary>
/// Related message /// Related message
/// </summary> /// </summary>
public MqttMsgBase Message public MqttMsgBase Message { get; set; }
{
get { return this.msg; }
set { this.msg = value; }
}
#endregion #endregion
// related message // related message
protected MqttMsgBase msg;
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
/// <param name="msg">Related message</param> /// <param name="msg">Related message</param>
public MsgInternalEvent(MqttMsgBase msg) public MsgInternalEvent(MqttMsgBase msg) => this.Message = msg;
{
this.msg = msg;
}
} }
} }

View File

@ -14,40 +14,31 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
using System;
using uPLibrary.Networking.M2Mqtt.Messages; using uPLibrary.Networking.M2Mqtt.Messages;
namespace uPLibrary.Networking.M2Mqtt.Internal namespace uPLibrary.Networking.M2Mqtt.Internal {
{
/// <summary> /// <summary>
/// Internal event for a published message /// Internal event for a published message
/// </summary> /// </summary>
public class MsgPublishedInternalEvent : MsgInternalEvent public class MsgPublishedInternalEvent : MsgInternalEvent {
{
#region Properties... #region Properties...
/// <summary> /// <summary>
/// Message published (or failed due to retries) /// Message published (or failed due to retries)
/// </summary> /// </summary>
public bool IsPublished public Boolean IsPublished { get; internal set; }
{
get { return this.isPublished; }
internal set { this.isPublished = value; }
}
#endregion #endregion
// published flag // published flag
bool isPublished;
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
/// <param name="msg">Message published</param> /// <param name="msg">Message published</param>
/// <param name="isPublished">Publish flag</param> /// <param name="isPublished">Publish flag</param>
public MsgPublishedInternalEvent(MqttMsgBase msg, bool isPublished) public MsgPublishedInternalEvent(MqttMsgBase msg, Boolean isPublished)
: base(msg) : base(msg) => this.IsPublished = isPublished;
{
this.isPublished = isPublished;
}
} }
} }

24
M2Mqtt/M2Mqtt.csproj Normal file
View File

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AssemblyName>M2Mqtt</AssemblyName>
<RootNamespace>uPLibrary.Networking.M2Mqtt</RootNamespace>
<Description>MQTT Client Library for M2M communication</Description>
<Authors>Paolo Patierno</Authors>
<Company>Paolo Patierno</Company>
<Copyright>Copyright © Paolo Patierno 2014</Copyright>
<Version>4.3.0</Version>
<AssemblyVersion>4.3.0</AssemblyVersion>
<FileVersion>4.3.0</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>TRACE;SSL</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants>TRACE;SSL</DefineConstants>
</PropertyGroup>
</Project>

View File

@ -17,75 +17,73 @@ Contributors:
using System; using System;
using System.Text; using System.Text;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Base class for all MQTT messages /// Base class for all MQTT messages
/// </summary> /// </summary>
public abstract class MqttMsgBase public abstract class MqttMsgBase {
{
#region Constants... #region Constants...
// mask, offset and size for fixed header fields // mask, offset and size for fixed header fields
internal const byte MSG_TYPE_MASK = 0xF0; internal const Byte MSG_TYPE_MASK = 0xF0;
internal const byte MSG_TYPE_OFFSET = 0x04; internal const Byte MSG_TYPE_OFFSET = 0x04;
internal const byte MSG_TYPE_SIZE = 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_MASK = 0x0F; // [v3.1.1]
internal const byte MSG_FLAG_BITS_OFFSET = 0x00; // [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 MSG_FLAG_BITS_SIZE = 0x04; // [v3.1.1]
internal const byte DUP_FLAG_MASK = 0x08; internal const Byte DUP_FLAG_MASK = 0x08;
internal const byte DUP_FLAG_OFFSET = 0x03; internal const Byte DUP_FLAG_OFFSET = 0x03;
internal const byte DUP_FLAG_SIZE = 0x01; internal const Byte DUP_FLAG_SIZE = 0x01;
internal const byte QOS_LEVEL_MASK = 0x06; internal const Byte QOS_LEVEL_MASK = 0x06;
internal const byte QOS_LEVEL_OFFSET = 0x01; internal const Byte QOS_LEVEL_OFFSET = 0x01;
internal const byte QOS_LEVEL_SIZE = 0x02; internal const Byte QOS_LEVEL_SIZE = 0x02;
internal const byte RETAIN_FLAG_MASK = 0x01; internal const Byte RETAIN_FLAG_MASK = 0x01;
internal const byte RETAIN_FLAG_OFFSET = 0x00; internal const Byte RETAIN_FLAG_OFFSET = 0x00;
internal const byte RETAIN_FLAG_SIZE = 0x01; internal const Byte RETAIN_FLAG_SIZE = 0x01;
// MQTT message types // MQTT message types
internal const byte MQTT_MSG_CONNECT_TYPE = 0x01; internal const Byte MQTT_MSG_CONNECT_TYPE = 0x01;
internal const byte MQTT_MSG_CONNACK_TYPE = 0x02; internal const Byte MQTT_MSG_CONNACK_TYPE = 0x02;
internal const byte MQTT_MSG_PUBLISH_TYPE = 0x03; internal const Byte MQTT_MSG_PUBLISH_TYPE = 0x03;
internal const byte MQTT_MSG_PUBACK_TYPE = 0x04; internal const Byte MQTT_MSG_PUBACK_TYPE = 0x04;
internal const byte MQTT_MSG_PUBREC_TYPE = 0x05; internal const Byte MQTT_MSG_PUBREC_TYPE = 0x05;
internal const byte MQTT_MSG_PUBREL_TYPE = 0x06; internal const Byte MQTT_MSG_PUBREL_TYPE = 0x06;
internal const byte MQTT_MSG_PUBCOMP_TYPE = 0x07; internal const Byte MQTT_MSG_PUBCOMP_TYPE = 0x07;
internal const byte MQTT_MSG_SUBSCRIBE_TYPE = 0x08; internal const Byte MQTT_MSG_SUBSCRIBE_TYPE = 0x08;
internal const byte MQTT_MSG_SUBACK_TYPE = 0x09; internal const Byte MQTT_MSG_SUBACK_TYPE = 0x09;
internal const byte MQTT_MSG_UNSUBSCRIBE_TYPE = 0x0A; internal const Byte MQTT_MSG_UNSUBSCRIBE_TYPE = 0x0A;
internal const byte MQTT_MSG_UNSUBACK_TYPE = 0x0B; internal const Byte MQTT_MSG_UNSUBACK_TYPE = 0x0B;
internal const byte MQTT_MSG_PINGREQ_TYPE = 0x0C; internal const Byte MQTT_MSG_PINGREQ_TYPE = 0x0C;
internal const byte MQTT_MSG_PINGRESP_TYPE = 0x0D; internal const Byte MQTT_MSG_PINGRESP_TYPE = 0x0D;
internal const byte MQTT_MSG_DISCONNECT_TYPE = 0x0E; internal const Byte MQTT_MSG_DISCONNECT_TYPE = 0x0E;
// [v3.1.1] MQTT flag bits // [v3.1.1] MQTT flag bits
internal const byte MQTT_MSG_CONNECT_FLAG_BITS = 0x00; internal const Byte MQTT_MSG_CONNECT_FLAG_BITS = 0x00;
internal const byte MQTT_MSG_CONNACK_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_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_PUBACK_FLAG_BITS = 0x00;
internal const byte MQTT_MSG_PUBREC_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_PUBREL_FLAG_BITS = 0x02;
internal const byte MQTT_MSG_PUBCOMP_FLAG_BITS = 0x00; internal const Byte MQTT_MSG_PUBCOMP_FLAG_BITS = 0x00;
internal const byte MQTT_MSG_SUBSCRIBE_FLAG_BITS = 0x02; internal const Byte MQTT_MSG_SUBSCRIBE_FLAG_BITS = 0x02;
internal const byte MQTT_MSG_SUBACK_FLAG_BITS = 0x00; internal const Byte MQTT_MSG_SUBACK_FLAG_BITS = 0x00;
internal const byte MQTT_MSG_UNSUBSCRIBE_FLAG_BITS = 0x02; internal const Byte MQTT_MSG_UNSUBSCRIBE_FLAG_BITS = 0x02;
internal const byte MQTT_MSG_UNSUBACK_FLAG_BITS = 0x00; internal const Byte MQTT_MSG_UNSUBACK_FLAG_BITS = 0x00;
internal const byte MQTT_MSG_PINGREQ_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_PINGRESP_FLAG_BITS = 0x00;
internal const byte MQTT_MSG_DISCONNECT_FLAG_BITS = 0x00; internal const Byte MQTT_MSG_DISCONNECT_FLAG_BITS = 0x00;
// QOS levels // QOS levels
public const byte QOS_LEVEL_AT_MOST_ONCE = 0x00; public const Byte QOS_LEVEL_AT_MOST_ONCE = 0x00;
public const byte QOS_LEVEL_AT_LEAST_ONCE = 0x01; public const Byte QOS_LEVEL_AT_LEAST_ONCE = 0x01;
public const byte QOS_LEVEL_EXACTLY_ONCE = 0x02; public const Byte QOS_LEVEL_EXACTLY_ONCE = 0x02;
// SUBSCRIBE QoS level granted failure [v3.1.1] // SUBSCRIBE QoS level granted failure [v3.1.1]
public const byte QOS_LEVEL_GRANTED_FAILURE = 0x80; public const Byte QOS_LEVEL_GRANTED_FAILURE = 0x80;
internal const ushort MAX_TOPIC_LENGTH = 65535; internal const UInt16 MAX_TOPIC_LENGTH = 65535;
internal const ushort MIN_TOPIC_LENGTH = 1; internal const UInt16 MIN_TOPIC_LENGTH = 1;
internal const byte MESSAGE_ID_SIZE = 2; internal const Byte MESSAGE_ID_SIZE = 2;
#endregion #endregion
@ -94,67 +92,42 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <summary> /// <summary>
/// Message type /// Message type
/// </summary> /// </summary>
public byte Type public Byte Type { get; set; }
{
get { return this.type; }
set { this.type = value; }
}
/// <summary> /// <summary>
/// Duplicate message flag /// Duplicate message flag
/// </summary> /// </summary>
public bool DupFlag public Boolean DupFlag { get; set; }
{
get { return this.dupFlag; }
set { this.dupFlag = value; }
}
/// <summary> /// <summary>
/// Quality of Service level /// Quality of Service level
/// </summary> /// </summary>
public byte QosLevel public Byte QosLevel { get; set; }
{
get { return this.qosLevel; }
set { this.qosLevel = value; }
}
/// <summary> /// <summary>
/// Retain message flag /// Retain message flag
/// </summary> /// </summary>
public bool Retain public Boolean Retain { get; set; }
{
get { return this.retain; }
set { this.retain = value; }
}
/// <summary> /// <summary>
/// Message identifier for the message /// Message identifier for the message
/// </summary> /// </summary>
public ushort MessageId public UInt16 MessageId { get; set; }
{
get { return this.messageId; }
set { this.messageId = value; }
}
#endregion #endregion
// message type // message type
protected byte type;
// duplicate delivery // duplicate delivery
protected bool dupFlag;
// quality of service level // quality of service level
protected byte qosLevel;
// retain flag // retain flag
protected bool retain;
// message identifier // message identifier
protected ushort messageId;
/// <summary> /// <summary>
/// Returns message bytes rapresentation /// Returns message bytes rapresentation
/// </summary> /// </summary>
/// <param name="protocolVersion">Protocol version</param> /// <param name="protocolVersion">Protocol version</param>
/// <returns>Bytes rapresentation</returns> /// <returns>Bytes rapresentation</returns>
public abstract byte[] GetBytes(byte protocolVersion); public abstract Byte[] GetBytes(Byte protocolVersion);
/// <summary> /// <summary>
/// Encode remaining length and insert it into message buffer /// Encode remaining length and insert it into message buffer
@ -163,16 +136,15 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <param name="buffer">Message buffer for inserting encoded value</param> /// <param name="buffer">Message buffer for inserting encoded value</param>
/// <param name="index">Index from which insert encoded value into buffer</param> /// <param name="index">Index from which insert encoded value into buffer</param>
/// <returns>Index updated</returns> /// <returns>Index updated</returns>
protected int encodeRemainingLength(int remainingLength, byte[] buffer, int index) protected Int32 EncodeRemainingLength(Int32 remainingLength, Byte[] buffer, Int32 index) {
{ do {
int digit = 0; Int32 digit = remainingLength % 128;
do
{
digit = remainingLength % 128;
remainingLength /= 128; remainingLength /= 128;
if (remainingLength > 0) if (remainingLength > 0) {
digit = digit | 0x80; digit |= 0x80;
buffer[index++] = (byte)digit; }
buffer[index++] = (Byte)digit;
} while (remainingLength > 0); } while (remainingLength > 0);
return index; return index;
} }
@ -182,18 +154,16 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// </summary> /// </summary>
/// <param name="channel">Channel from reading bytes</param> /// <param name="channel">Channel from reading bytes</param>
/// <returns>Decoded remaining length</returns> /// <returns>Decoded remaining length</returns>
protected static int decodeRemainingLength(IMqttNetworkChannel channel) protected static Int32 DecodeRemainingLength(IMqttNetworkChannel channel) {
{ Int32 multiplier = 1;
int multiplier = 1; Int32 value = 0;
int value = 0; Byte[] nextByte = new Byte[1];
int digit = 0; Int32 digit;
byte[] nextByte = new byte[1]; do {
do
{
// next digit from stream // next digit from stream
channel.Receive(nextByte); _ = channel.Receive(nextByte);
digit = nextByte[0]; digit = nextByte[0];
value += ((digit & 127) * multiplier); value += (digit & 127) * multiplier;
multiplier *= 128; multiplier *= 128;
} while ((digit & 128) != 0); } while ((digit & 128) != 0);
return value; return value;
@ -207,63 +177,54 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <param name="fieldNames">Message fields name</param> /// <param name="fieldNames">Message fields name</param>
/// <param name="fieldValues">Message fields value</param> /// <param name="fieldValues">Message fields value</param>
/// <returns>String representation of the message</returns> /// <returns>String representation of the message</returns>
protected string GetTraceString(string name, object[] fieldNames, object[] fieldValues) protected String GetTraceString(String name, Object[] fieldNames, Object[] fieldValues) {
{
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.Append(name); _ = sb.Append(name);
if ((fieldNames != null) && (fieldValues != null)) if (fieldNames != null && fieldValues != null) {
{ _ = sb.Append("(");
sb.Append("("); Boolean addComma = false;
bool addComma = false; for (Int32 i = 0; i < fieldValues.Length; i++) {
for (int i = 0; i < fieldValues.Length; i++) if (fieldValues[i] != null) {
{ if (addComma) {
if (fieldValues[i] != null) _ = sb.Append(",");
{
if (addComma)
{
sb.Append(",");
} }
sb.Append(fieldNames[i]); _ = sb.Append(fieldNames[i]);
sb.Append(":"); _ = sb.Append(":");
sb.Append(GetStringObject(fieldValues[i])); _ = sb.Append(this.GetStringObject(fieldValues[i]));
addComma = true; addComma = true;
} }
} }
sb.Append(")"); _ = sb.Append(")");
} }
return sb.ToString(); return sb.ToString();
} }
object GetStringObject(object value) Object GetStringObject(Object value) {
{ if (value is Byte[] binary) {
byte[] binary = value as byte[]; String hexChars = "0123456789ABCDEF";
if (binary != null)
{
string hexChars = "0123456789ABCDEF";
StringBuilder sb = new StringBuilder(binary.Length * 2); StringBuilder sb = new StringBuilder(binary.Length * 2);
for (int i = 0; i < binary.Length; ++i) for (Int32 i = 0; i < binary.Length; ++i) {
{ _ = sb.Append(hexChars[binary[i] >> 4]);
sb.Append(hexChars[binary[i] >> 4]); _ = sb.Append(hexChars[binary[i] & 0x0F]);
sb.Append(hexChars[binary[i] & 0x0F]);
} }
return sb.ToString(); return sb.ToString();
} }
object[] list = value as object[]; if (value is Object[] list) {
if (list != null)
{
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.Append('['); _ = sb.Append('[');
for (int i = 0; i < list.Length; ++i) for (Int32 i = 0; i < list.Length; ++i) {
{ if (i > 0) {
if (i > 0) sb.Append(','); _ = sb.Append(',');
sb.Append(list[i]);
} }
sb.Append(']');
_ = sb.Append(list[i]);
}
_ = sb.Append(']');
return sb.ToString(); return sb.ToString();
} }

View File

@ -17,34 +17,32 @@ Contributors:
using System; using System;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Class for CONNACK message from broker to client /// Class for CONNACK message from broker to client
/// </summary> /// </summary>
public class MqttMsgConnack : MqttMsgBase public class MqttMsgConnack : MqttMsgBase {
{
#region Constants... #region Constants...
// return codes for CONNACK message // return codes for CONNACK message
public const byte CONN_ACCEPTED = 0x00; public const Byte CONN_ACCEPTED = 0x00;
public const byte CONN_REFUSED_PROT_VERS = 0x01; public const Byte CONN_REFUSED_PROT_VERS = 0x01;
public const byte CONN_REFUSED_IDENT_REJECTED = 0x02; public const Byte CONN_REFUSED_IDENT_REJECTED = 0x02;
public const byte CONN_REFUSED_SERVER_UNAVAILABLE = 0x03; public const Byte CONN_REFUSED_SERVER_UNAVAILABLE = 0x03;
public const byte CONN_REFUSED_USERNAME_PASSWORD = 0x04; public const Byte CONN_REFUSED_USERNAME_PASSWORD = 0x04;
public const byte CONN_REFUSED_NOT_AUTHORIZED = 0x05; 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_OFFSET = 0;
private const byte TOPIC_NAME_COMP_RESP_BYTE_SIZE = 1; 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) // [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_OFFSET = 0;
private const byte CONN_ACK_FLAGS_BYTE_SIZE = 1; private const Byte CONN_ACK_FLAGS_BYTE_SIZE = 1;
// [v3.1.1] session present flag // [v3.1.1] session present flag
private const byte SESSION_PRESENT_FLAG_MASK = 0x01; private const Byte SESSION_PRESENT_FLAG_MASK = 0x01;
private const byte SESSION_PRESENT_FLAG_OFFSET = 0x00; private const Byte SESSION_PRESENT_FLAG_OFFSET = 0x00;
private const byte SESSION_PRESENT_FLAG_SIZE = 0x01; //private const Byte SESSION_PRESENT_FLAG_SIZE = 0x01;
private const byte CONN_RETURN_CODE_BYTE_OFFSET = 1; private const Byte CONN_RETURN_CODE_BYTE_OFFSET = 1;
private const byte CONN_RETURN_CODE_BYTE_SIZE = 1; private const Byte CONN_RETURN_CODE_BYTE_SIZE = 1;
#endregion #endregion
@ -54,36 +52,21 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <summary> /// <summary>
/// Session present flag /// Session present flag
/// </summary> /// </summary>
public bool SessionPresent public Boolean SessionPresent { get; set; }
{
get { return this.sessionPresent; }
set { this.sessionPresent = value; }
}
/// <summary> /// <summary>
/// Return Code /// Return Code
/// </summary> /// </summary>
public byte ReturnCode public Byte ReturnCode { get; set; }
{
get { return this.returnCode; }
set { this.returnCode = value; }
}
#endregion #endregion
// [v3.1.1] session present flag // [v3.1.1] session present flag
private bool sessionPresent;
// return code for CONNACK message
private byte returnCode;
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
public MqttMsgConnack() public MqttMsgConnack() => this.Type = MQTT_MSG_CONNACK_TYPE;
{
this.type = MQTT_MSG_CONNACK_TYPE;
}
/// <summary> /// <summary>
/// Parse bytes for a CONNACK message /// Parse bytes for a CONNACK message
@ -92,100 +75,95 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <param name="protocolVersion">Protocol Version</param> /// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param> /// <param name="channel">Channel connected to the broker</param>
/// <returns>CONNACK message instance</returns> /// <returns>CONNACK message instance</returns>
public static MqttMsgConnack Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) public static MqttMsgConnack Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
{ Byte[] buffer;
byte[] buffer;
MqttMsgConnack msg = new MqttMsgConnack(); MqttMsgConnack msg = new MqttMsgConnack();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
{
// [v3.1.1] check flag bits // [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_CONNACK_FLAG_BITS) if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_CONNACK_FLAG_BITS) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
} }
}
// get remaining length and allocate buffer // get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
buffer = new byte[remainingLength]; buffer = new Byte[remainingLength];
// read bytes from socket... // read bytes from socket...
channel.Receive(buffer); _ = channel.Receive(buffer);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
{
// [v3.1.1] ... set session present flag ... // [v3.1.1] ... set session present flag ...
msg.sessionPresent = (buffer[CONN_ACK_FLAGS_BYTE_OFFSET] & SESSION_PRESENT_FLAG_MASK) != 0x00; msg.SessionPresent = (buffer[CONN_ACK_FLAGS_BYTE_OFFSET] & SESSION_PRESENT_FLAG_MASK) != 0x00;
} }
// ...and set return code from broker // ...and set return code from broker
msg.returnCode = buffer[CONN_RETURN_CODE_BYTE_OFFSET]; msg.ReturnCode = buffer[CONN_RETURN_CODE_BYTE_OFFSET];
return msg; return msg;
} }
public override byte[] GetBytes(byte ProtocolVersion) public override Byte[] GetBytes(Byte ProtocolVersion) {
{ Int32 varHeaderSize = 0;
int fixedHeaderSize = 0; Int32 payloadSize = 0;
int varHeaderSize = 0; Int32 remainingLength = 0;
int payloadSize = 0; Byte[] buffer;
int remainingLength = 0; Int32 index = 0;
byte[] buffer;
int index = 0;
if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
// flags byte and connect return code // flags byte and connect return code
varHeaderSize += (CONN_ACK_FLAGS_BYTE_SIZE + CONN_RETURN_CODE_BYTE_SIZE); varHeaderSize += CONN_ACK_FLAGS_BYTE_SIZE + CONN_RETURN_CODE_BYTE_SIZE;
else } else {
// topic name compression response and connect return code // topic name compression response and connect return code
varHeaderSize += (TOPIC_NAME_COMP_RESP_BYTE_SIZE + CONN_RETURN_CODE_BYTE_SIZE); varHeaderSize += TOPIC_NAME_COMP_RESP_BYTE_SIZE + CONN_RETURN_CODE_BYTE_SIZE;
}
remainingLength += (varHeaderSize + payloadSize); remainingLength += varHeaderSize + payloadSize;
// first byte of fixed header // first byte of fixed header
fixedHeaderSize = 1; Int32 fixedHeaderSize = 1;
int temp = remainingLength; Int32 temp = remainingLength;
// increase fixed header size based on remaining length // increase fixed header size based on remaining length
// (each remaining length byte can encode until 128) // (each remaining length byte can encode until 128)
do do {
{
fixedHeaderSize++; fixedHeaderSize++;
temp = temp / 128; temp /= 128;
} while (temp > 0); } while (temp > 0);
// allocate buffer for message // allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize]; buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte // first fixed header byte
if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) buffer[index++] = 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] ? (Byte)((MQTT_MSG_CONNACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_CONNACK_FLAG_BITS)
else : (Byte)(MQTT_MSG_CONNACK_TYPE << MSG_TYPE_OFFSET);
buffer[index++] = (byte)(MQTT_MSG_CONNACK_TYPE << MSG_TYPE_OFFSET);
// encode remaining length // encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index); index = this.EncodeRemainingLength(remainingLength, buffer, index);
if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
// [v3.1.1] session present flag // [v3.1.1] session present flag
buffer[index++] = this.sessionPresent ? (byte)(1 << SESSION_PRESENT_FLAG_OFFSET) : (byte)0x00; buffer[index++] = this.SessionPresent ? (Byte)(1 << SESSION_PRESENT_FLAG_OFFSET) : (Byte)0x00;
else } else {
// topic name compression response (reserved values. not used); // topic name compression response (reserved values. not used);
buffer[index++] = 0x00; buffer[index++] = 0x00;
}
// connect return code // connect return code
buffer[index++] = this.returnCode; buffer[index++] = this.ReturnCode;
return buffer; return buffer;
} }
public override string ToString() public override String ToString() =>
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"CONNACK", "CONNACK",
new object[] { "returnCode" }, new Object[] { "returnCode" },
new object[] { this.returnCode }); new Object[] { this.ReturnCode });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -18,58 +18,56 @@ using System;
using System.Text; using System.Text;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Class for CONNECT message from client to broker /// Class for CONNECT message from client to broker
/// </summary> /// </summary>
public class MqttMsgConnect : MqttMsgBase public class MqttMsgConnect : MqttMsgBase {
{
#region Constants... #region Constants...
// protocol name supported // protocol name supported
internal const string PROTOCOL_NAME_V3_1 = "MQIsdp"; internal const String PROTOCOL_NAME_V3_1 = "MQIsdp";
internal const string PROTOCOL_NAME_V3_1_1 = "MQTT"; // [v.3.1.1] internal const String PROTOCOL_NAME_V3_1_1 = "MQTT"; // [v.3.1.1]
// max length for client id (removed in 3.1.1) // max length for client id (removed in 3.1.1)
internal const int CLIENT_ID_MAX_LENGTH = 23; internal const Int32 CLIENT_ID_MAX_LENGTH = 23;
// variable header fields // variable header fields
internal const byte PROTOCOL_NAME_LEN_SIZE = 2; internal const Byte PROTOCOL_NAME_LEN_SIZE = 2;
internal const byte PROTOCOL_NAME_V3_1_SIZE = 6; 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_NAME_V3_1_1_SIZE = 4; // [v.3.1.1]
internal const byte PROTOCOL_VERSION_SIZE = 1; internal const Byte PROTOCOL_VERSION_SIZE = 1;
internal const byte CONNECT_FLAGS_SIZE = 1; internal const Byte CONNECT_FLAGS_SIZE = 1;
internal const byte KEEP_ALIVE_TIME_SIZE = 2; internal const Byte KEEP_ALIVE_TIME_SIZE = 2;
internal const byte PROTOCOL_VERSION_V3_1 = 0x03; internal const Byte PROTOCOL_VERSION_V3_1 = 0x03;
internal const byte PROTOCOL_VERSION_V3_1_1 = 0x04; // [v.3.1.1] internal const Byte PROTOCOL_VERSION_V3_1_1 = 0x04; // [v.3.1.1]
internal const ushort KEEP_ALIVE_PERIOD_DEFAULT = 60; // seconds internal const UInt16 KEEP_ALIVE_PERIOD_DEFAULT = 60; // seconds
internal const ushort MAX_KEEP_ALIVE = 65535; // 16 bit internal const UInt16 MAX_KEEP_ALIVE = 65535; // 16 bit
// connect flags // connect flags
internal const byte USERNAME_FLAG_MASK = 0x80; internal const Byte USERNAME_FLAG_MASK = 0x80;
internal const byte USERNAME_FLAG_OFFSET = 0x07; internal const Byte USERNAME_FLAG_OFFSET = 0x07;
internal const byte USERNAME_FLAG_SIZE = 0x01; internal const Byte USERNAME_FLAG_SIZE = 0x01;
internal const byte PASSWORD_FLAG_MASK = 0x40; internal const Byte PASSWORD_FLAG_MASK = 0x40;
internal const byte PASSWORD_FLAG_OFFSET = 0x06; internal const Byte PASSWORD_FLAG_OFFSET = 0x06;
internal const byte PASSWORD_FLAG_SIZE = 0x01; internal const Byte PASSWORD_FLAG_SIZE = 0x01;
internal const byte WILL_RETAIN_FLAG_MASK = 0x20; internal const Byte WILL_RETAIN_FLAG_MASK = 0x20;
internal const byte WILL_RETAIN_FLAG_OFFSET = 0x05; internal const Byte WILL_RETAIN_FLAG_OFFSET = 0x05;
internal const byte WILL_RETAIN_FLAG_SIZE = 0x01; internal const Byte WILL_RETAIN_FLAG_SIZE = 0x01;
internal const byte WILL_QOS_FLAG_MASK = 0x18; internal const Byte WILL_QOS_FLAG_MASK = 0x18;
internal const byte WILL_QOS_FLAG_OFFSET = 0x03; internal const Byte WILL_QOS_FLAG_OFFSET = 0x03;
internal const byte WILL_QOS_FLAG_SIZE = 0x02; internal const Byte WILL_QOS_FLAG_SIZE = 0x02;
internal const byte WILL_FLAG_MASK = 0x04; internal const Byte WILL_FLAG_MASK = 0x04;
internal const byte WILL_FLAG_OFFSET = 0x02; internal const Byte WILL_FLAG_OFFSET = 0x02;
internal const byte WILL_FLAG_SIZE = 0x01; internal const Byte WILL_FLAG_SIZE = 0x01;
internal const byte CLEAN_SESSION_FLAG_MASK = 0x02; internal const Byte CLEAN_SESSION_FLAG_MASK = 0x02;
internal const byte CLEAN_SESSION_FLAG_OFFSET = 0x01; internal const Byte CLEAN_SESSION_FLAG_OFFSET = 0x01;
internal const byte CLEAN_SESSION_FLAG_SIZE = 0x01; internal const Byte CLEAN_SESSION_FLAG_SIZE = 0x01;
// [v.3.1.1] lsb (reserved) must be now 0 // [v.3.1.1] lsb (reserved) must be now 0
internal const byte RESERVED_FLAG_MASK = 0x01; internal const Byte RESERVED_FLAG_MASK = 0x01;
internal const byte RESERVED_FLAG_OFFSET = 0x00; internal const Byte RESERVED_FLAG_OFFSET = 0x00;
internal const byte RESERVED_FLAG_SIZE = 0x01; internal const Byte RESERVED_FLAG_SIZE = 0x01;
#endregion #endregion
@ -78,153 +76,81 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <summary> /// <summary>
/// Protocol name /// Protocol name
/// </summary> /// </summary>
public string ProtocolName public String ProtocolName { get; set; }
{
get { return this.protocolName; }
set { this.protocolName = value; }
}
/// <summary> /// <summary>
/// Protocol version /// Protocol version
/// </summary> /// </summary>
public byte ProtocolVersion public Byte ProtocolVersion { get; set; }
{
get { return this.protocolVersion; }
set { this.protocolVersion = value; }
}
/// <summary> /// <summary>
/// Client identifier /// Client identifier
/// </summary> /// </summary>
public string ClientId public String ClientId { get; set; }
{
get { return this.clientId; }
set { this.clientId = value; }
}
/// <summary> /// <summary>
/// Will retain flag /// Will retain flag
/// </summary> /// </summary>
public bool WillRetain public Boolean WillRetain { get; set; }
{
get { return this.willRetain; }
set { this.willRetain = value; }
}
/// <summary> /// <summary>
/// Will QOS level /// Will QOS level
/// </summary> /// </summary>
public byte WillQosLevel public Byte WillQosLevel { get; set; }
{
get { return this.willQosLevel; }
set { this.willQosLevel = value; }
}
/// <summary> /// <summary>
/// Will flag /// Will flag
/// </summary> /// </summary>
public bool WillFlag public Boolean WillFlag { get; set; }
{
get { return this.willFlag; }
set { this.willFlag = value; }
}
/// <summary> /// <summary>
/// Will topic /// Will topic
/// </summary> /// </summary>
public string WillTopic public String WillTopic { get; set; }
{
get { return this.willTopic; }
set { this.willTopic = value; }
}
/// <summary> /// <summary>
/// Will message /// Will message
/// </summary> /// </summary>
public string WillMessage public String WillMessage { get; set; }
{
get { return this.willMessage; }
set { this.willMessage = value; }
}
/// <summary> /// <summary>
/// Username /// Username
/// </summary> /// </summary>
public string Username public String Username { get; set; }
{
get { return this.username; }
set { this.username = value; }
}
/// <summary> /// <summary>
/// Password /// Password
/// </summary> /// </summary>
public string Password public String Password { get; set; }
{
get { return this.password; }
set { this.password = value; }
}
/// <summary> /// <summary>
/// Clean session flag /// Clean session flag
/// </summary> /// </summary>
public bool CleanSession public Boolean CleanSession { get; set; }
{
get { return this.cleanSession; }
set { this.cleanSession = value; }
}
/// <summary> /// <summary>
/// Keep alive period /// Keep alive period
/// </summary> /// </summary>
public ushort KeepAlivePeriod public UInt16 KeepAlivePeriod { get; set; }
{
get { return this.keepAlivePeriod; }
set { this.keepAlivePeriod = value; }
}
#endregion #endregion
// protocol name // protocol name
private string protocolName;
// protocol version
private byte protocolVersion;
// client identifier
private string clientId;
// will retain flag // will retain flag
protected bool willRetain;
// will quality of service level // 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> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
public MqttMsgConnect() public MqttMsgConnect() => this.Type = MQTT_MSG_CONNECT_TYPE;
{
this.type = MQTT_MSG_CONNECT_TYPE;
}
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
/// <param name="clientId">Client identifier</param> /// <param name="clientId">Client identifier</param>
public MqttMsgConnect(string clientId) : 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) this(clientId, null, null, false, QOS_LEVEL_AT_LEAST_ONCE, false, null, null, true, KEEP_ALIVE_PERIOD_DEFAULT, PROTOCOL_VERSION_V3_1_1) {
{
} }
/// <summary> /// <summary>
@ -241,34 +167,33 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <param name="cleanSession">Clean sessione flag</param> /// <param name="cleanSession">Clean sessione flag</param>
/// <param name="keepAlivePeriod">Keep alive period</param> /// <param name="keepAlivePeriod">Keep alive period</param>
/// <param name="protocolVersion">Protocol version</param> /// <param name="protocolVersion">Protocol version</param>
public MqttMsgConnect(string clientId, public MqttMsgConnect(String clientId,
string username, String username,
string password, String password,
bool willRetain, Boolean willRetain,
byte willQosLevel, Byte willQosLevel,
bool willFlag, Boolean willFlag,
string willTopic, String willTopic,
string willMessage, String willMessage,
bool cleanSession, Boolean cleanSession,
ushort keepAlivePeriod, UInt16 keepAlivePeriod,
byte protocolVersion Byte protocolVersion
) ) {
{ this.Type = MQTT_MSG_CONNECT_TYPE;
this.type = MQTT_MSG_CONNECT_TYPE;
this.clientId = clientId; this.ClientId = clientId;
this.username = username; this.Username = username;
this.password = password; this.Password = password;
this.willRetain = willRetain; this.WillRetain = willRetain;
this.willQosLevel = willQosLevel; this.WillQosLevel = willQosLevel;
this.willFlag = willFlag; this.WillFlag = willFlag;
this.willTopic = willTopic; this.WillTopic = willTopic;
this.willMessage = willMessage; this.WillMessage = willMessage;
this.cleanSession = cleanSession; this.CleanSession = cleanSession;
this.keepAlivePeriod = keepAlivePeriod; this.KeepAlivePeriod = keepAlivePeriod;
// [v.3.1.1] added new protocol name and version // [v.3.1.1] added new protocol name and version
this.protocolVersion = protocolVersion; this.ProtocolVersion = protocolVersion;
this.protocolName = (this.protocolVersion == PROTOCOL_VERSION_V3_1_1) ? PROTOCOL_NAME_V3_1_1 : PROTOCOL_NAME_V3_1; this.ProtocolName = (this.ProtocolVersion == PROTOCOL_VERSION_V3_1_1) ? PROTOCOL_NAME_V3_1_1 : PROTOCOL_NAME_V3_1;
} }
/// <summary> /// <summary>
@ -278,171 +203,168 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <param name="protocolVersion">Protocol Version</param> /// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param> /// <param name="channel">Channel connected to the broker</param>
/// <returns>CONNECT message instance</returns> /// <returns>CONNECT message instance</returns>
public static MqttMsgConnect Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) public static MqttMsgConnect Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
{ Byte[] buffer;
byte[] buffer; Int32 index = 0;
int index = 0; Int32 protNameUtf8Length;
int protNameUtf8Length; Byte[] protNameUtf8;
byte[] protNameUtf8; Boolean isUsernameFlag;
bool isUsernameFlag; Boolean isPasswordFlag;
bool isPasswordFlag; Int32 clientIdUtf8Length;
int clientIdUtf8Length; Byte[] clientIdUtf8;
byte[] clientIdUtf8; Int32 willTopicUtf8Length;
int willTopicUtf8Length; Byte[] willTopicUtf8;
byte[] willTopicUtf8; Int32 willMessageUtf8Length;
int willMessageUtf8Length; Byte[] willMessageUtf8;
byte[] willMessageUtf8; Int32 usernameUtf8Length;
int usernameUtf8Length; Byte[] usernameUtf8;
byte[] usernameUtf8; Int32 passwordUtf8Length;
int passwordUtf8Length; Byte[] passwordUtf8;
byte[] passwordUtf8;
MqttMsgConnect msg = new MqttMsgConnect(); MqttMsgConnect msg = new MqttMsgConnect();
// get remaining length and allocate buffer // get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
buffer = new byte[remainingLength]; buffer = new Byte[remainingLength];
// read bytes from socket... // read bytes from socket...
channel.Receive(buffer); _ = channel.Receive(buffer);
// protocol name // protocol name
protNameUtf8Length = ((buffer[index++] << 8) & 0xFF00); protNameUtf8Length = (buffer[index++] << 8) & 0xFF00;
protNameUtf8Length |= buffer[index++]; protNameUtf8Length |= buffer[index++];
protNameUtf8 = new byte[protNameUtf8Length]; protNameUtf8 = new Byte[protNameUtf8Length];
Array.Copy(buffer, index, protNameUtf8, 0, protNameUtf8Length); Array.Copy(buffer, index, protNameUtf8, 0, protNameUtf8Length);
index += protNameUtf8Length; index += protNameUtf8Length;
msg.protocolName = new String(Encoding.UTF8.GetChars(protNameUtf8)); msg.ProtocolName = new String(Encoding.UTF8.GetChars(protNameUtf8));
// [v3.1.1] wrong protocol name // [v3.1.1] wrong protocol name
if (!msg.protocolName.Equals(PROTOCOL_NAME_V3_1) && !msg.protocolName.Equals(PROTOCOL_NAME_V3_1_1)) if (!msg.ProtocolName.Equals(PROTOCOL_NAME_V3_1) && !msg.ProtocolName.Equals(PROTOCOL_NAME_V3_1_1)) {
throw new MqttClientException(MqttClientErrorCode.InvalidProtocolName); throw new MqttClientException(MqttClientErrorCode.InvalidProtocolName);
}
// protocol version // protocol version
msg.protocolVersion = buffer[index]; msg.ProtocolVersion = buffer[index];
index += PROTOCOL_VERSION_SIZE; index += PROTOCOL_VERSION_SIZE;
// connect flags // connect flags
// [v3.1.1] check lsb (reserved) must be 0 // [v3.1.1] check lsb (reserved) must be 0
if ((msg.protocolVersion == PROTOCOL_VERSION_V3_1_1) && if (msg.ProtocolVersion == PROTOCOL_VERSION_V3_1_1 &&
((buffer[index] & RESERVED_FLAG_MASK) != 0x00)) (buffer[index] & RESERVED_FLAG_MASK) != 0x00) {
throw new MqttClientException(MqttClientErrorCode.InvalidConnectFlags); throw new MqttClientException(MqttClientErrorCode.InvalidConnectFlags);
}
isUsernameFlag = (buffer[index] & USERNAME_FLAG_MASK) != 0x00; isUsernameFlag = (buffer[index] & USERNAME_FLAG_MASK) != 0x00;
isPasswordFlag = (buffer[index] & PASSWORD_FLAG_MASK) != 0x00; isPasswordFlag = (buffer[index] & PASSWORD_FLAG_MASK) != 0x00;
msg.willRetain = (buffer[index] & WILL_RETAIN_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.WillQosLevel = (Byte)((buffer[index] & WILL_QOS_FLAG_MASK) >> WILL_QOS_FLAG_OFFSET);
msg.willFlag = (buffer[index] & WILL_FLAG_MASK) != 0x00; msg.WillFlag = (buffer[index] & WILL_FLAG_MASK) != 0x00;
msg.cleanSession = (buffer[index] & CLEAN_SESSION_FLAG_MASK) != 0x00; msg.CleanSession = (buffer[index] & CLEAN_SESSION_FLAG_MASK) != 0x00;
index += CONNECT_FLAGS_SIZE; index += CONNECT_FLAGS_SIZE;
// keep alive timer // keep alive timer
msg.keepAlivePeriod = (ushort)((buffer[index++] << 8) & 0xFF00); msg.KeepAlivePeriod = (UInt16)((buffer[index++] << 8) & 0xFF00);
msg.keepAlivePeriod |= buffer[index++]; msg.KeepAlivePeriod |= buffer[index++];
// client identifier [v3.1.1] it may be zero bytes long (empty string) // client identifier [v3.1.1] it may be zero bytes long (empty string)
clientIdUtf8Length = ((buffer[index++] << 8) & 0xFF00); clientIdUtf8Length = (buffer[index++] << 8) & 0xFF00;
clientIdUtf8Length |= buffer[index++]; clientIdUtf8Length |= buffer[index++];
clientIdUtf8 = new byte[clientIdUtf8Length]; clientIdUtf8 = new Byte[clientIdUtf8Length];
Array.Copy(buffer, index, clientIdUtf8, 0, clientIdUtf8Length); Array.Copy(buffer, index, clientIdUtf8, 0, clientIdUtf8Length);
index += clientIdUtf8Length; index += clientIdUtf8Length;
msg.clientId = new String(Encoding.UTF8.GetChars(clientIdUtf8)); msg.ClientId = new String(Encoding.UTF8.GetChars(clientIdUtf8));
// [v3.1.1] if client identifier is zero bytes long, clean session must be true // [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)) if (msg.ProtocolVersion == PROTOCOL_VERSION_V3_1_1 && clientIdUtf8Length == 0 && !msg.CleanSession) {
throw new MqttClientException(MqttClientErrorCode.InvalidClientId); throw new MqttClientException(MqttClientErrorCode.InvalidClientId);
}
// will topic and will message // will topic and will message
if (msg.willFlag) if (msg.WillFlag) {
{ willTopicUtf8Length = (buffer[index++] << 8) & 0xFF00;
willTopicUtf8Length = ((buffer[index++] << 8) & 0xFF00);
willTopicUtf8Length |= buffer[index++]; willTopicUtf8Length |= buffer[index++];
willTopicUtf8 = new byte[willTopicUtf8Length]; willTopicUtf8 = new Byte[willTopicUtf8Length];
Array.Copy(buffer, index, willTopicUtf8, 0, willTopicUtf8Length); Array.Copy(buffer, index, willTopicUtf8, 0, willTopicUtf8Length);
index += willTopicUtf8Length; index += willTopicUtf8Length;
msg.willTopic = new String(Encoding.UTF8.GetChars(willTopicUtf8)); msg.WillTopic = new String(Encoding.UTF8.GetChars(willTopicUtf8));
willMessageUtf8Length = ((buffer[index++] << 8) & 0xFF00); willMessageUtf8Length = (buffer[index++] << 8) & 0xFF00;
willMessageUtf8Length |= buffer[index++]; willMessageUtf8Length |= buffer[index++];
willMessageUtf8 = new byte[willMessageUtf8Length]; willMessageUtf8 = new Byte[willMessageUtf8Length];
Array.Copy(buffer, index, willMessageUtf8, 0, willMessageUtf8Length); Array.Copy(buffer, index, willMessageUtf8, 0, willMessageUtf8Length);
index += willMessageUtf8Length; index += willMessageUtf8Length;
msg.willMessage = new String(Encoding.UTF8.GetChars(willMessageUtf8)); msg.WillMessage = new String(Encoding.UTF8.GetChars(willMessageUtf8));
} }
// username // username
if (isUsernameFlag) if (isUsernameFlag) {
{ usernameUtf8Length = (buffer[index++] << 8) & 0xFF00;
usernameUtf8Length = ((buffer[index++] << 8) & 0xFF00);
usernameUtf8Length |= buffer[index++]; usernameUtf8Length |= buffer[index++];
usernameUtf8 = new byte[usernameUtf8Length]; usernameUtf8 = new Byte[usernameUtf8Length];
Array.Copy(buffer, index, usernameUtf8, 0, usernameUtf8Length); Array.Copy(buffer, index, usernameUtf8, 0, usernameUtf8Length);
index += usernameUtf8Length; index += usernameUtf8Length;
msg.username = new String(Encoding.UTF8.GetChars(usernameUtf8)); msg.Username = new String(Encoding.UTF8.GetChars(usernameUtf8));
} }
// password // password
if (isPasswordFlag) if (isPasswordFlag) {
{ passwordUtf8Length = (buffer[index++] << 8) & 0xFF00;
passwordUtf8Length = ((buffer[index++] << 8) & 0xFF00);
passwordUtf8Length |= buffer[index++]; passwordUtf8Length |= buffer[index++];
passwordUtf8 = new byte[passwordUtf8Length]; passwordUtf8 = new Byte[passwordUtf8Length];
Array.Copy(buffer, index, passwordUtf8, 0, passwordUtf8Length); Array.Copy(buffer, index, passwordUtf8, 0, passwordUtf8Length);
index += passwordUtf8Length; msg.Password = new String(Encoding.UTF8.GetChars(passwordUtf8));
msg.password = new String(Encoding.UTF8.GetChars(passwordUtf8));
} }
return msg; return msg;
} }
public override byte[] GetBytes(byte protocolVersion) public override Byte[] GetBytes(Byte protocolVersion) {
{ Int32 varHeaderSize = 0;
int fixedHeaderSize = 0; Int32 payloadSize = 0;
int varHeaderSize = 0; Int32 remainingLength = 0;
int payloadSize = 0; Byte[] buffer;
int remainingLength = 0; Int32 index = 0;
byte[] buffer;
int index = 0;
byte[] clientIdUtf8 = Encoding.UTF8.GetBytes(this.clientId); Byte[] clientIdUtf8 = Encoding.UTF8.GetBytes(this.ClientId);
byte[] willTopicUtf8 = (this.willFlag && (this.willTopic != null)) ? Encoding.UTF8.GetBytes(this.willTopic) : null; 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[] 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[] 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; Byte[] passwordUtf8 = (this.Password != null && this.Password.Length > 0) ? Encoding.UTF8.GetBytes(this.Password) : null;
// [v3.1.1] // [v3.1.1]
if (this.protocolVersion == PROTOCOL_VERSION_V3_1_1) if (this.ProtocolVersion == PROTOCOL_VERSION_V3_1_1) {
{
// will flag set, will topic and will message MUST be present // will flag set, will topic and will message MUST be present
if (this.willFlag && ((this.willQosLevel >= 0x03) || if (this.WillFlag && (this.WillQosLevel >= 0x03 ||
(willTopicUtf8 == null) || (willMessageUtf8 == null) || willTopicUtf8 == null || willMessageUtf8 == null ||
((willTopicUtf8 != null) && (willTopicUtf8.Length == 0)) || willTopicUtf8 != null && willTopicUtf8.Length == 0 ||
((willMessageUtf8 != null) && (willMessageUtf8.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); 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) if (this.KeepAlivePeriod > MAX_KEEP_ALIVE) {
throw new MqttClientException(MqttClientErrorCode.KeepAliveWrong); throw new MqttClientException(MqttClientErrorCode.KeepAliveWrong);
}
// check on will QoS Level // check on will QoS Level
if ((this.willQosLevel < MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE) || if (this.WillQosLevel < MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE ||
(this.willQosLevel > MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE)) this.WillQosLevel > MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE) {
throw new MqttClientException(MqttClientErrorCode.WillWrong); throw new MqttClientException(MqttClientErrorCode.WillWrong);
}
// protocol name field size // protocol name field size
// MQTT version 3.1 // MQTT version 3.1
if (this.protocolVersion == PROTOCOL_VERSION_V3_1) if (this.ProtocolVersion == PROTOCOL_VERSION_V3_1) {
{ varHeaderSize += PROTOCOL_NAME_LEN_SIZE + PROTOCOL_NAME_V3_1_SIZE;
varHeaderSize += (PROTOCOL_NAME_LEN_SIZE + PROTOCOL_NAME_V3_1_SIZE);
} }
// MQTT version 3.1.1 // MQTT version 3.1.1
else else {
{ varHeaderSize += PROTOCOL_NAME_LEN_SIZE + PROTOCOL_NAME_V3_1_1_SIZE;
varHeaderSize += (PROTOCOL_NAME_LEN_SIZE + PROTOCOL_NAME_V3_1_1_SIZE);
} }
// protocol level field size // protocol level field size
varHeaderSize += PROTOCOL_VERSION_SIZE; varHeaderSize += PROTOCOL_VERSION_SIZE;
@ -462,34 +384,32 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
// password field size // password field size
payloadSize += (passwordUtf8 != null) ? (passwordUtf8.Length + 2) : 0; payloadSize += (passwordUtf8 != null) ? (passwordUtf8.Length + 2) : 0;
remainingLength += (varHeaderSize + payloadSize); remainingLength += varHeaderSize + payloadSize;
// first byte of fixed header // first byte of fixed header
fixedHeaderSize = 1; Int32 fixedHeaderSize = 1;
int temp = remainingLength; Int32 temp = remainingLength;
// increase fixed header size based on remaining length // increase fixed header size based on remaining length
// (each remaining length byte can encode until 128) // (each remaining length byte can encode until 128)
do do {
{
fixedHeaderSize++; fixedHeaderSize++;
temp = temp / 128; temp /= 128;
} while (temp > 0); } while (temp > 0);
// allocate buffer for message // allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize]; buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte // first fixed header byte
buffer[index++] = (MQTT_MSG_CONNECT_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_CONNECT_FLAG_BITS; // [v.3.1.1] buffer[index++] = (MQTT_MSG_CONNECT_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_CONNECT_FLAG_BITS; // [v.3.1.1]
// encode remaining length // encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index); index = this.EncodeRemainingLength(remainingLength, buffer, index);
// protocol name // protocol name
buffer[index++] = 0; // MSB protocol name size buffer[index++] = 0; // MSB protocol name size
// MQTT version 3.1 // MQTT version 3.1
if (this.protocolVersion == PROTOCOL_VERSION_V3_1) if (this.ProtocolVersion == PROTOCOL_VERSION_V3_1) {
{
buffer[index++] = PROTOCOL_NAME_V3_1_SIZE; // LSB protocol name size 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); Array.Copy(Encoding.UTF8.GetBytes(PROTOCOL_NAME_V3_1), 0, buffer, index, PROTOCOL_NAME_V3_1_SIZE);
index += PROTOCOL_NAME_V3_1_SIZE; index += PROTOCOL_NAME_V3_1_SIZE;
@ -497,8 +417,7 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
buffer[index++] = PROTOCOL_VERSION_V3_1; buffer[index++] = PROTOCOL_VERSION_V3_1;
} }
// MQTT version 3.1.1 // MQTT version 3.1.1
else else {
{
buffer[index++] = PROTOCOL_NAME_V3_1_1_SIZE; // LSB protocol name size 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); 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; index += PROTOCOL_NAME_V3_1_1_SIZE;
@ -507,76 +426,73 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
} }
// connect flags // connect flags
byte connectFlags = 0x00; Byte connectFlags = 0x00;
connectFlags |= (usernameUtf8 != null) ? (byte)(1 << USERNAME_FLAG_OFFSET) : (byte)0x00; connectFlags |= (usernameUtf8 != null) ? (Byte)(1 << USERNAME_FLAG_OFFSET) : (Byte)0x00;
connectFlags |= (passwordUtf8 != null) ? (byte)(1 << PASSWORD_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; 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) // only if will flag is set, we have to use will QoS level (otherwise is MUST be 0)
if (this.willFlag) if (this.WillFlag) {
connectFlags |= (byte)(this.willQosLevel << WILL_QOS_FLAG_OFFSET); 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;
connectFlags |= this.WillFlag ? (Byte)(1 << WILL_FLAG_OFFSET) : (Byte)0x00;
connectFlags |= this.CleanSession ? (Byte)(1 << CLEAN_SESSION_FLAG_OFFSET) : (Byte)0x00;
buffer[index++] = connectFlags; buffer[index++] = connectFlags;
// keep alive period // keep alive period
buffer[index++] = (byte)((this.keepAlivePeriod >> 8) & 0x00FF); // MSB buffer[index++] = (Byte)((this.KeepAlivePeriod >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(this.keepAlivePeriod & 0x00FF); // LSB buffer[index++] = (Byte)(this.KeepAlivePeriod & 0x00FF); // LSB
// client identifier // client identifier
buffer[index++] = (byte)((clientIdUtf8.Length >> 8) & 0x00FF); // MSB buffer[index++] = (Byte)((clientIdUtf8.Length >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(clientIdUtf8.Length & 0x00FF); // LSB buffer[index++] = (Byte)(clientIdUtf8.Length & 0x00FF); // LSB
Array.Copy(clientIdUtf8, 0, buffer, index, clientIdUtf8.Length); Array.Copy(clientIdUtf8, 0, buffer, index, clientIdUtf8.Length);
index += clientIdUtf8.Length; index += clientIdUtf8.Length;
// will topic // will topic
if (this.willFlag && (willTopicUtf8 != null)) if (this.WillFlag && willTopicUtf8 != null) {
{ buffer[index++] = (Byte)((willTopicUtf8.Length >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)((willTopicUtf8.Length >> 8) & 0x00FF); // MSB buffer[index++] = (Byte)(willTopicUtf8.Length & 0x00FF); // LSB
buffer[index++] = (byte)(willTopicUtf8.Length & 0x00FF); // LSB
Array.Copy(willTopicUtf8, 0, buffer, index, willTopicUtf8.Length); Array.Copy(willTopicUtf8, 0, buffer, index, willTopicUtf8.Length);
index += willTopicUtf8.Length; index += willTopicUtf8.Length;
} }
// will message // will message
if (this.willFlag && (willMessageUtf8 != null)) if (this.WillFlag && willMessageUtf8 != null) {
{ buffer[index++] = (Byte)((willMessageUtf8.Length >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)((willMessageUtf8.Length >> 8) & 0x00FF); // MSB buffer[index++] = (Byte)(willMessageUtf8.Length & 0x00FF); // LSB
buffer[index++] = (byte)(willMessageUtf8.Length & 0x00FF); // LSB
Array.Copy(willMessageUtf8, 0, buffer, index, willMessageUtf8.Length); Array.Copy(willMessageUtf8, 0, buffer, index, willMessageUtf8.Length);
index += willMessageUtf8.Length; index += willMessageUtf8.Length;
} }
// username // username
if (usernameUtf8 != null) if (usernameUtf8 != null) {
{ buffer[index++] = (Byte)((usernameUtf8.Length >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)((usernameUtf8.Length >> 8) & 0x00FF); // MSB buffer[index++] = (Byte)(usernameUtf8.Length & 0x00FF); // LSB
buffer[index++] = (byte)(usernameUtf8.Length & 0x00FF); // LSB
Array.Copy(usernameUtf8, 0, buffer, index, usernameUtf8.Length); Array.Copy(usernameUtf8, 0, buffer, index, usernameUtf8.Length);
index += usernameUtf8.Length; index += usernameUtf8.Length;
} }
// password // password
if (passwordUtf8 != null) if (passwordUtf8 != null) {
{ buffer[index++] = (Byte)((passwordUtf8.Length >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)((passwordUtf8.Length >> 8) & 0x00FF); // MSB buffer[index++] = (Byte)(passwordUtf8.Length & 0x00FF); // LSB
buffer[index++] = (byte)(passwordUtf8.Length & 0x00FF); // LSB
Array.Copy(passwordUtf8, 0, buffer, index, passwordUtf8.Length); Array.Copy(passwordUtf8, 0, buffer, index, passwordUtf8.Length);
index += passwordUtf8.Length; _ = passwordUtf8.Length;
} }
return buffer; return buffer;
} }
public override string ToString() public override String ToString() =>
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"CONNECT", "CONNECT",
new object[] { "protocolName", "protocolVersion", "clientId", "willFlag", "willRetain", "willQosLevel", "willTopic", "willMessage", "username", "password", "cleanSession", "keepAlivePeriod" }, 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 }); 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 #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -14,19 +14,17 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System; using System;
#else #else
using Microsoft.SPOT; using Microsoft.SPOT;
#endif #endif
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Event Args class for CONNECT message received from client /// Event Args class for CONNECT message received from client
/// </summary> /// </summary>
public class MqttMsgConnectEventArgs : EventArgs public class MqttMsgConnectEventArgs : EventArgs {
{
/// <summary> /// <summary>
/// Message received from client /// Message received from client
/// </summary> /// </summary>
@ -36,9 +34,6 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// Constructor /// Constructor
/// </summary> /// </summary>
/// <param name="msg">CONNECT message received from client</param> /// <param name="msg">CONNECT message received from client</param>
public MqttMsgConnectEventArgs(MqttMsgConnect connect) public MqttMsgConnectEventArgs(MqttMsgConnect connect) => this.Message = connect;
{
this.Message = connect;
}
} }
} }

View File

@ -15,15 +15,12 @@ Contributors:
*/ */
using System; using System;
using System.Text;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Context for MQTT message /// Context for MQTT message
/// </summary> /// </summary>
public class MqttMsgContext public class MqttMsgContext {
{
/// <summary> /// <summary>
/// MQTT message /// MQTT message
/// </summary> /// </summary>
@ -42,27 +39,23 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <summary> /// <summary>
/// Timestamp in ticks (for retry) /// Timestamp in ticks (for retry)
/// </summary> /// </summary>
public int Timestamp { get; set; } public Int32 Timestamp { get; set; }
/// <summary> /// <summary>
/// Attempt (for retry) /// Attempt (for retry)
/// </summary> /// </summary>
public int Attempt { get; set; } public Int32 Attempt { get; set; }
/// <summary> /// <summary>
/// Unique key /// Unique key
/// </summary> /// </summary>
public string Key public String Key => this.Flow + "_" + this.Message.MessageId;
{
get { return this.Flow + "_" + this.Message.MessageId; }
}
} }
/// <summary> /// <summary>
/// Flow of the message /// Flow of the message
/// </summary> /// </summary>
public enum MqttMsgFlow public enum MqttMsgFlow {
{
/// <summary> /// <summary>
/// To publish to subscribers /// To publish to subscribers
/// </summary> /// </summary>
@ -77,8 +70,7 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <summary> /// <summary>
/// MQTT message state /// MQTT message state
/// </summary> /// </summary>
public enum MqttMsgState public enum MqttMsgState {
{
/// <summary> /// <summary>
/// QOS = 0, Message queued /// QOS = 0, Message queued
/// </summary> /// </summary>

View File

@ -14,22 +14,18 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
using System;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Class for DISCONNECT message from client to broker /// Class for DISCONNECT message from client to broker
/// </summary> /// </summary>
public class MqttMsgDisconnect : MqttMsgBase public class MqttMsgDisconnect : MqttMsgBase {
{
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
public MqttMsgDisconnect() public MqttMsgDisconnect() => this.Type = MQTT_MSG_DISCONNECT_TYPE;
{
this.type = MQTT_MSG_DISCONNECT_TYPE;
}
/// <summary> /// <summary>
/// Parse bytes for a DISCONNECT message /// Parse bytes for a DISCONNECT message
@ -38,49 +34,46 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <param name="protocolVersion">Protocol Version</param> /// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param> /// <param name="channel">Channel connected to the broker</param>
/// <returns>DISCONNECT message instance</returns> /// <returns>DISCONNECT message instance</returns>
public static MqttMsgDisconnect Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) public static MqttMsgDisconnect Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
{
MqttMsgDisconnect msg = new MqttMsgDisconnect(); MqttMsgDisconnect msg = new MqttMsgDisconnect();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
{
// [v3.1.1] check flag bits // [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_DISCONNECT_FLAG_BITS) if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_DISCONNECT_FLAG_BITS) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
} }
}
// get remaining length and allocate buffer // get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); _ = DecodeRemainingLength(channel);
// NOTE : remainingLength must be 0 // NOTE : remainingLength must be 0
return msg; return msg;
} }
public override byte[] GetBytes(byte protocolVersion) public override Byte[] GetBytes(Byte protocolVersion) {
{ Byte[] buffer = new Byte[2];
byte[] buffer = new byte[2]; Int32 index = 0;
int index = 0;
// first fixed header byte // first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) buffer[index++] = 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] ? (Byte)((MQTT_MSG_DISCONNECT_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_DISCONNECT_FLAG_BITS)
else : (Byte)(MQTT_MSG_DISCONNECT_TYPE << MSG_TYPE_OFFSET);
buffer[index++] = (MQTT_MSG_DISCONNECT_TYPE << MSG_TYPE_OFFSET);
buffer[index++] = 0x00; buffer[index++] = 0x00;
return buffer; return buffer;
} }
public override string ToString() public override String ToString() =>
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"DISCONNECT", "DISCONNECT",
null, null,
null); null);
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -14,33 +14,28 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
using System;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Class for PINGREQ message from client to broker /// Class for PINGREQ message from client to broker
/// </summary> /// </summary>
public class MqttMsgPingReq : MqttMsgBase public class MqttMsgPingReq : MqttMsgBase {
{
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
public MqttMsgPingReq() public MqttMsgPingReq() => this.Type = MQTT_MSG_PINGREQ_TYPE;
{
this.type = MQTT_MSG_PINGREQ_TYPE;
}
public override byte[] GetBytes(byte protocolVersion) public override Byte[] GetBytes(Byte protocolVersion) {
{ Byte[] buffer = new Byte[2];
byte[] buffer = new byte[2]; Int32 index = 0;
int index = 0;
// first fixed header byte // first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) buffer[index++] = 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] ? (Byte)((MQTT_MSG_PINGREQ_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PINGREQ_FLAG_BITS)
else : (Byte)(MQTT_MSG_PINGREQ_TYPE << MSG_TYPE_OFFSET);
buffer[index++] = (MQTT_MSG_PINGREQ_TYPE << MSG_TYPE_OFFSET);
buffer[index++] = 0x00; buffer[index++] = 0x00;
return buffer; return buffer;
@ -53,34 +48,32 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <param name="protocolVersion">Protocol Version</param> /// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param> /// <param name="channel">Channel connected to the broker</param>
/// <returns>PINGREQ message instance</returns> /// <returns>PINGREQ message instance</returns>
public static MqttMsgPingReq Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) public static MqttMsgPingReq Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
{
MqttMsgPingReq msg = new MqttMsgPingReq(); MqttMsgPingReq msg = new MqttMsgPingReq();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
{
// [v3.1.1] check flag bits // [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGREQ_FLAG_BITS) if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGREQ_FLAG_BITS) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
} }
}
// already know remaininglength is zero (MQTT specification), // already know remaininglength is zero (MQTT specification),
// so it isn't necessary to read other data from socket // so it isn't necessary to read other data from socket
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); _ = DecodeRemainingLength(channel);
return msg; return msg;
} }
public override string ToString() public override String ToString() =>
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"PINGREQ", "PINGREQ",
null, null,
null); null);
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -17,20 +17,15 @@ Contributors:
using System; using System;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Class for PINGRESP message from client to broker /// Class for PINGRESP message from client to broker
/// </summary> /// </summary>
public class MqttMsgPingResp : MqttMsgBase public class MqttMsgPingResp : MqttMsgBase {
{
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
public MqttMsgPingResp() public MqttMsgPingResp() => this.Type = MQTT_MSG_PINGRESP_TYPE;
{
this.type = MQTT_MSG_PINGRESP_TYPE;
}
/// <summary> /// <summary>
/// Parse bytes for a PINGRESP message /// Parse bytes for a PINGRESP message
@ -39,49 +34,46 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <param name="protocolVersion">Protocol Version</param> /// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param> /// <param name="channel">Channel connected to the broker</param>
/// <returns>PINGRESP message instance</returns> /// <returns>PINGRESP message instance</returns>
public static MqttMsgPingResp Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) public static MqttMsgPingResp Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
{
MqttMsgPingResp msg = new MqttMsgPingResp(); MqttMsgPingResp msg = new MqttMsgPingResp();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
{
// [v3.1.1] check flag bits // [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGRESP_FLAG_BITS) if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGRESP_FLAG_BITS) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
} }
}
// already know remaininglength is zero (MQTT specification), // already know remaininglength is zero (MQTT specification),
// so it isn't necessary to read other data from socket // so it isn't necessary to read other data from socket
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); _ = DecodeRemainingLength(channel);
return msg; return msg;
} }
public override byte[] GetBytes(byte protocolVersion) public override Byte[] GetBytes(Byte protocolVersion) {
{ Byte[] buffer = new Byte[2];
byte[] buffer = new byte[2]; Int32 index = 0;
int index = 0;
// first fixed header byte // first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) buffer[index++] = 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] ? (Byte)((MQTT_MSG_PINGRESP_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PINGRESP_FLAG_BITS)
else : (Byte)(MQTT_MSG_PINGRESP_TYPE << MSG_TYPE_OFFSET);
buffer[index++] = (MQTT_MSG_PINGRESP_TYPE << MSG_TYPE_OFFSET);
buffer[index++] = 0x00; buffer[index++] = 0x00;
return buffer; return buffer;
} }
public override string ToString() public override String ToString() =>
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"PINGRESP", "PINGRESP",
null, null,
null); null);
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -14,64 +14,56 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
using System;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Class for PUBACK message from broker to client /// Class for PUBACK message from broker to client
/// </summary> /// </summary>
public class MqttMsgPuback : MqttMsgBase public class MqttMsgPuback : MqttMsgBase {
{
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
public MqttMsgPuback() public MqttMsgPuback() => this.Type = MQTT_MSG_PUBACK_TYPE;
{
this.type = MQTT_MSG_PUBACK_TYPE;
}
public override byte[] GetBytes(byte protocolVersion) public override Byte[] GetBytes(Byte protocolVersion) {
{ Int32 varHeaderSize = 0;
int fixedHeaderSize = 0; Int32 payloadSize = 0;
int varHeaderSize = 0; Int32 remainingLength = 0;
int payloadSize = 0; Byte[] buffer;
int remainingLength = 0; Int32 index = 0;
byte[] buffer;
int index = 0;
// message identifier // message identifier
varHeaderSize += MESSAGE_ID_SIZE; varHeaderSize += MESSAGE_ID_SIZE;
remainingLength += (varHeaderSize + payloadSize); remainingLength += varHeaderSize + payloadSize;
// first byte of fixed header // first byte of fixed header
fixedHeaderSize = 1; Int32 fixedHeaderSize = 1;
int temp = remainingLength; Int32 temp = remainingLength;
// increase fixed header size based on remaining length // increase fixed header size based on remaining length
// (each remaining length byte can encode until 128) // (each remaining length byte can encode until 128)
do do {
{
fixedHeaderSize++; fixedHeaderSize++;
temp = temp / 128; temp /= 128;
} while (temp > 0); } while (temp > 0);
// allocate buffer for message // allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize]; buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte // first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) buffer[index++] = 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] ? (Byte)((MQTT_MSG_PUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBACK_FLAG_BITS)
else : (Byte)(MQTT_MSG_PUBACK_TYPE << MSG_TYPE_OFFSET);
buffer[index++] = (MQTT_MSG_PUBACK_TYPE << MSG_TYPE_OFFSET);
// encode remaining length // encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index); index = this.EncodeRemainingLength(remainingLength, buffer, index);
// get message identifier // get message identifier
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
return buffer; return buffer;
} }
@ -83,43 +75,41 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <param name="protocolVersion">Protocol Version</param> /// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param> /// <param name="channel">Channel connected to the broker</param>
/// <returns>PUBACK message instance</returns> /// <returns>PUBACK message instance</returns>
public static MqttMsgPuback Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) public static MqttMsgPuback Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
{ Byte[] buffer;
byte[] buffer; Int32 index = 0;
int index = 0;
MqttMsgPuback msg = new MqttMsgPuback(); MqttMsgPuback msg = new MqttMsgPuback();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
{
// [v3.1.1] check flag bits // [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBACK_FLAG_BITS) if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBACK_FLAG_BITS) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
} }
}
// get remaining length and allocate buffer // get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
buffer = new byte[remainingLength]; buffer = new Byte[remainingLength];
// read bytes from socket... // read bytes from socket...
channel.Receive(buffer); _ = channel.Receive(buffer);
// message id // message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]); msg.MessageId |= buffer[index++];
return msg; return msg;
} }
public override string ToString() public override String ToString() =>
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"PUBACK", "PUBACK",
new object[] { "messageId" }, new Object[] { "messageId" },
new object[] { this.messageId }); new Object[] { this.MessageId });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -14,64 +14,56 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
using System;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Class for PUBCOMP message from broker to client /// Class for PUBCOMP message from broker to client
/// </summary> /// </summary>
public class MqttMsgPubcomp : MqttMsgBase public class MqttMsgPubcomp : MqttMsgBase {
{
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
public MqttMsgPubcomp() public MqttMsgPubcomp() => this.Type = MQTT_MSG_PUBCOMP_TYPE;
{
this.type = MQTT_MSG_PUBCOMP_TYPE;
}
public override byte[] GetBytes(byte protocolVersion) public override Byte[] GetBytes(Byte protocolVersion) {
{ Int32 varHeaderSize = 0;
int fixedHeaderSize = 0; Int32 payloadSize = 0;
int varHeaderSize = 0; Int32 remainingLength = 0;
int payloadSize = 0; Byte[] buffer;
int remainingLength = 0; Int32 index = 0;
byte[] buffer;
int index = 0;
// message identifier // message identifier
varHeaderSize += MESSAGE_ID_SIZE; varHeaderSize += MESSAGE_ID_SIZE;
remainingLength += (varHeaderSize + payloadSize); remainingLength += varHeaderSize + payloadSize;
// first byte of fixed header // first byte of fixed header
fixedHeaderSize = 1; Int32 fixedHeaderSize = 1;
int temp = remainingLength; Int32 temp = remainingLength;
// increase fixed header size based on remaining length // increase fixed header size based on remaining length
// (each remaining length byte can encode until 128) // (each remaining length byte can encode until 128)
do do {
{
fixedHeaderSize++; fixedHeaderSize++;
temp = temp / 128; temp /= 128;
} while (temp > 0); } while (temp > 0);
// allocate buffer for message // allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize]; buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte // first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) buffer[index++] = 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] ? (Byte)((MQTT_MSG_PUBCOMP_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBCOMP_FLAG_BITS)
else : (Byte)(MQTT_MSG_PUBCOMP_TYPE << MSG_TYPE_OFFSET);
buffer[index++] = (MQTT_MSG_PUBCOMP_TYPE << MSG_TYPE_OFFSET);
// encode remaining length // encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index); index = this.EncodeRemainingLength(remainingLength, buffer, index);
// get message identifier // get message identifier
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
return buffer; return buffer;
} }
@ -83,43 +75,41 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <param name="protocolVersion">Protocol Version</param> /// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param> /// <param name="channel">Channel connected to the broker</param>
/// <returns>PUBCOMP message instance</returns> /// <returns>PUBCOMP message instance</returns>
public static MqttMsgPubcomp Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) public static MqttMsgPubcomp Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
{ Byte[] buffer;
byte[] buffer; Int32 index = 0;
int index = 0;
MqttMsgPubcomp msg = new MqttMsgPubcomp(); MqttMsgPubcomp msg = new MqttMsgPubcomp();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
{
// [v3.1.1] check flag bits // [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBCOMP_FLAG_BITS) if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBCOMP_FLAG_BITS) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
} }
}
// get remaining length and allocate buffer // get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
buffer = new byte[remainingLength]; buffer = new Byte[remainingLength];
// read bytes from socket... // read bytes from socket...
channel.Receive(buffer); _ = channel.Receive(buffer);
// message id // message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]); msg.MessageId |= buffer[index++];
return msg; return msg;
} }
public override string ToString() public override String ToString() =>
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"PUBCOMP", "PUBCOMP",
new object[] { "messageId" }, new Object[] { "messageId" },
new object[] { this.messageId }); new Object[] { this.MessageId });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -40,9 +40,7 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
public MqttMsgPublish() { public MqttMsgPublish() => this.Type = MQTT_MSG_PUBLISH_TYPE;
this.type = MQTT_MSG_PUBLISH_TYPE;
}
/// <summary> /// <summary>
/// Constructor /// Constructor
@ -61,17 +59,16 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
/// <param name="qosLevel">Quality of Service level</param> /// <param name="qosLevel">Quality of Service level</param>
/// <param name="retain">Retain flag</param> /// <param name="retain">Retain flag</param>
public MqttMsgPublish(String topic, Byte[] message, Boolean dupFlag, Byte qosLevel, Boolean retain) : base() { public MqttMsgPublish(String topic, Byte[] message, Boolean dupFlag, Byte qosLevel, Boolean retain) : base() {
this.type = MQTT_MSG_PUBLISH_TYPE; this.Type = MQTT_MSG_PUBLISH_TYPE;
this.Topic = topic; this.Topic = topic;
this.Message = message; this.Message = message;
this.dupFlag = dupFlag; this.DupFlag = dupFlag;
this.qosLevel = qosLevel; this.QosLevel = qosLevel;
this.retain = retain; this.Retain = retain;
this.messageId = 0; this.MessageId = 0;
} }
public override Byte[] GetBytes(Byte protocolVersion) { public override Byte[] GetBytes(Byte protocolVersion) {
Int32 fixedHeaderSize = 0;
Int32 varHeaderSize = 0; Int32 varHeaderSize = 0;
Int32 payloadSize = 0; Int32 payloadSize = 0;
Int32 remainingLength = 0; Int32 remainingLength = 0;
@ -79,17 +76,17 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
Int32 index = 0; Int32 index = 0;
// topic can't contain wildcards // topic can't contain wildcards
if ((this.Topic.IndexOf('#') != -1) || (this.Topic.IndexOf('+') != -1)) { if (this.Topic.IndexOf('#') != -1 || this.Topic.IndexOf('+') != -1) {
throw new MqttClientException(MqttClientErrorCode.TopicWildcard); throw new MqttClientException(MqttClientErrorCode.TopicWildcard);
} }
// check topic length // check topic length
if ((this.Topic.Length < MIN_TOPIC_LENGTH) || (this.Topic.Length > MAX_TOPIC_LENGTH)) { if (this.Topic.Length < MIN_TOPIC_LENGTH || this.Topic.Length > MAX_TOPIC_LENGTH) {
throw new MqttClientException(MqttClientErrorCode.TopicLength); throw new MqttClientException(MqttClientErrorCode.TopicLength);
} }
// check wrong QoS level (both bits can't be set 1) // check wrong QoS level (both bits can't be set 1)
if (this.qosLevel > QOS_LEVEL_EXACTLY_ONCE) { if (this.QosLevel > QOS_LEVEL_EXACTLY_ONCE) {
throw new MqttClientException(MqttClientErrorCode.QosNotAllowed); throw new MqttClientException(MqttClientErrorCode.QosNotAllowed);
} }
@ -99,7 +96,7 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
varHeaderSize += topicUtf8.Length + 2; varHeaderSize += topicUtf8.Length + 2;
// message id is valid only with QOS level 1 or QOS level 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)) { if (this.QosLevel == QOS_LEVEL_AT_LEAST_ONCE || this.QosLevel == QOS_LEVEL_EXACTLY_ONCE) {
varHeaderSize += MESSAGE_ID_SIZE; varHeaderSize += MESSAGE_ID_SIZE;
} }
@ -109,30 +106,30 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
payloadSize += this.Message.Length; payloadSize += this.Message.Length;
} }
remainingLength += (varHeaderSize + payloadSize); remainingLength += varHeaderSize + payloadSize;
// first byte of fixed header // first byte of fixed header
fixedHeaderSize = 1; Int32 fixedHeaderSize = 1;
Int32 temp = remainingLength; Int32 temp = remainingLength;
// increase fixed header size based on remaining length // increase fixed header size based on remaining length
// (each remaining length byte can encode until 128) // (each remaining length byte can encode until 128)
do { do {
fixedHeaderSize++; fixedHeaderSize++;
temp = temp / 128; temp /= 128;
} while (temp > 0); } while (temp > 0);
// allocate buffer for message // allocate buffer for message
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize]; buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte // first fixed header byte
buffer[index] = (Byte)((MQTT_MSG_PUBLISH_TYPE << MSG_TYPE_OFFSET) | (this.qosLevel << QOS_LEVEL_OFFSET)); 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.DupFlag ? (Byte)(1 << DUP_FLAG_OFFSET) : (Byte)0x00;
buffer[index] |= this.retain ? (Byte)(1 << RETAIN_FLAG_OFFSET) : (Byte)0x00; buffer[index] |= this.Retain ? (Byte)(1 << RETAIN_FLAG_OFFSET) : (Byte)0x00;
index++; index++;
// encode remaining length // encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index); index = this.EncodeRemainingLength(remainingLength, buffer, index);
// topic name // topic name
buffer[index++] = (Byte)((topicUtf8.Length >> 8) & 0x00FF); // MSB buffer[index++] = (Byte)((topicUtf8.Length >> 8) & 0x00FF); // MSB
@ -141,22 +138,22 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
index += topicUtf8.Length; index += topicUtf8.Length;
// message id is valid only with QOS level 1 or QOS level 2 // message id is valid only with QOS level 1 or QOS level 2
if ((this.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) || if (this.QosLevel == QOS_LEVEL_AT_LEAST_ONCE ||
(this.qosLevel == QOS_LEVEL_EXACTLY_ONCE)) { this.QosLevel == QOS_LEVEL_EXACTLY_ONCE) {
// check message identifier assigned // check message identifier assigned
if (this.messageId == 0) { if (this.MessageId == 0) {
throw new MqttClientException(MqttClientErrorCode.WrongMessageId); throw new MqttClientException(MqttClientErrorCode.WrongMessageId);
} }
buffer[index++] = (Byte)((this.messageId >> 8) & 0x00FF); // MSB buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
buffer[index++] = (Byte)(this.messageId & 0x00FF); // LSB buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
} }
// check on message with zero length // check on message with zero length
if (this.Message != null) { if (this.Message != null) {
// message data // message data
Array.Copy(this.Message, 0, buffer, index, this.Message.Length); Array.Copy(this.Message, 0, buffer, index, this.Message.Length);
index += this.Message.Length; _ = this.Message.Length;
} }
return buffer; return buffer;
@ -177,14 +174,14 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
MqttMsgPublish msg = new MqttMsgPublish(); MqttMsgPublish msg = new MqttMsgPublish();
// get remaining length and allocate buffer // get remaining length and allocate buffer
Int32 remainingLength = decodeRemainingLength(channel); Int32 remainingLength = DecodeRemainingLength(channel);
buffer = new Byte[remainingLength]; buffer = new Byte[remainingLength];
// read bytes from socket... // read bytes from socket...
Int32 received = channel.Receive(buffer); Int32 received = channel.Receive(buffer);
// topic name // topic name
topicUtf8Length = ((buffer[index++] << 8) & 0xFF00); topicUtf8Length = (buffer[index++] << 8) & 0xFF00;
topicUtf8Length |= buffer[index++]; topicUtf8Length |= buffer[index++];
topicUtf8 = new Byte[topicUtf8Length]; topicUtf8 = new Byte[topicUtf8Length];
Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length); Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length);
@ -192,22 +189,22 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
msg.Topic = new String(Encoding.UTF8.GetChars(topicUtf8)); msg.Topic = new String(Encoding.UTF8.GetChars(topicUtf8));
// read QoS level from fixed header // read QoS level from fixed header
msg.qosLevel = (Byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET); msg.QosLevel = (Byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
// check wrong QoS level (both bits can't be set 1) // check wrong QoS level (both bits can't be set 1)
if (msg.qosLevel > QOS_LEVEL_EXACTLY_ONCE) { if (msg.QosLevel > QOS_LEVEL_EXACTLY_ONCE) {
throw new MqttClientException(MqttClientErrorCode.QosNotAllowed); throw new MqttClientException(MqttClientErrorCode.QosNotAllowed);
} }
// read DUP flag from fixed header // read DUP flag from fixed header
msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01); msg.DupFlag = (fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET == 0x01;
// read retain flag from fixed header // read retain flag from fixed header
msg.retain = (((fixedHeaderFirstByte & RETAIN_FLAG_MASK) >> RETAIN_FLAG_OFFSET) == 0x01); msg.Retain = (fixedHeaderFirstByte & RETAIN_FLAG_MASK) >> RETAIN_FLAG_OFFSET == 0x01;
// message id is valid only with QOS level 1 or QOS level 2 // message id is valid only with QOS level 1 or QOS level 2
if ((msg.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) || if (msg.QosLevel == QOS_LEVEL_AT_LEAST_ONCE ||
(msg.qosLevel == QOS_LEVEL_EXACTLY_ONCE)) { msg.QosLevel == QOS_LEVEL_EXACTLY_ONCE) {
// message id // message id
msg.messageId = (UInt16)((buffer[index++] << 8) & 0xFF00); msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]); msg.MessageId |= buffer[index++];
} }
// get payload with message data // get payload with message data
@ -220,8 +217,8 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
// copy first part of payload data received // copy first part of payload data received
Array.Copy(buffer, index, msg.Message, messageOffset, received - index); Array.Copy(buffer, index, msg.Message, messageOffset, received - index);
remaining -= (received - index); remaining -= received - index;
messageOffset += (received - index); messageOffset += received - index;
// if payload isn't finished // if payload isn't finished
while (remaining > 0) { while (remaining > 0) {
@ -235,15 +232,15 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
return msg; return msg;
} }
public override String ToString() { public override String ToString() =>
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"PUBLISH", "PUBLISH",
new Object[] { "messageId", "topic", "message" }, new Object[] { "messageId", "topic", "message" },
new Object[] { this.messageId, this.Topic, this.Message }); new Object[] { this.MessageId, this.Topic, this.Message });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -14,78 +14,47 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System; using System;
#else #else
using Microsoft.SPOT; using Microsoft.SPOT;
#endif #endif
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Event Args class for PUBLISH message received from broker /// Event Args class for PUBLISH message received from broker
/// </summary> /// </summary>
public class MqttMsgPublishEventArgs : EventArgs public class MqttMsgPublishEventArgs : EventArgs {
{
#region Properties... #region Properties...
/// <summary> /// <summary>
/// Message topic /// Message topic
/// </summary> /// </summary>
public string Topic public String Topic { get; internal set; }
{
get { return this.topic; }
internal set { this.topic = value; }
}
/// <summary> /// <summary>
/// Message data /// Message data
/// </summary> /// </summary>
public byte[] Message public Byte[] Message { get; internal set; }
{
get { return this.message; }
internal set { this.message = value; }
}
/// <summary> /// <summary>
/// Duplicate message flag /// Duplicate message flag
/// </summary> /// </summary>
public bool DupFlag public Boolean DupFlag { get; set; }
{
get { return this.dupFlag; }
set { this.dupFlag = value; }
}
/// <summary> /// <summary>
/// Quality of Service level /// Quality of Service level
/// </summary> /// </summary>
public byte QosLevel public Byte QosLevel { get; internal set; }
{
get { return this.qosLevel; }
internal set { this.qosLevel = value; }
}
/// <summary> /// <summary>
/// Retain message flag /// Retain message flag
/// </summary> /// </summary>
public bool Retain public Boolean Retain { get; internal set; }
{
get { return this.retain; }
internal set { this.retain = value; }
}
#endregion #endregion
// message topic // 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> /// <summary>
/// Constructor /// Constructor
@ -95,17 +64,16 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <param name="dupFlag">Duplicate delivery flag</param> /// <param name="dupFlag">Duplicate delivery flag</param>
/// <param name="qosLevel">Quality of Service level</param> /// <param name="qosLevel">Quality of Service level</param>
/// <param name="retain">Retain flag</param> /// <param name="retain">Retain flag</param>
public MqttMsgPublishEventArgs(string topic, public MqttMsgPublishEventArgs(String topic,
byte[] message, Byte[] message,
bool dupFlag, Boolean dupFlag,
byte qosLevel, Byte qosLevel,
bool retain) Boolean retain) {
{ this.Topic = topic;
this.topic = topic; this.Message = message;
this.message = message; this.DupFlag = dupFlag;
this.dupFlag = dupFlag; this.QosLevel = qosLevel;
this.qosLevel = qosLevel; this.Retain = retain;
this.retain = retain;
} }
} }
} }

View File

@ -14,54 +14,39 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System; using System;
#else #else
using Microsoft.SPOT; using Microsoft.SPOT;
#endif #endif
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Event Args class for published message /// Event Args class for published message
/// </summary> /// </summary>
public class MqttMsgPublishedEventArgs : EventArgs public class MqttMsgPublishedEventArgs : EventArgs {
{
#region Properties... #region Properties...
/// <summary> /// <summary>
/// Message identifier /// Message identifier
/// </summary> /// </summary>
public ushort MessageId public UInt16 MessageId { get; internal set; }
{
get { return this.messageId; }
internal set { this.messageId = value; }
}
/// <summary> /// <summary>
/// Message published (or failed due to retries) /// Message published (or failed due to retries)
/// </summary> /// </summary>
public bool IsPublished public Boolean IsPublished { get; internal set; }
{
get { return this.isPublished; }
internal set { this.isPublished = value; }
}
#endregion #endregion
// message identifier // message identifier
ushort messageId;
// published flag
bool isPublished;
/// <summary> /// <summary>
/// Constructor (published message) /// Constructor (published message)
/// </summary> /// </summary>
/// <param name="messageId">Message identifier published</param> /// <param name="messageId">Message identifier published</param>
public MqttMsgPublishedEventArgs(ushort messageId) public MqttMsgPublishedEventArgs(UInt16 messageId)
: this(messageId, true) : this(messageId, true) {
{
} }
/// <summary> /// <summary>
@ -69,10 +54,9 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// </summary> /// </summary>
/// <param name="messageId">Message identifier</param> /// <param name="messageId">Message identifier</param>
/// <param name="isPublished">Publish flag</param> /// <param name="isPublished">Publish flag</param>
public MqttMsgPublishedEventArgs(ushort messageId, bool isPublished) public MqttMsgPublishedEventArgs(UInt16 messageId, Boolean isPublished) {
{ this.MessageId = messageId;
this.messageId = messageId; this.IsPublished = isPublished;
this.isPublished = isPublished;
} }
} }
} }

View File

@ -14,64 +14,56 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
using System;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Class for PUBREC message from broker to client /// Class for PUBREC message from broker to client
/// </summary> /// </summary>
public class MqttMsgPubrec : MqttMsgBase public class MqttMsgPubrec : MqttMsgBase {
{
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
public MqttMsgPubrec() public MqttMsgPubrec() => this.Type = MQTT_MSG_PUBREC_TYPE;
{
this.type = MQTT_MSG_PUBREC_TYPE;
}
public override byte[] GetBytes(byte protocolVersion) public override Byte[] GetBytes(Byte protocolVersion) {
{ Int32 varHeaderSize = 0;
int fixedHeaderSize = 0; Int32 payloadSize = 0;
int varHeaderSize = 0; Int32 remainingLength = 0;
int payloadSize = 0; Byte[] buffer;
int remainingLength = 0; Int32 index = 0;
byte[] buffer;
int index = 0;
// message identifier // message identifier
varHeaderSize += MESSAGE_ID_SIZE; varHeaderSize += MESSAGE_ID_SIZE;
remainingLength += (varHeaderSize + payloadSize); remainingLength += varHeaderSize + payloadSize;
// first byte of fixed header // first byte of fixed header
fixedHeaderSize = 1; Int32 fixedHeaderSize = 1;
int temp = remainingLength; Int32 temp = remainingLength;
// increase fixed header size based on remaining length // increase fixed header size based on remaining length
// (each remaining length byte can encode until 128) // (each remaining length byte can encode until 128)
do do {
{
fixedHeaderSize++; fixedHeaderSize++;
temp = temp / 128; temp /= 128;
} while (temp > 0); } while (temp > 0);
// allocate buffer for message // allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize]; buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte // first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) buffer[index++] = 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] ? (Byte)((MQTT_MSG_PUBREC_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBREC_FLAG_BITS)
else : (Byte)(MQTT_MSG_PUBREC_TYPE << MSG_TYPE_OFFSET);
buffer[index++] = (MQTT_MSG_PUBREC_TYPE << MSG_TYPE_OFFSET);
// encode remaining length // encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index); index = this.EncodeRemainingLength(remainingLength, buffer, index);
// get message identifier // get message identifier
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
return buffer; return buffer;
} }
@ -83,43 +75,41 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <param name="protocolVersion">Protocol Version</param> /// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param> /// <param name="channel">Channel connected to the broker</param>
/// <returns>PUBREC message instance</returns> /// <returns>PUBREC message instance</returns>
public static MqttMsgPubrec Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) public static MqttMsgPubrec Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
{ Byte[] buffer;
byte[] buffer; Int32 index = 0;
int index = 0;
MqttMsgPubrec msg = new MqttMsgPubrec(); MqttMsgPubrec msg = new MqttMsgPubrec();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
{
// [v3.1.1] check flag bits // [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBREC_FLAG_BITS) if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBREC_FLAG_BITS) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
} }
}
// get remaining length and allocate buffer // get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
buffer = new byte[remainingLength]; buffer = new Byte[remainingLength];
// read bytes from socket... // read bytes from socket...
channel.Receive(buffer); _ = channel.Receive(buffer);
// message id // message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]); msg.MessageId |= buffer[index++];
return msg; return msg;
} }
public override string ToString() public override String ToString() =>
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"PUBREC", "PUBREC",
new object[] { "messageId" }, new Object[] { "messageId" },
new object[] { this.messageId }); new Object[] { this.MessageId });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -16,69 +16,62 @@ Contributors:
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Class for PUBREL message from client top broker /// Class for PUBREL message from client top broker
/// </summary> /// </summary>
public class MqttMsgPubrel : MqttMsgBase public class MqttMsgPubrel : MqttMsgBase {
{
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
public MqttMsgPubrel() public MqttMsgPubrel() {
{ this.Type = MQTT_MSG_PUBREL_TYPE;
this.type = MQTT_MSG_PUBREL_TYPE;
// PUBREL message use QoS Level 1 (not "officially" in 3.1.1) // PUBREL message use QoS Level 1 (not "officially" in 3.1.1)
this.qosLevel = QOS_LEVEL_AT_LEAST_ONCE; this.QosLevel = QOS_LEVEL_AT_LEAST_ONCE;
} }
public override byte[] GetBytes(byte protocolVersion) public override System.Byte[] GetBytes(System.Byte protocolVersion) {
{ System.Int32 varHeaderSize = 0;
int fixedHeaderSize = 0; System.Int32 payloadSize = 0;
int varHeaderSize = 0; System.Int32 remainingLength = 0;
int payloadSize = 0; System.Byte[] buffer;
int remainingLength = 0; System.Int32 index = 0;
byte[] buffer;
int index = 0;
// message identifier // message identifier
varHeaderSize += MESSAGE_ID_SIZE; varHeaderSize += MESSAGE_ID_SIZE;
remainingLength += (varHeaderSize + payloadSize); remainingLength += varHeaderSize + payloadSize;
// first byte of fixed header // first byte of fixed header
fixedHeaderSize = 1; System.Int32 fixedHeaderSize = 1;
int temp = remainingLength; System.Int32 temp = remainingLength;
// increase fixed header size based on remaining length // increase fixed header size based on remaining length
// (each remaining length byte can encode until 128) // (each remaining length byte can encode until 128)
do do {
{
fixedHeaderSize++; fixedHeaderSize++;
temp = temp / 128; temp /= 128;
} while (temp > 0); } while (temp > 0);
// allocate buffer for message // allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize]; buffer = new System.Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte // first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) 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] buffer[index++] = (MQTT_MSG_PUBREL_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBREL_FLAG_BITS; // [v.3.1.1]
else } else {
{ buffer[index] = (System.Byte)((MQTT_MSG_PUBREL_TYPE << MSG_TYPE_OFFSET) |
buffer[index] = (byte)((MQTT_MSG_PUBREL_TYPE << MSG_TYPE_OFFSET) | (this.QosLevel << QOS_LEVEL_OFFSET));
(this.qosLevel << QOS_LEVEL_OFFSET)); buffer[index] |= this.DupFlag ? (System.Byte)(1 << DUP_FLAG_OFFSET) : (System.Byte)0x00;
buffer[index] |= this.dupFlag ? (byte)(1 << DUP_FLAG_OFFSET) : (byte)0x00;
index++; index++;
} }
// encode remaining length // encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index); index = this.EncodeRemainingLength(remainingLength, buffer, index);
// get next message identifier // get next message identifier
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB buffer[index++] = (System.Byte)((this.MessageId >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB buffer[index++] = (System.Byte)(this.MessageId & 0x00FF); // LSB
return buffer; return buffer;
} }
@ -90,53 +83,50 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <param name="protocolVersion">Protocol Version</param> /// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param> /// <param name="channel">Channel connected to the broker</param>
/// <returns>PUBREL message instance</returns> /// <returns>PUBREL message instance</returns>
public static MqttMsgPubrel Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) public static MqttMsgPubrel Parse(System.Byte fixedHeaderFirstByte, System.Byte protocolVersion, IMqttNetworkChannel channel) {
{ System.Byte[] buffer;
byte[] buffer; System.Int32 index = 0;
int index = 0;
MqttMsgPubrel msg = new MqttMsgPubrel(); MqttMsgPubrel msg = new MqttMsgPubrel();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
{
// [v3.1.1] check flag bits // [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBREL_FLAG_BITS) if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBREL_FLAG_BITS) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
} }
}
// get remaining length and allocate buffer // get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); System.Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
buffer = new byte[remainingLength]; buffer = new System.Byte[remainingLength];
// read bytes from socket... // read bytes from socket...
channel.Receive(buffer); _ = channel.Receive(buffer);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1) if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1) {
{
// only 3.1.0 // only 3.1.0
// read QoS level from fixed header (would be QoS Level 1) // read QoS level from fixed header (would be QoS Level 1)
msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET); msg.QosLevel = (System.Byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
// read DUP flag from fixed header // read DUP flag from fixed header
msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01); msg.DupFlag = (fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET == 0x01;
} }
// message id // message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.MessageId = (System.UInt16)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]); msg.MessageId |= buffer[index++];
return msg; return msg;
} }
public override string ToString() public override System.String ToString() =>
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"PUBREL", "PUBREL",
new object[] { "messageId" }, new System.Object[] { "messageId" },
new object[] { this.messageId }); new System.Object[] { this.MessageId });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -17,36 +17,26 @@ Contributors:
using System; using System;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Class for SUBACK message from broker to client /// Class for SUBACK message from broker to client
/// </summary> /// </summary>
public class MqttMsgSuback : MqttMsgBase public class MqttMsgSuback : MqttMsgBase {
{
#region Properties... #region Properties...
/// <summary> /// <summary>
/// List of granted QOS Levels /// List of granted QOS Levels
/// </summary> /// </summary>
public byte[] GrantedQoSLevels public Byte[] GrantedQoSLevels { get; set; }
{
get { return this.grantedQosLevels; }
set { this.grantedQosLevels = value; }
}
#endregion #endregion
// granted QOS levels // granted QOS levels
byte[] grantedQosLevels;
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
public MqttMsgSuback() public MqttMsgSuback() => this.Type = MQTT_MSG_SUBACK_TYPE;
{
this.type = MQTT_MSG_SUBACK_TYPE;
}
/// <summary> /// <summary>
/// Parse bytes for a SUBACK message /// Parse bytes for a SUBACK message
@ -55,108 +45,99 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <param name="protocolVersion">Protocol Version</param> /// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param> /// <param name="channel">Channel connected to the broker</param>
/// <returns>SUBACK message instance</returns> /// <returns>SUBACK message instance</returns>
public static MqttMsgSuback Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) public static MqttMsgSuback Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
{ Byte[] buffer;
byte[] buffer; Int32 index = 0;
int index = 0;
MqttMsgSuback msg = new MqttMsgSuback(); MqttMsgSuback msg = new MqttMsgSuback();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
{
// [v3.1.1] check flag bits // [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBACK_FLAG_BITS) if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBACK_FLAG_BITS) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
} }
}
// get remaining length and allocate buffer // get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
buffer = new byte[remainingLength]; buffer = new Byte[remainingLength];
// read bytes from socket... // read bytes from socket...
channel.Receive(buffer); _ = channel.Receive(buffer);
// message id // message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]); msg.MessageId |= buffer[index++];
// payload contains QoS levels granted // payload contains QoS levels granted
msg.grantedQosLevels = new byte[remainingLength - MESSAGE_ID_SIZE]; msg.GrantedQoSLevels = new Byte[remainingLength - MESSAGE_ID_SIZE];
int qosIdx = 0; Int32 qosIdx = 0;
do do {
{ msg.GrantedQoSLevels[qosIdx++] = buffer[index++];
msg.grantedQosLevels[qosIdx++] = buffer[index++];
} while (index < remainingLength); } while (index < remainingLength);
return msg; return msg;
} }
public override byte[] GetBytes(byte protocolVersion) public override Byte[] GetBytes(Byte protocolVersion) {
{ Int32 varHeaderSize = 0;
int fixedHeaderSize = 0; Int32 payloadSize = 0;
int varHeaderSize = 0; Int32 remainingLength = 0;
int payloadSize = 0; Byte[] buffer;
int remainingLength = 0; Int32 index = 0;
byte[] buffer;
int index = 0;
// message identifier // message identifier
varHeaderSize += MESSAGE_ID_SIZE; varHeaderSize += MESSAGE_ID_SIZE;
int grantedQosIdx = 0; Int32 grantedQosIdx;
for (grantedQosIdx = 0; grantedQosIdx < this.grantedQosLevels.Length; grantedQosIdx++) for (grantedQosIdx = 0; grantedQosIdx < this.GrantedQoSLevels.Length; grantedQosIdx++) {
{
payloadSize++; payloadSize++;
} }
remainingLength += (varHeaderSize + payloadSize); remainingLength += varHeaderSize + payloadSize;
// first byte of fixed header // first byte of fixed header
fixedHeaderSize = 1; Int32 fixedHeaderSize = 1;
int temp = remainingLength; Int32 temp = remainingLength;
// increase fixed header size based on remaining length // increase fixed header size based on remaining length
// (each remaining length byte can encode until 128) // (each remaining length byte can encode until 128)
do do {
{
fixedHeaderSize++; fixedHeaderSize++;
temp = temp / 128; temp /= 128;
} while (temp > 0); } while (temp > 0);
// allocate buffer for message // allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize]; buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte // first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) buffer[index++] = 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] ? (Byte)((MQTT_MSG_SUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_SUBACK_FLAG_BITS)
else : (Byte)(MQTT_MSG_SUBACK_TYPE << MSG_TYPE_OFFSET);
buffer[index++] = (byte)(MQTT_MSG_SUBACK_TYPE << MSG_TYPE_OFFSET);
// encode remaining length // encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index); index = this.EncodeRemainingLength(remainingLength, buffer, index);
// message id // message id
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
// payload contains QoS levels granted // payload contains QoS levels granted
for (grantedQosIdx = 0; grantedQosIdx < this.grantedQosLevels.Length; grantedQosIdx++) for (grantedQosIdx = 0; grantedQosIdx < this.GrantedQoSLevels.Length; grantedQosIdx++) {
{ buffer[index++] = this.GrantedQoSLevels[grantedQosIdx];
buffer[index++] = this.grantedQosLevels[grantedQosIdx];
} }
return buffer; return buffer;
} }
public override string ToString() public override String ToString() =>
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"SUBACK", "SUBACK",
new object[] { "messageId", "grantedQosLevels" }, new Object[] { "messageId", "grantedQosLevels" },
new object[] { this.messageId, this.grantedQosLevels }); new Object[] { this.MessageId, this.GrantedQoSLevels });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -16,69 +16,52 @@ Contributors:
using System; using System;
// if NOT .Net Micro Framework // if NOT .Net Micro Framework
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System.Collections.Generic; using System.Collections.Generic;
#endif #endif
using System.Collections; using System.Collections;
using System.Text; using System.Text;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Class for SUBSCRIBE message from client to broker /// Class for SUBSCRIBE message from client to broker
/// </summary> /// </summary>
public class MqttMsgSubscribe : MqttMsgBase public class MqttMsgSubscribe : MqttMsgBase {
{
#region Properties... #region Properties...
/// <summary> /// <summary>
/// List of topics to subscribe /// List of topics to subscribe
/// </summary> /// </summary>
public string[] Topics public String[] Topics { get; set; }
{
get { return this.topics; }
set { this.topics = value; }
}
/// <summary> /// <summary>
/// List of QOS Levels related to topics /// List of QOS Levels related to topics
/// </summary> /// </summary>
public byte[] QoSLevels public Byte[] QoSLevels { get; set; }
{
get { return this.qosLevels; }
set { this.qosLevels = value; }
}
#endregion #endregion
// topics to subscribe // topics to subscribe
string[] topics;
// QOS levels related to topics
byte[] qosLevels;
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
public MqttMsgSubscribe() public MqttMsgSubscribe() => this.Type = MQTT_MSG_SUBSCRIBE_TYPE;
{
this.type = MQTT_MSG_SUBSCRIBE_TYPE;
}
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
/// <param name="topics">List of topics to subscribe</param> /// <param name="topics">List of topics to subscribe</param>
/// <param name="qosLevels">List of QOS Levels related to topics</param> /// <param name="qosLevels">List of QOS Levels related to topics</param>
public MqttMsgSubscribe(string[] topics, byte[] qosLevels) public MqttMsgSubscribe(String[] topics, Byte[] qosLevels) {
{ this.Type = MQTT_MSG_SUBSCRIBE_TYPE;
this.type = MQTT_MSG_SUBSCRIBE_TYPE;
this.topics = topics; this.Topics = topics;
this.qosLevels = qosLevels; this.QoSLevels = qosLevels;
// SUBSCRIBE message uses QoS Level 1 (not "officially" in 3.1.1) // SUBSCRIBE message uses QoS Level 1 (not "officially" in 3.1.1)
this.qosLevel = QOS_LEVEL_AT_LEAST_ONCE; this.QosLevel = QOS_LEVEL_AT_LEAST_ONCE;
} }
/// <summary> /// <summary>
@ -88,62 +71,59 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <param name="protocolVersion">Protocol Version</param> /// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param> /// <param name="channel">Channel connected to the broker</param>
/// <returns>SUBSCRIBE message instance</returns> /// <returns>SUBSCRIBE message instance</returns>
public static MqttMsgSubscribe Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) public static MqttMsgSubscribe Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
{ Byte[] buffer;
byte[] buffer; Int32 index = 0;
int index = 0; Byte[] topicUtf8;
byte[] topicUtf8; Int32 topicUtf8Length;
int topicUtf8Length;
MqttMsgSubscribe msg = new MqttMsgSubscribe(); MqttMsgSubscribe msg = new MqttMsgSubscribe();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
{
// [v3.1.1] check flag bits // [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBSCRIBE_FLAG_BITS) if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBSCRIBE_FLAG_BITS) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
} }
}
// get remaining length and allocate buffer // get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
buffer = new byte[remainingLength]; buffer = new Byte[remainingLength];
// read bytes from socket... // read bytes from socket...
int received = channel.Receive(buffer); Int32 received = channel.Receive(buffer);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1) if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1) {
{
// only 3.1.0 // only 3.1.0
// read QoS level from fixed header // read QoS level from fixed header
msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET); msg.QosLevel = (Byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
// read DUP flag from fixed header // read DUP flag from fixed header
msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01); msg.DupFlag = (fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET == 0x01;
// retain flag not used // retain flag not used
msg.retain = false; msg.Retain = false;
} }
// message id // message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]); msg.MessageId |= buffer[index++];
// payload contains topics and QoS levels // payload contains topics and QoS levels
// NOTE : before, I don't know how many topics will be in the payload (so use List) // NOTE : before, I don't know how many topics will be in the payload (so use List)
// if .Net Micro Framework // if .Net Micro Framework
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3) #if MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
IList tmpTopics = new ArrayList(); IList tmpTopics = new ArrayList();
IList tmpQosLevels = new ArrayList(); IList tmpQosLevels = new ArrayList();
// else other frameworks (.Net, .Net Compact, Mono, Windows Phone) // else other frameworks (.Net, .Net Compact, Mono, Windows Phone)
#else #else
IList<String> tmpTopics = new List<String>(); IList<String> tmpTopics = new List<String>();
IList<byte> tmpQosLevels = new List<byte>(); IList<Byte> tmpQosLevels = new List<Byte>();
#endif #endif
do do {
{
// topic name // topic name
topicUtf8Length = ((buffer[index++] << 8) & 0xFF00); topicUtf8Length = (buffer[index++] << 8) & 0xFF00;
topicUtf8Length |= buffer[index++]; topicUtf8Length |= buffer[index++];
topicUtf8 = new byte[topicUtf8Length]; topicUtf8 = new Byte[topicUtf8Length];
Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length); Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length);
index += topicUtf8Length; index += topicUtf8Length;
tmpTopics.Add(new String(Encoding.UTF8.GetChars(topicUtf8))); tmpTopics.Add(new String(Encoding.UTF8.GetChars(topicUtf8)));
@ -154,119 +134,116 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
} while (index < remainingLength); } while (index < remainingLength);
// copy from list to array // copy from list to array
msg.topics = new string[tmpTopics.Count]; msg.Topics = new String[tmpTopics.Count];
msg.qosLevels = new byte[tmpQosLevels.Count]; msg.QoSLevels = new Byte[tmpQosLevels.Count];
for (int i = 0; i < tmpTopics.Count; i++) for (Int32 i = 0; i < tmpTopics.Count; i++) {
{ msg.Topics[i] = (String)tmpTopics[i];
msg.topics[i] = (string)tmpTopics[i]; msg.QoSLevels[i] = (Byte)tmpQosLevels[i];
msg.qosLevels[i] = (byte)tmpQosLevels[i];
} }
return msg; return msg;
} }
public override byte[] GetBytes(byte protocolVersion) public override Byte[] GetBytes(Byte protocolVersion) {
{ Int32 varHeaderSize = 0;
int fixedHeaderSize = 0; Int32 payloadSize = 0;
int varHeaderSize = 0; Int32 remainingLength = 0;
int payloadSize = 0; Byte[] buffer;
int remainingLength = 0; Int32 index = 0;
byte[] buffer;
int index = 0;
// topics list empty // topics list empty
if ((this.topics == null) || (this.topics.Length == 0)) if (this.Topics == null || this.Topics.Length == 0) {
throw new MqttClientException(MqttClientErrorCode.TopicsEmpty); throw new MqttClientException(MqttClientErrorCode.TopicsEmpty);
}
// qos levels list empty // qos levels list empty
if ((this.qosLevels == null) || (this.qosLevels.Length == 0)) if (this.QoSLevels == null || this.QoSLevels.Length == 0) {
throw new MqttClientException(MqttClientErrorCode.QosLevelsEmpty); throw new MqttClientException(MqttClientErrorCode.QosLevelsEmpty);
}
// topics and qos levels lists length don't match // topics and qos levels lists length don't match
if (this.topics.Length != this.qosLevels.Length) if (this.Topics.Length != this.QoSLevels.Length) {
throw new MqttClientException(MqttClientErrorCode.TopicsQosLevelsNotMatch); throw new MqttClientException(MqttClientErrorCode.TopicsQosLevelsNotMatch);
}
// message identifier // message identifier
varHeaderSize += MESSAGE_ID_SIZE; varHeaderSize += MESSAGE_ID_SIZE;
Byte[][] topicsUtf8 = new Byte[this.Topics.Length][];
int topicIdx = 0;
byte[][] topicsUtf8 = new byte[this.topics.Length][];
for (topicIdx = 0; topicIdx < this.topics.Length; topicIdx++) Int32 topicIdx;
{ for (topicIdx = 0; topicIdx < this.Topics.Length; topicIdx++) {
// check topic length // check topic length
if ((this.topics[topicIdx].Length < MIN_TOPIC_LENGTH) || (this.topics[topicIdx].Length > MAX_TOPIC_LENGTH)) if (this.Topics[topicIdx].Length < MIN_TOPIC_LENGTH || this.Topics[topicIdx].Length > MAX_TOPIC_LENGTH) {
throw new MqttClientException(MqttClientErrorCode.TopicLength); throw new MqttClientException(MqttClientErrorCode.TopicLength);
}
topicsUtf8[topicIdx] = Encoding.UTF8.GetBytes(this.topics[topicIdx]); topicsUtf8[topicIdx] = Encoding.UTF8.GetBytes(this.Topics[topicIdx]);
payloadSize += 2; // topic size (MSB, LSB) payloadSize += 2; // topic size (MSB, LSB)
payloadSize += topicsUtf8[topicIdx].Length; payloadSize += topicsUtf8[topicIdx].Length;
payloadSize++; // byte for QoS payloadSize++; // byte for QoS
} }
remainingLength += (varHeaderSize + payloadSize); remainingLength += varHeaderSize + payloadSize;
// first byte of fixed header // first byte of fixed header
fixedHeaderSize = 1; Int32 fixedHeaderSize = 1;
int temp = remainingLength; Int32 temp = remainingLength;
// increase fixed header size based on remaining length // increase fixed header size based on remaining length
// (each remaining length byte can encode until 128) // (each remaining length byte can encode until 128)
do do {
{
fixedHeaderSize++; fixedHeaderSize++;
temp = temp / 128; temp /= 128;
} while (temp > 0); } while (temp > 0);
// allocate buffer for message // allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize]; buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte // first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) 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] buffer[index++] = (MQTT_MSG_SUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_SUBSCRIBE_FLAG_BITS; // [v.3.1.1]
else } else {
{ buffer[index] = (Byte)((MQTT_MSG_SUBSCRIBE_TYPE << MSG_TYPE_OFFSET) |
buffer[index] = (byte)((MQTT_MSG_SUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | (this.QosLevel << QOS_LEVEL_OFFSET));
(this.qosLevel << QOS_LEVEL_OFFSET)); buffer[index] |= this.DupFlag ? (Byte)(1 << DUP_FLAG_OFFSET) : (Byte)0x00;
buffer[index] |= this.dupFlag ? (byte)(1 << DUP_FLAG_OFFSET) : (byte)0x00;
index++; index++;
} }
// encode remaining length // encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index); index = this.EncodeRemainingLength(remainingLength, buffer, index);
// check message identifier assigned (SUBSCRIBE uses QoS Level 1, so message id is mandatory) // check message identifier assigned (SUBSCRIBE uses QoS Level 1, so message id is mandatory)
if (this.messageId == 0) if (this.MessageId == 0) {
throw new MqttClientException(MqttClientErrorCode.WrongMessageId); throw new MqttClientException(MqttClientErrorCode.WrongMessageId);
buffer[index++] = (byte)((messageId >> 8) & 0x00FF); // MSB }
buffer[index++] = (byte)(messageId & 0x00FF); // LSB
topicIdx = 0; buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
for (topicIdx = 0; topicIdx < this.topics.Length; topicIdx++) buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
{
for (topicIdx = 0; topicIdx < this.Topics.Length; topicIdx++) {
// topic name // topic name
buffer[index++] = (byte)((topicsUtf8[topicIdx].Length >> 8) & 0x00FF); // MSB buffer[index++] = (Byte)((topicsUtf8[topicIdx].Length >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(topicsUtf8[topicIdx].Length & 0x00FF); // LSB buffer[index++] = (Byte)(topicsUtf8[topicIdx].Length & 0x00FF); // LSB
Array.Copy(topicsUtf8[topicIdx], 0, buffer, index, topicsUtf8[topicIdx].Length); Array.Copy(topicsUtf8[topicIdx], 0, buffer, index, topicsUtf8[topicIdx].Length);
index += topicsUtf8[topicIdx].Length; index += topicsUtf8[topicIdx].Length;
// requested QoS // requested QoS
buffer[index++] = this.qosLevels[topicIdx]; buffer[index++] = this.QoSLevels[topicIdx];
} }
return buffer; return buffer;
} }
public override string ToString() public override String ToString() =>
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"SUBSCRIBE", "SUBSCRIBE",
new object[] { "messageId", "topics", "qosLevels" }, new Object[] { "messageId", "topics", "qosLevels" },
new object[] { this.messageId, this.topics, this.qosLevels }); new Object[] { this.MessageId, this.Topics, this.QoSLevels });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -14,56 +14,37 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System; using System;
#else #else
using Microsoft.SPOT; using Microsoft.SPOT;
#endif #endif
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Event Args class for subscribe request on topics /// Event Args class for subscribe request on topics
/// </summary> /// </summary>
public class MqttMsgSubscribeEventArgs : EventArgs public class MqttMsgSubscribeEventArgs : EventArgs {
{
#region Properties... #region Properties...
/// <summary> /// <summary>
/// Message identifier /// Message identifier
/// </summary> /// </summary>
public ushort MessageId public UInt16 MessageId { get; internal set; }
{
get { return this.messageId; }
internal set { this.messageId = value; }
}
/// <summary> /// <summary>
/// Topics requested to subscribe /// Topics requested to subscribe
/// </summary> /// </summary>
public string[] Topics public String[] Topics { get; internal set; }
{
get { return this.topics; }
internal set { this.topics = value; }
}
/// <summary> /// <summary>
/// List of QOS Levels requested /// List of QOS Levels requested
/// </summary> /// </summary>
public byte[] QoSLevels public Byte[] QoSLevels { get; internal set; }
{
get { return this.qosLevels; }
internal set { this.qosLevels = value; }
}
#endregion #endregion
// message identifier // message identifier
ushort messageId;
// topics requested to subscribe
string[] topics;
// QoS levels requested
byte[] qosLevels;
/// <summary> /// <summary>
/// Constructor /// Constructor
@ -71,11 +52,10 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <param name="messageId">Message identifier for subscribe topics request</param> /// <param name="messageId">Message identifier for subscribe topics request</param>
/// <param name="topics">Topics requested to subscribe</param> /// <param name="topics">Topics requested to subscribe</param>
/// <param name="qosLevels">List of QOS Levels requested</param> /// <param name="qosLevels">List of QOS Levels requested</param>
public MqttMsgSubscribeEventArgs(ushort messageId, string[] topics, byte[] qosLevels) public MqttMsgSubscribeEventArgs(UInt16 messageId, String[] topics, Byte[] qosLevels) {
{ this.MessageId = messageId;
this.messageId = messageId; this.Topics = topics;
this.topics = topics; this.QoSLevels = qosLevels;
this.qosLevels = qosLevels;
} }
} }
} }

View File

@ -14,55 +14,41 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System; using System;
#else #else
using Microsoft.SPOT; using Microsoft.SPOT;
#endif #endif
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Event Args class for subscribed topics /// Event Args class for subscribed topics
/// </summary> /// </summary>
public class MqttMsgSubscribedEventArgs : EventArgs public class MqttMsgSubscribedEventArgs : EventArgs {
{
#region Properties... #region Properties...
/// <summary> /// <summary>
/// Message identifier /// Message identifier
/// </summary> /// </summary>
public ushort MessageId public UInt16 MessageId { get; internal set; }
{
get { return this.messageId; }
internal set { this.messageId = value; }
}
/// <summary> /// <summary>
/// List of granted QOS Levels /// List of granted QOS Levels
/// </summary> /// </summary>
public byte[] GrantedQoSLevels public Byte[] GrantedQoSLevels { get; internal set; }
{
get { return this.grantedQosLevels; }
internal set { this.grantedQosLevels = value; }
}
#endregion #endregion
// message identifier // message identifier
ushort messageId;
// granted QOS levels
byte[] grantedQosLevels;
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
/// <param name="messageId">Message identifier for subscribed topics</param> /// <param name="messageId">Message identifier for subscribed topics</param>
/// <param name="grantedQosLevels">List of granted QOS Levels</param> /// <param name="grantedQosLevels">List of granted QOS Levels</param>
public MqttMsgSubscribedEventArgs(ushort messageId, byte[] grantedQosLevels) public MqttMsgSubscribedEventArgs(UInt16 messageId, Byte[] grantedQosLevels) {
{ this.MessageId = messageId;
this.messageId = messageId; this.GrantedQoSLevels = grantedQosLevels;
this.grantedQosLevels = grantedQosLevels;
} }
} }
} }

View File

@ -17,20 +17,15 @@ Contributors:
using System; using System;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Class for UNSUBACK message from broker to client /// Class for UNSUBACK message from broker to client
/// </summary> /// </summary>
public class MqttMsgUnsuback : MqttMsgBase public class MqttMsgUnsuback : MqttMsgBase {
{
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
public MqttMsgUnsuback() public MqttMsgUnsuback() => this.Type = MQTT_MSG_UNSUBACK_TYPE;
{
this.type = MQTT_MSG_UNSUBACK_TYPE;
}
/// <summary> /// <summary>
/// Parse bytes for a UNSUBACK message /// Parse bytes for a UNSUBACK message
@ -39,88 +34,82 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <param name="protocolVersion">Protocol Version</param> /// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param> /// <param name="channel">Channel connected to the broker</param>
/// <returns>UNSUBACK message instance</returns> /// <returns>UNSUBACK message instance</returns>
public static MqttMsgUnsuback Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) public static MqttMsgUnsuback Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
{ Byte[] buffer;
byte[] buffer; Int32 index = 0;
int index = 0;
MqttMsgUnsuback msg = new MqttMsgUnsuback(); MqttMsgUnsuback msg = new MqttMsgUnsuback();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
{
// [v3.1.1] check flag bits // [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBACK_FLAG_BITS) if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBACK_FLAG_BITS) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
} }
}
// get remaining length and allocate buffer // get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
buffer = new byte[remainingLength]; buffer = new Byte[remainingLength];
// read bytes from socket... // read bytes from socket...
channel.Receive(buffer); _ = channel.Receive(buffer);
// message id // message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]); msg.MessageId |= buffer[index++];
return msg; return msg;
} }
public override byte[] GetBytes(byte protocolVersion) public override Byte[] GetBytes(Byte protocolVersion) {
{ Int32 varHeaderSize = 0;
int fixedHeaderSize = 0; Int32 payloadSize = 0;
int varHeaderSize = 0; Int32 remainingLength = 0;
int payloadSize = 0; Byte[] buffer;
int remainingLength = 0; Int32 index = 0;
byte[] buffer;
int index = 0;
// message identifier // message identifier
varHeaderSize += MESSAGE_ID_SIZE; varHeaderSize += MESSAGE_ID_SIZE;
remainingLength += (varHeaderSize + payloadSize); remainingLength += varHeaderSize + payloadSize;
// first byte of fixed header // first byte of fixed header
fixedHeaderSize = 1; Int32 fixedHeaderSize = 1;
int temp = remainingLength; Int32 temp = remainingLength;
// increase fixed header size based on remaining length // increase fixed header size based on remaining length
// (each remaining length byte can encode until 128) // (each remaining length byte can encode until 128)
do do {
{
fixedHeaderSize++; fixedHeaderSize++;
temp = temp / 128; temp /= 128;
} while (temp > 0); } while (temp > 0);
// allocate buffer for message // allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize]; buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte // first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) buffer[index++] = 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] ? (Byte)((MQTT_MSG_UNSUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_UNSUBACK_FLAG_BITS)
else : (Byte)(MQTT_MSG_UNSUBACK_TYPE << MSG_TYPE_OFFSET);
buffer[index++] = (byte)(MQTT_MSG_UNSUBACK_TYPE << MSG_TYPE_OFFSET);
// encode remaining length // encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index); index = this.EncodeRemainingLength(remainingLength, buffer, index);
// message id // message id
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
return buffer; return buffer;
} }
public override string ToString() public override String ToString() =>
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"UNSUBACK", "UNSUBACK",
new object[] { "messageId" }, new Object[] { "messageId" },
new object[] { this.messageId }); new Object[] { this.MessageId });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -16,56 +16,45 @@ Contributors:
using System; using System;
// if NOT .Net Micro Framework // if NOT .Net Micro Framework
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System.Collections.Generic; using System.Collections.Generic;
#endif #endif
using System.Collections; using System.Collections;
using System.Text; using System.Text;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Class for UNSUBSCRIBE message from client to broker /// Class for UNSUBSCRIBE message from client to broker
/// </summary> /// </summary>
public class MqttMsgUnsubscribe : MqttMsgBase public class MqttMsgUnsubscribe : MqttMsgBase {
{
#region Properties... #region Properties...
/// <summary> /// <summary>
/// List of topics to unsubscribe /// List of topics to unsubscribe
/// </summary> /// </summary>
public string[] Topics public String[] Topics { get; set; }
{
get { return this.topics; }
set { this.topics = value; }
}
#endregion #endregion
// topics to unsubscribe // topics to unsubscribe
string[] topics;
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
public MqttMsgUnsubscribe() public MqttMsgUnsubscribe() => this.Type = MQTT_MSG_UNSUBSCRIBE_TYPE;
{
this.type = MQTT_MSG_UNSUBSCRIBE_TYPE;
}
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
/// <param name="topics">List of topics to unsubscribe</param> /// <param name="topics">List of topics to unsubscribe</param>
public MqttMsgUnsubscribe(string[] topics) public MqttMsgUnsubscribe(String[] topics) {
{ this.Type = MQTT_MSG_UNSUBSCRIBE_TYPE;
this.type = MQTT_MSG_UNSUBSCRIBE_TYPE;
this.topics = topics; this.Topics = topics;
// UNSUBSCRIBE message uses QoS Level 1 (not "officially" in 3.1.1) // UNSUBSCRIBE message uses QoS Level 1 (not "officially" in 3.1.1)
this.qosLevel = QOS_LEVEL_AT_LEAST_ONCE; this.QosLevel = QOS_LEVEL_AT_LEAST_ONCE;
} }
/// <summary> /// <summary>
@ -75,148 +64,141 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
/// <param name="protocolVersion">Protocol Version</param> /// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param> /// <param name="channel">Channel connected to the broker</param>
/// <returns>UNSUBSCRIBE message instance</returns> /// <returns>UNSUBSCRIBE message instance</returns>
public static MqttMsgUnsubscribe Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) public static MqttMsgUnsubscribe Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
{ Byte[] buffer;
byte[] buffer; Int32 index = 0;
int index = 0; Byte[] topicUtf8;
byte[] topicUtf8; Int32 topicUtf8Length;
int topicUtf8Length;
MqttMsgUnsubscribe msg = new MqttMsgUnsubscribe(); MqttMsgUnsubscribe msg = new MqttMsgUnsubscribe();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
{
// [v3.1.1] check flag bits // [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBSCRIBE_FLAG_BITS) if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBSCRIBE_FLAG_BITS) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
} }
}
// get remaining length and allocate buffer // get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); Int32 remainingLength = DecodeRemainingLength(channel);
buffer = new byte[remainingLength]; buffer = new Byte[remainingLength];
// read bytes from socket... // read bytes from socket...
int received = channel.Receive(buffer); Int32 received = channel.Receive(buffer);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1) if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1) {
{
// only 3.1.0 // only 3.1.0
// read QoS level from fixed header // read QoS level from fixed header
msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET); msg.QosLevel = (Byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
// read DUP flag from fixed header // read DUP flag from fixed header
msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01); msg.DupFlag = (fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET == 0x01;
// retain flag not used // retain flag not used
msg.retain = false; msg.Retain = false;
} }
// message id // message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]); msg.MessageId |= buffer[index++];
// payload contains topics // payload contains topics
// NOTE : before, I don't know how many topics will be in the payload (so use List) // NOTE : before, I don't know how many topics will be in the payload (so use List)
// if .Net Micro Framework // if .Net Micro Framework
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3) #if MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
IList tmpTopics = new ArrayList(); IList tmpTopics = new ArrayList();
// else other frameworks (.Net, .Net Compact, Mono, Windows Phone) // else other frameworks (.Net, .Net Compact, Mono, Windows Phone)
#else #else
IList<String> tmpTopics = new List<String>(); IList<String> tmpTopics = new List<String>();
#endif #endif
do do {
{
// topic name // topic name
topicUtf8Length = ((buffer[index++] << 8) & 0xFF00); topicUtf8Length = (buffer[index++] << 8) & 0xFF00;
topicUtf8Length |= buffer[index++]; topicUtf8Length |= buffer[index++];
topicUtf8 = new byte[topicUtf8Length]; topicUtf8 = new Byte[topicUtf8Length];
Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length); Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length);
index += topicUtf8Length; index += topicUtf8Length;
tmpTopics.Add(new String(Encoding.UTF8.GetChars(topicUtf8))); tmpTopics.Add(new String(Encoding.UTF8.GetChars(topicUtf8)));
} while (index < remainingLength); } while (index < remainingLength);
// copy from list to array // copy from list to array
msg.topics = new string[tmpTopics.Count]; msg.Topics = new String[tmpTopics.Count];
for (int i = 0; i < tmpTopics.Count; i++) for (Int32 i = 0; i < tmpTopics.Count; i++) {
{ msg.Topics[i] = (String)tmpTopics[i];
msg.topics[i] = (string)tmpTopics[i];
} }
return msg; return msg;
} }
public override byte[] GetBytes(byte protocolVersion) public override Byte[] GetBytes(Byte protocolVersion) {
{ Int32 varHeaderSize = 0;
int fixedHeaderSize = 0; Int32 payloadSize = 0;
int varHeaderSize = 0; Int32 remainingLength = 0;
int payloadSize = 0; Byte[] buffer;
int remainingLength = 0; Int32 index = 0;
byte[] buffer;
int index = 0;
// topics list empty // topics list empty
if ((this.topics == null) || (this.topics.Length == 0)) if (this.Topics == null || this.Topics.Length == 0) {
throw new MqttClientException(MqttClientErrorCode.TopicsEmpty); throw new MqttClientException(MqttClientErrorCode.TopicsEmpty);
}
// message identifier // message identifier
varHeaderSize += MESSAGE_ID_SIZE; varHeaderSize += MESSAGE_ID_SIZE;
Byte[][] topicsUtf8 = new Byte[this.Topics.Length][];
int topicIdx = 0;
byte[][] topicsUtf8 = new byte[this.topics.Length][];
for (topicIdx = 0; topicIdx < this.topics.Length; topicIdx++) Int32 topicIdx;
{ for (topicIdx = 0; topicIdx < this.Topics.Length; topicIdx++) {
// check topic length // check topic length
if ((this.topics[topicIdx].Length < MIN_TOPIC_LENGTH) || (this.topics[topicIdx].Length > MAX_TOPIC_LENGTH)) if (this.Topics[topicIdx].Length < MIN_TOPIC_LENGTH || this.Topics[topicIdx].Length > MAX_TOPIC_LENGTH) {
throw new MqttClientException(MqttClientErrorCode.TopicLength); throw new MqttClientException(MqttClientErrorCode.TopicLength);
}
topicsUtf8[topicIdx] = Encoding.UTF8.GetBytes(this.topics[topicIdx]); topicsUtf8[topicIdx] = Encoding.UTF8.GetBytes(this.Topics[topicIdx]);
payloadSize += 2; // topic size (MSB, LSB) payloadSize += 2; // topic size (MSB, LSB)
payloadSize += topicsUtf8[topicIdx].Length; payloadSize += topicsUtf8[topicIdx].Length;
} }
remainingLength += (varHeaderSize + payloadSize); remainingLength += varHeaderSize + payloadSize;
// first byte of fixed header // first byte of fixed header
fixedHeaderSize = 1; Int32 fixedHeaderSize = 1;
int temp = remainingLength; Int32 temp = remainingLength;
// increase fixed header size based on remaining length // increase fixed header size based on remaining length
// (each remaining length byte can encode until 128) // (each remaining length byte can encode until 128)
do do {
{
fixedHeaderSize++; fixedHeaderSize++;
temp = temp / 128; temp /= 128;
} while (temp > 0); } while (temp > 0);
// allocate buffer for message // allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize]; buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte // first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) 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] buffer[index++] = (MQTT_MSG_UNSUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_UNSUBSCRIBE_FLAG_BITS; // [v.3.1.1]
else } else {
{ buffer[index] = (Byte)((MQTT_MSG_UNSUBSCRIBE_TYPE << MSG_TYPE_OFFSET) |
buffer[index] = (byte)((MQTT_MSG_UNSUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | (this.QosLevel << QOS_LEVEL_OFFSET));
(this.qosLevel << QOS_LEVEL_OFFSET)); buffer[index] |= this.DupFlag ? (Byte)(1 << DUP_FLAG_OFFSET) : (Byte)0x00;
buffer[index] |= this.dupFlag ? (byte)(1 << DUP_FLAG_OFFSET) : (byte)0x00;
index++; index++;
} }
// encode remaining length // encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index); index = this.EncodeRemainingLength(remainingLength, buffer, index);
// check message identifier assigned // check message identifier assigned
if (this.messageId == 0) if (this.MessageId == 0) {
throw new MqttClientException(MqttClientErrorCode.WrongMessageId); throw new MqttClientException(MqttClientErrorCode.WrongMessageId);
buffer[index++] = (byte)((messageId >> 8) & 0x00FF); // MSB }
buffer[index++] = (byte)(messageId & 0x00FF); // LSB
topicIdx = 0; buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
for (topicIdx = 0; topicIdx < this.topics.Length; topicIdx++) buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
{
for (topicIdx = 0; topicIdx < this.Topics.Length; topicIdx++) {
// topic name // topic name
buffer[index++] = (byte)((topicsUtf8[topicIdx].Length >> 8) & 0x00FF); // MSB buffer[index++] = (Byte)((topicsUtf8[topicIdx].Length >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(topicsUtf8[topicIdx].Length & 0x00FF); // LSB buffer[index++] = (Byte)(topicsUtf8[topicIdx].Length & 0x00FF); // LSB
Array.Copy(topicsUtf8[topicIdx], 0, buffer, index, topicsUtf8[topicIdx].Length); Array.Copy(topicsUtf8[topicIdx], 0, buffer, index, topicsUtf8[topicIdx].Length);
index += topicsUtf8[topicIdx].Length; index += topicsUtf8[topicIdx].Length;
} }
@ -224,16 +206,15 @@ namespace uPLibrary.Networking.M2Mqtt.Messages
return buffer; return buffer;
} }
public override string ToString() public override String ToString() =>
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"UNSUBSCRIBE", "UNSUBSCRIBE",
new object[] { "messageId", "topics" }, new Object[] { "messageId", "topics" },
new object[] { this.messageId, this.topics }); new Object[] { this.MessageId, this.Topics });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -14,55 +14,41 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System; using System;
#else #else
using Microsoft.SPOT; using Microsoft.SPOT;
#endif #endif
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Event Args class for unsubscribe request on topics /// Event Args class for unsubscribe request on topics
/// </summary> /// </summary>
public class MqttMsgUnsubscribeEventArgs : EventArgs public class MqttMsgUnsubscribeEventArgs : EventArgs {
{
#region Properties... #region Properties...
/// <summary> /// <summary>
/// Message identifier /// Message identifier
/// </summary> /// </summary>
public ushort MessageId public UInt16 MessageId { get; internal set; }
{
get { return this.messageId; }
internal set { this.messageId = value; }
}
/// <summary> /// <summary>
/// Topics requested to subscribe /// Topics requested to subscribe
/// </summary> /// </summary>
public string[] Topics public String[] Topics { get; internal set; }
{
get { return this.topics; }
internal set { this.topics = value; }
}
#endregion #endregion
// message identifier // message identifier
ushort messageId;
// topics requested to unsubscribe
string[] topics;
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
/// <param name="messageId">Message identifier for subscribed topics</param> /// <param name="messageId">Message identifier for subscribed topics</param>
/// <param name="topics">Topics requested to subscribe</param> /// <param name="topics">Topics requested to subscribe</param>
public MqttMsgUnsubscribeEventArgs(ushort messageId, string[] topics) public MqttMsgUnsubscribeEventArgs(UInt16 messageId, String[] topics) {
{ this.MessageId = messageId;
this.messageId = messageId; this.Topics = topics;
this.topics = topics;
} }
} }
} }

View File

@ -14,42 +14,32 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System; using System;
#else #else
using Microsoft.SPOT; using Microsoft.SPOT;
#endif #endif
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{
/// <summary> /// <summary>
/// Event Args class for unsubscribed topic /// Event Args class for unsubscribed topic
/// </summary> /// </summary>
public class MqttMsgUnsubscribedEventArgs : EventArgs public class MqttMsgUnsubscribedEventArgs : EventArgs {
{
#region Properties... #region Properties...
/// <summary> /// <summary>
/// Message identifier /// Message identifier
/// </summary> /// </summary>
public ushort MessageId public UInt16 MessageId { get; internal set; }
{
get { return this.messageId; }
internal set { this.messageId = value; }
}
#endregion #endregion
// message identifier // message identifier
ushort messageId;
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
/// <param name="messageId">Message identifier for unsubscribed topic</param> /// <param name="messageId">Message identifier for unsubscribed topic</param>
public MqttMsgUnsubscribedEventArgs(ushort messageId) public MqttMsgUnsubscribedEventArgs(UInt16 messageId) => this.MessageId = messageId;
{
this.messageId = messageId;
}
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -14,13 +14,11 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
namespace uPLibrary.Networking.M2Mqtt namespace uPLibrary.Networking.M2Mqtt {
{
/// <summary> /// <summary>
/// Supported SSL/TLS protocol versions /// Supported SSL/TLS protocol versions
/// </summary> /// </summary>
public enum MqttSslProtocols public enum MqttSslProtocols {
{
None, None,
SSLv3, SSLv3,
TLSv1_0, TLSv1_0,

View File

@ -14,72 +14,72 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
namespace uPLibrary.Networking.M2Mqtt using System;
{
namespace uPLibrary.Networking.M2Mqtt {
/// <summary> /// <summary>
/// Settings class for the MQTT broker /// Settings class for the MQTT broker
/// </summary> /// </summary>
public class MqttSettings public class MqttSettings {
{
// default port for MQTT protocol // default port for MQTT protocol
public const int MQTT_BROKER_DEFAULT_PORT = 1883; public const Int32 MQTT_BROKER_DEFAULT_PORT = 1883;
public const int MQTT_BROKER_DEFAULT_SSL_PORT = 8883; public const Int32 MQTT_BROKER_DEFAULT_SSL_PORT = 8883;
// default timeout on receiving from client // default timeout on receiving from client
public const int MQTT_DEFAULT_TIMEOUT = 30000; public const Int32 MQTT_DEFAULT_TIMEOUT = 30000;
// max publish, subscribe and unsubscribe retry for QoS Level 1 or 2 // max publish, subscribe and unsubscribe retry for QoS Level 1 or 2
public const int MQTT_ATTEMPTS_RETRY = 3; public const Int32 MQTT_ATTEMPTS_RETRY = 3;
// delay for retry publish, subscribe and unsubscribe for QoS Level 1 or 2 // delay for retry publish, subscribe and unsubscribe for QoS Level 1 or 2
public const int MQTT_DELAY_RETRY = 10000; public const Int32 MQTT_DELAY_RETRY = 10000;
// broker need to receive the first message (CONNECT) // broker need to receive the first message (CONNECT)
// within a reasonable amount of time after TCP/IP connection // within a reasonable amount of time after TCP/IP connection
public const int MQTT_CONNECT_TIMEOUT = 30000; public const Int32 MQTT_CONNECT_TIMEOUT = 30000;
// default inflight queue size // default inflight queue size
public const int MQTT_MAX_INFLIGHT_QUEUE_SIZE = int.MaxValue; public const Int32 MQTT_MAX_INFLIGHT_QUEUE_SIZE = Int32.MaxValue;
/// <summary> /// <summary>
/// Listening connection port /// Listening connection port
/// </summary> /// </summary>
public int Port { get; internal set; } public Int32 Port { get; internal set; }
/// <summary> /// <summary>
/// Listening connection SSL port /// Listening connection SSL port
/// </summary> /// </summary>
public int SslPort { get; internal set; } public Int32 SslPort { get; internal set; }
/// <summary> /// <summary>
/// Timeout on client connection (before receiving CONNECT message) /// Timeout on client connection (before receiving CONNECT message)
/// </summary> /// </summary>
public int TimeoutOnConnection { get; internal set; } public Int32 TimeoutOnConnection { get; internal set; }
/// <summary> /// <summary>
/// Timeout on receiving /// Timeout on receiving
/// </summary> /// </summary>
public int TimeoutOnReceiving { get; internal set; } public Int32 TimeoutOnReceiving { get; internal set; }
/// <summary> /// <summary>
/// Attempts on retry /// Attempts on retry
/// </summary> /// </summary>
public int AttemptsOnRetry { get; internal set; } public Int32 AttemptsOnRetry { get; internal set; }
/// <summary> /// <summary>
/// Delay on retry /// Delay on retry
/// </summary> /// </summary>
public int DelayOnRetry { get; internal set; } public Int32 DelayOnRetry { get; internal set; }
/// <summary> /// <summary>
/// Inflight queue size /// Inflight queue size
/// </summary> /// </summary>
public int InflightQueueSize { get; set; } public Int32 InflightQueueSize { get; set; }
/// <summary> /// <summary>
/// Singleton instance of settings /// Singleton instance of settings
/// </summary> /// </summary>
public static MqttSettings Instance public static MqttSettings Instance {
{ get {
get if (instance == null) {
{
if (instance == null)
instance = new MqttSettings(); instance = new MqttSettings();
}
return instance; return instance;
} }
} }
@ -90,8 +90,7 @@ namespace uPLibrary.Networking.M2Mqtt
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
private MqttSettings() private MqttSettings() {
{
this.Port = MQTT_BROKER_DEFAULT_PORT; this.Port = MQTT_BROKER_DEFAULT_PORT;
this.SslPort = MQTT_BROKER_DEFAULT_SSL_PORT; this.SslPort = MQTT_BROKER_DEFAULT_SSL_PORT;
this.TimeoutOnReceiving = MQTT_DEFAULT_TIMEOUT; this.TimeoutOnReceiving = MQTT_DEFAULT_TIMEOUT;

View File

@ -14,23 +14,16 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
using System;
using System.Threading; using System.Threading;
namespace uPLibrary.Networking.M2Mqtt namespace uPLibrary.Networking.M2Mqtt {
{
/// <summary> /// <summary>
/// Support methods fos specific framework /// Support methods fos specific framework
/// </summary> /// </summary>
public class Fx public class Fx {
{ public static void StartThread(ThreadStart threadStart) => new Thread(threadStart).Start();
public static void StartThread(ThreadStart threadStart)
{
new Thread(threadStart).Start();
}
public static void SleepThread(int millisecondsTimeout) public static void SleepThread(Int32 millisecondsTimeout) => Thread.Sleep(millisecondsTimeout);
{
Thread.Sleep(millisecondsTimeout);
}
} }
} }

View File

@ -15,13 +15,17 @@ Contributors:
*/ */
#if SSL #if SSL
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3) #if MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
using Microsoft.SPOT.Net.Security; using Microsoft.SPOT.Net.Security;
#else #else
using System.Net.Security;
using System.Security.Authentication; using System.Security.Authentication;
#if NETCOREAPP
using System.Net.Security;
#endif
#endif #endif
#endif #endif
using System.Net.Sockets; using System.Net.Sockets;
using System.Net; using System.Net;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
@ -29,56 +33,52 @@ using System;
//using System.Security.Authentication; //using System.Security.Authentication;
//using System.Net.Security; //using System.Net.Security;
namespace uPLibrary.Networking.M2Mqtt namespace uPLibrary.Networking.M2Mqtt {
{
/// <summary> /// <summary>
/// Channel to communicate over the network /// Channel to communicate over the network
/// </summary> /// </summary>
public class MqttNetworkChannel : IMqttNetworkChannel public class MqttNetworkChannel : IMqttNetworkChannel {
{
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) #if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
private readonly RemoteCertificateValidationCallback userCertificateValidationCallback; private readonly RemoteCertificateValidationCallback userCertificateValidationCallback;
private readonly LocalCertificateSelectionCallback userCertificateSelectionCallback; private readonly LocalCertificateSelectionCallback userCertificateSelectionCallback;
#endif #endif
// remote host information // remote host information
private string remoteHostName;
private IPAddress remoteIpAddress;
private int remotePort;
// socket for communication // socket for communication
private Socket socket; private Socket socket;
// using SSL // using SSL
private bool secure; private readonly Boolean secure;
#if MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
// CA certificate (on client) // CA certificate (on client)
private X509Certificate caCert; private readonly X509Certificate caCert;
#endif
// Server certificate (on broker) // Server certificate (on broker)
private X509Certificate serverCert; private readonly X509Certificate serverCert;
// client certificate (on client) // client certificate (on client)
private X509Certificate clientCert; private readonly X509Certificate clientCert;
// SSL/TLS protocol version // SSL/TLS protocol version
private MqttSslProtocols sslProtocol; private readonly MqttSslProtocols sslProtocol;
/// <summary> /// <summary>
/// Remote host name /// Remote host name
/// </summary> /// </summary>
public string RemoteHostName { get { return this.remoteHostName; } } public String RemoteHostName { get; }
/// <summary> /// <summary>
/// Remote IP address /// Remote IP address
/// </summary> /// </summary>
public IPAddress RemoteIpAddress { get { return this.remoteIpAddress; } } public IPAddress RemoteIpAddress { get; }
/// <summary> /// <summary>
/// Remote port /// Remote port
/// </summary> /// </summary>
public int RemotePort { get { return this.remotePort; } } public Int32 RemotePort { get; }
#if SSL #if SSL
// SSL stream // SSL stream
private SslStream sslStream; private SslStream sslStream;
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
private NetworkStream netStream; private NetworkStream netStream;
#endif #endif
#endif #endif
@ -86,27 +86,15 @@ namespace uPLibrary.Networking.M2Mqtt
/// <summary> /// <summary>
/// Data available on the channel /// Data available on the channel
/// </summary> /// </summary>
public bool DataAvailable
{
get
{
#if SSL #if SSL
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3) #if MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
if (secure) public Boolean DataAvailable => this.secure ? this.sslStream.DataAvailable : this.socket.Available > 0;
return this.sslStream.DataAvailable;
else
return (this.socket.Available > 0);
#else #else
if (secure) public Boolean DataAvailable => this.secure ? this.netStream.DataAvailable : this.socket.Available > 0;
return this.netStream.DataAvailable;
else
return (this.socket.Available > 0);
#endif #endif
#else #else
return (this.socket.Available > 0); public Boolean DataAvailable => this.socket.Available > 0;
#endif #endif
}
}
/// <summary> /// <summary>
/// Constructor /// Constructor
@ -132,7 +120,7 @@ namespace uPLibrary.Networking.M2Mqtt
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) #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="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> /// <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, public MqttNetworkChannel(Socket socket, Boolean secure, X509Certificate serverCert, MqttSslProtocols sslProtocol,
RemoteCertificateValidationCallback userCertificateValidationCallback, RemoteCertificateValidationCallback userCertificateValidationCallback,
LocalCertificateSelectionCallback userCertificateSelectionCallback) LocalCertificateSelectionCallback userCertificateSelectionCallback)
#else #else
@ -154,7 +142,7 @@ namespace uPLibrary.Networking.M2Mqtt
/// </summary> /// </summary>
/// <param name="remoteHostName">Remote Host name</param> /// <param name="remoteHostName">Remote Host name</param>
/// <param name="remotePort">Remote port</param> /// <param name="remotePort">Remote port</param>
public MqttNetworkChannel(string remoteHostName, int remotePort) public MqttNetworkChannel(String remoteHostName, Int32 remotePort)
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) #if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
: this(remoteHostName, remotePort, false, null, null, MqttSslProtocols.None, null, null) : this(remoteHostName, remotePort, false, null, null, MqttSslProtocols.None, null, null)
#else #else
@ -175,7 +163,7 @@ namespace uPLibrary.Networking.M2Mqtt
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) #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="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> /// <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, public MqttNetworkChannel(String remoteHostName, Int32 remotePort, Boolean secure, X509Certificate caCert, X509Certificate clientCert, MqttSslProtocols sslProtocol,
RemoteCertificateValidationCallback userCertificateValidationCallback, RemoteCertificateValidationCallback userCertificateValidationCallback,
LocalCertificateSelectionCallback userCertificateSelectionCallback) LocalCertificateSelectionCallback userCertificateSelectionCallback)
#else #else
@ -183,38 +171,36 @@ namespace uPLibrary.Networking.M2Mqtt
#endif #endif
{ {
IPAddress remoteIpAddress = null; IPAddress remoteIpAddress = null;
try try {
{
// check if remoteHostName is a valid IP address and get it // check if remoteHostName is a valid IP address and get it
remoteIpAddress = IPAddress.Parse(remoteHostName); remoteIpAddress = IPAddress.Parse(remoteHostName);
} } catch {
catch
{
} }
// in this case the parameter remoteHostName isn't a valid IP address // in this case the parameter remoteHostName isn't a valid IP address
if (remoteIpAddress == null) if (remoteIpAddress == null) {
{
IPHostEntry hostEntry = Dns.GetHostEntry(remoteHostName); IPHostEntry hostEntry = Dns.GetHostEntry(remoteHostName);
if ((hostEntry != null) && (hostEntry.AddressList.Length > 0)) if (hostEntry != null && hostEntry.AddressList.Length > 0) {
{
// check for the first address not null // check for the first address not null
// it seems that with .Net Micro Framework, the IPV6 addresses aren't supported and return "null" // it seems that with .Net Micro Framework, the IPV6 addresses aren't supported and return "null"
int i = 0; Int32 i = 0;
while (hostEntry.AddressList[i] == null) i++; while (hostEntry.AddressList[i] == null) {
remoteIpAddress = hostEntry.AddressList[i]; i++;
} }
else
{ remoteIpAddress = hostEntry.AddressList[i];
} else {
throw new Exception("No address found for the remote host name"); throw new Exception("No address found for the remote host name");
} }
} }
this.remoteHostName = remoteHostName; this.RemoteHostName = remoteHostName;
this.remoteIpAddress = remoteIpAddress; this.RemoteIpAddress = remoteIpAddress;
this.remotePort = remotePort; this.RemotePort = remotePort;
this.secure = secure; this.secure = secure;
#if MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
this.caCert = caCert; this.caCert = caCert;
#endif
this.clientCert = clientCert; this.clientCert = clientCert;
this.sslProtocol = sslProtocol; this.sslProtocol = sslProtocol;
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) #if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
@ -226,18 +212,16 @@ namespace uPLibrary.Networking.M2Mqtt
/// <summary> /// <summary>
/// Connect to remote server /// Connect to remote server
/// </summary> /// </summary>
public void Connect() public void Connect() {
{ this.socket = new Socket(IPAddressUtility.GetAddressFamily(this.RemoteIpAddress), SocketType.Stream, ProtocolType.Tcp);
this.socket = new Socket(IPAddressUtility.GetAddressFamily(this.remoteIpAddress), SocketType.Stream, ProtocolType.Tcp);
// try connection to the broker // try connection to the broker
this.socket.Connect(new IPEndPoint(this.remoteIpAddress, this.remotePort)); this.socket.Connect(new IPEndPoint(this.RemoteIpAddress, this.RemotePort));
#if SSL #if SSL
// secure channel requested // secure channel requested
if (secure) if (this.secure) {
{
// create SSL stream // create SSL stream
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3) #if MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
this.sslStream = new SslStream(this.socket); this.sslStream = new SslStream(this.socket);
#else #else
this.netStream = new NetworkStream(this.socket); this.netStream = new NetworkStream(this.socket);
@ -245,7 +229,7 @@ namespace uPLibrary.Networking.M2Mqtt
#endif #endif
// server authentication (SSL/TLS handshake) // server authentication (SSL/TLS handshake)
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3) #if MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
this.sslStream.AuthenticateAsClient(this.remoteHostName, this.sslStream.AuthenticateAsClient(this.remoteHostName,
this.clientCert, this.clientCert,
new X509Certificate[] { this.caCert }, new X509Certificate[] { this.caCert },
@ -254,10 +238,11 @@ namespace uPLibrary.Networking.M2Mqtt
#else #else
X509CertificateCollection clientCertificates = null; X509CertificateCollection clientCertificates = null;
// check if there is a client certificate to add to the collection, otherwise it's null (as empty) // check if there is a client certificate to add to the collection, otherwise it's null (as empty)
if (this.clientCert != null) if (this.clientCert != null) {
clientCertificates = new X509CertificateCollection(new X509Certificate[] { this.clientCert }); clientCertificates = new X509CertificateCollection(new X509Certificate[] { this.clientCert });
}
this.sslStream.AuthenticateAsClient(this.remoteHostName, this.sslStream.AuthenticateAsClient(this.RemoteHostName,
clientCertificates, clientCertificates,
MqttSslUtility.ToSslPlatformEnum(this.sslProtocol), MqttSslUtility.ToSslPlatformEnum(this.sslProtocol),
false); false);
@ -272,17 +257,15 @@ namespace uPLibrary.Networking.M2Mqtt
/// </summary> /// </summary>
/// <param name="buffer">Data buffer to send</param> /// <param name="buffer">Data buffer to send</param>
/// <returns>Number of byte sent</returns> /// <returns>Number of byte sent</returns>
public int Send(byte[] buffer) public Int32 Send(Byte[] buffer) {
{
#if SSL #if SSL
if (this.secure) if (this.secure) {
{
this.sslStream.Write(buffer, 0, buffer.Length); this.sslStream.Write(buffer, 0, buffer.Length);
this.sslStream.Flush(); this.sslStream.Flush();
return buffer.Length; return buffer.Length;
} } else {
else
return this.socket.Send(buffer, 0, buffer.Length, SocketFlags.None); return this.socket.Send(buffer, 0, buffer.Length, SocketFlags.None);
}
#else #else
return this.socket.Send(buffer, 0, buffer.Length, SocketFlags.None); return this.socket.Send(buffer, 0, buffer.Length, SocketFlags.None);
#endif #endif
@ -293,35 +276,33 @@ namespace uPLibrary.Networking.M2Mqtt
/// </summary> /// </summary>
/// <param name="buffer">Data buffer for receiving data</param> /// <param name="buffer">Data buffer for receiving data</param>
/// <returns>Number of bytes received</returns> /// <returns>Number of bytes received</returns>
public int Receive(byte[] buffer) public Int32 Receive(Byte[] buffer) {
{
#if SSL #if SSL
if (this.secure) if (this.secure) {
{
// read all data needed (until fill buffer) // read all data needed (until fill buffer)
int idx = 0, read = 0; Int32 idx = 0, read = 0;
while (idx < buffer.Length) while (idx < buffer.Length) {
{
// fixed scenario with socket closed gracefully by peer/broker and // fixed scenario with socket closed gracefully by peer/broker and
// Read return 0. Avoid infinite loop. // Read return 0. Avoid infinite loop.
read = this.sslStream.Read(buffer, idx, buffer.Length - idx); read = this.sslStream.Read(buffer, idx, buffer.Length - idx);
if (read == 0) if (read == 0) {
return 0; return 0;
}
idx += read; idx += read;
} }
return buffer.Length; return buffer.Length;
} } else {
else
{
// read all data needed (until fill buffer) // read all data needed (until fill buffer)
int idx = 0, read = 0; Int32 idx = 0, read = 0;
while (idx < buffer.Length) while (idx < buffer.Length) {
{
// fixed scenario with socket closed gracefully by peer/broker and // fixed scenario with socket closed gracefully by peer/broker and
// Read return 0. Avoid infinite loop. // Read return 0. Avoid infinite loop.
read = this.socket.Receive(buffer, idx, buffer.Length - idx, SocketFlags.None); read = this.socket.Receive(buffer, idx, buffer.Length - idx, SocketFlags.None);
if (read == 0) if (read == 0) {
return 0; return 0;
}
idx += read; idx += read;
} }
return buffer.Length; return buffer.Length;
@ -348,28 +329,17 @@ namespace uPLibrary.Networking.M2Mqtt
/// <param name="buffer">Data buffer for receiving data</param> /// <param name="buffer">Data buffer for receiving data</param>
/// <param name="timeout">Timeout on receiving (in milliseconds)</param> /// <param name="timeout">Timeout on receiving (in milliseconds)</param>
/// <returns>Number of bytes received</returns> /// <returns>Number of bytes received</returns>
public int Receive(byte[] buffer, int timeout) public Int32 Receive(Byte[] buffer, Int32 timeout) =>
{
// check data availability (timeout is in microseconds) // check data availability (timeout is in microseconds)
if (this.socket.Poll(timeout * 1000, SelectMode.SelectRead)) this.socket.Poll(timeout * 1000, SelectMode.SelectRead) ? this.Receive(buffer) : 0;
{
return this.Receive(buffer);
}
else
{
return 0;
}
}
/// <summary> /// <summary>
/// Close the network channel /// Close the network channel
/// </summary> /// </summary>
public void Close() public void Close() {
{
#if SSL #if SSL
if (this.secure) if (this.secure) {
{ #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
this.netStream.Close(); this.netStream.Close();
#endif #endif
this.sslStream.Close(); this.sslStream.Close();
@ -383,12 +353,10 @@ namespace uPLibrary.Networking.M2Mqtt
/// <summary> /// <summary>
/// Accept connection from a remote client /// Accept connection from a remote client
/// </summary> /// </summary>
public void Accept() public void Accept() {
{
#if SSL #if SSL
// secure channel requested // secure channel requested
if (secure) if (this.secure) {
{
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3) #if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
this.netStream = new NetworkStream(this.socket); this.netStream = new NetworkStream(this.socket);
@ -408,49 +376,38 @@ namespace uPLibrary.Networking.M2Mqtt
/// <summary> /// <summary>
/// IPAddress Utility class /// IPAddress Utility class
/// </summary> /// </summary>
public static class IPAddressUtility public static class IPAddressUtility {
{
/// <summary> /// <summary>
/// Return AddressFamily for the IP address /// Return AddressFamily for the IP address
/// </summary> /// </summary>
/// <param name="ipAddress">IP address to check</param> /// <param name="ipAddress">IP address to check</param>
/// <returns>Address family</returns> /// <returns>Address family</returns>
public static AddressFamily GetAddressFamily(IPAddress ipAddress) public static AddressFamily GetAddressFamily(IPAddress ipAddress) =>
{ #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) ipAddress.AddressFamily;
return ipAddress.AddressFamily;
#else #else
return (ipAddress.ToString().IndexOf(':') != -1) ? return (ipAddress.ToString().IndexOf(':') != -1) ?
AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork; AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork;
#endif #endif
}
} }
/// <summary> /// <summary>
/// MQTT SSL utility class /// MQTT SSL utility class
/// </summary> /// </summary>
public static class MqttSslUtility public static class MqttSslUtility {
#if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3 && !COMPACT_FRAMEWORK
public static SslProtocols ToSslPlatformEnum(MqttSslProtocols mqttSslProtocol) => mqttSslProtocol switch
{ {
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3 && !COMPACT_FRAMEWORK) MqttSslProtocols.None => SslProtocols.None,
public static SslProtocols ToSslPlatformEnum(MqttSslProtocols mqttSslProtocol) //MqttSslProtocols.SSLv3 => SslProtocols.Ssl3,
{ MqttSslProtocols.TLSv1_0 => SslProtocols.Tls,
switch (mqttSslProtocol) MqttSslProtocols.TLSv1_1 => SslProtocols.Tls11,
{ MqttSslProtocols.TLSv1_2 => SslProtocols.Tls12,
case MqttSslProtocols.None: _ => throw new ArgumentException("SSL/TLS protocol version not supported"),
return SslProtocols.None; };
case MqttSslProtocols.SSLv3: #elif MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
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) public static SslProtocols ToSslPlatformEnum(MqttSslProtocols mqttSslProtocol)
{ {
switch (mqttSslProtocol) switch (mqttSslProtocol)

View File

@ -13,7 +13,7 @@ and the Eclipse Distribution License is available at
Contributors: Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if !NETCOREAPP
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -42,3 +42,4 @@ using System.Runtime.InteropServices;
#if !WindowsCE #if !WindowsCE
[assembly: AssemblyFileVersion("4.3.0.0")] [assembly: AssemblyFileVersion("4.3.0.0")]
#endif #endif
#endif

View File

@ -14,20 +14,18 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
namespace uPLibrary.Networking.M2Mqtt.Session using System;
{
namespace uPLibrary.Networking.M2Mqtt.Session {
/// <summary> /// <summary>
/// MQTT Client Session /// MQTT Client Session
/// </summary> /// </summary>
public class MqttClientSession : MqttSession public class MqttClientSession : MqttSession {
{
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
/// <param name="clientId">Client Id to create session</param> /// <param name="clientId">Client Id to create session</param>
public MqttClientSession(string clientId) public MqttClientSession(String clientId) : base(clientId) {
: base(clientId)
{
} }
} }
} }

View File

@ -14,19 +14,18 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
using System;
using System.Collections; using System.Collections;
namespace uPLibrary.Networking.M2Mqtt.Session namespace uPLibrary.Networking.M2Mqtt.Session {
{
/// <summary> /// <summary>
/// MQTT Session base class /// MQTT Session base class
/// </summary> /// </summary>
public abstract class MqttSession public abstract class MqttSession {
{
/// <summary> /// <summary>
/// Client Id /// Client Id
/// </summary> /// </summary>
public string ClientId { get; set; } public String ClientId { get; set; }
/// <summary> /// <summary>
/// Messages inflight during session /// Messages inflight during session
@ -37,16 +36,14 @@ namespace uPLibrary.Networking.M2Mqtt.Session
/// Constructor /// Constructor
/// </summary> /// </summary>
public MqttSession() public MqttSession()
: this(null) : this(null) {
{
} }
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
/// <param name="clientId">Client Id to create session</param> /// <param name="clientId">Client Id to create session</param>
public MqttSession(string clientId) public MqttSession(String clientId) {
{
this.ClientId = clientId; this.ClientId = clientId;
this.InflightMessages = new Hashtable(); this.InflightMessages = new Hashtable();
} }
@ -54,8 +51,7 @@ namespace uPLibrary.Networking.M2Mqtt.Session
/// <summary> /// <summary>
/// Clean session /// Clean session
/// </summary> /// </summary>
public virtual void Clear() public virtual void Clear() {
{
this.ClientId = null; this.ClientId = null;
this.InflightMessages.Clear(); this.InflightMessages.Clear();
} }

View File

@ -17,19 +17,17 @@ Contributors:
using System; using System;
using System.Collections; using System.Collections;
namespace uPLibrary.Networking.M2Mqtt.Utility namespace uPLibrary.Networking.M2Mqtt.Utility {
{
/// <summary> /// <summary>
/// Extension class for a Queue /// Extension class for a Queue
/// </summary> /// </summary>
internal static class QueueExtension internal static class QueueExtension {
{
/// <summary> /// <summary>
/// Predicate for searching inside a queue /// Predicate for searching inside a queue
/// </summary> /// </summary>
/// <param name="item">Item of the queue</param> /// <param name="item">Item of the queue</param>
/// <returns>Result of predicate</returns> /// <returns>Result of predicate</returns>
internal delegate bool QueuePredicate(object item); internal delegate Boolean QueuePredicate(Object item);
/// <summary> /// <summary>
/// Get (without removing) an item from queue based on predicate /// Get (without removing) an item from queue based on predicate
@ -37,13 +35,12 @@ namespace uPLibrary.Networking.M2Mqtt.Utility
/// <param name="queue">Queue in which to search</param> /// <param name="queue">Queue in which to search</param>
/// <param name="predicate">Predicate to verify to get item</param> /// <param name="predicate">Predicate to verify to get item</param>
/// <returns>Item matches the predicate</returns> /// <returns>Item matches the predicate</returns>
internal static object Get(Queue queue, QueuePredicate predicate) internal static Object Get(Queue queue, QueuePredicate predicate) {
{ foreach (Object item in queue) {
foreach (var item in queue) if (predicate(item)) {
{
if (predicate(item))
return item; return item;
} }
}
return null; return null;
} }
} }

View File

@ -14,15 +14,14 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
using System;
using System.Diagnostics; using System.Diagnostics;
namespace uPLibrary.Networking.M2Mqtt.Utility namespace uPLibrary.Networking.M2Mqtt.Utility {
{
/// <summary> /// <summary>
/// Tracing levels /// Tracing levels
/// </summary> /// </summary>
public enum TraceLevel public enum TraceLevel {
{
Error = 0x01, Error = 0x01,
Warning = 0x02, Warning = 0x02,
Information = 0x04, Information = 0x04,
@ -32,54 +31,39 @@ namespace uPLibrary.Networking.M2Mqtt.Utility
} }
// delegate for writing trace // delegate for writing trace
public delegate void WriteTrace(string format, params object[] args); public delegate void WriteTrace(String format, params Object[] args);
/// <summary> /// <summary>
/// Tracing class /// Tracing class
/// </summary> /// </summary>
public static class Trace public static class Trace {
{
public static TraceLevel TraceLevel; public static TraceLevel TraceLevel;
public static WriteTrace TraceListener; public static WriteTrace TraceListener;
[Conditional("DEBUG")] [Conditional("DEBUG")]
public static void Debug(string format, params object[] args) public static void Debug(String format, params Object[] args) => TraceListener?.Invoke(format, args);
{
if (TraceListener != null) public static void WriteLine(TraceLevel level, String format) {
{ if ((level & TraceLevel) > 0) {
TraceListener(format, args); TraceListener.Invoke(format);
} }
} }
public static void WriteLine(TraceLevel level, string format) public static void WriteLine(TraceLevel level, String format, Object arg1) {
{ if ( (level & TraceLevel) > 0) {
if (TraceListener != null && (level & TraceLevel) > 0) TraceListener.Invoke(format, arg1);
{
TraceListener(format);
} }
} }
public static void WriteLine(TraceLevel level, string format, object arg1) public static void WriteLine(TraceLevel level, String format, Object arg1, Object arg2) {
{ if ((level & TraceLevel) > 0) {
if (TraceListener != null && (level & TraceLevel) > 0) TraceListener.Invoke(format, arg1, arg2);
{
TraceListener(format, arg1);
} }
} }
public static void WriteLine(TraceLevel level, string format, object arg1, object arg2) public static void WriteLine(TraceLevel level, String format, Object arg1, Object arg2, Object arg3) {
{ if ((level & TraceLevel) > 0) {
if (TraceListener != null && (level & TraceLevel) > 0) TraceListener.Invoke(format, arg1, arg2, arg3);
{
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);
} }
} }
} }

View File

@ -13,7 +13,7 @@ and the Eclipse Distribution License is available at
Contributors: Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if !NETCOREAPP
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -34,3 +34,4 @@ namespace uPLibrary.Networking.M2Mqtt
public static void SleepThread(int millisecondsTimeout) { Task.Delay(millisecondsTimeout).RunSynchronously(); } public static void SleepThread(int millisecondsTimeout) { Task.Delay(millisecondsTimeout).RunSynchronously(); }
} }
} }
#endif

View File

@ -13,7 +13,7 @@ and the Eclipse Distribution License is available at
Contributors: Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if !NETCOREAPP
using System.Collections.Generic; using System.Collections.Generic;
namespace uPLibrary.Networking.M2Mqtt namespace uPLibrary.Networking.M2Mqtt
@ -25,3 +25,4 @@ namespace uPLibrary.Networking.M2Mqtt
{ {
} }
} }
#endif

View File

@ -13,7 +13,7 @@ and the Eclipse Distribution License is available at
Contributors: Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if !NETCOREAPP
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -177,3 +177,4 @@ namespace uPLibrary.Networking.M2Mqtt
} }
} }
} }
#endif

View File

@ -13,7 +13,7 @@ and the Eclipse Distribution License is available at
Contributors: Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if !NETCOREAPP
using System.Collections.Generic; using System.Collections.Generic;
namespace uPLibrary.Networking.M2Mqtt namespace uPLibrary.Networking.M2Mqtt
@ -25,3 +25,4 @@ namespace uPLibrary.Networking.M2Mqtt
{ {
} }
} }
#endif

4
README.md Normal file
View File

@ -0,0 +1,4 @@
# M2Mqtt
Based on https://github.com/eclipse/paho.mqtt.m2mqtt
Maybe you find this Repo on Github. This is a mirror from [here](https://git.blubbfish.net/vs_librarys/mqtt).