Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
04d70426ef | |||
0957512354 | |||
7b3d608c17 | |||
bd6472e5e4 | |||
57f343c908 |
203
LICENSE
Normal file
203
LICENSE
Normal 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
25
M2Mqtt.sln
Normal 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
|
@ -16,117 +16,104 @@ Contributors:
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace uPLibrary.Networking.M2Mqtt.Exceptions
|
namespace uPLibrary.Networking.M2Mqtt.Exceptions {
|
||||||
{
|
/// <summary>
|
||||||
|
/// MQTT client exception
|
||||||
|
/// </summary>
|
||||||
|
public class MqttClientException : Exception {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// MQTT client exception
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttClientException : Exception
|
/// <param name="code">Error code</param>
|
||||||
{
|
public MqttClientException(MqttClientErrorCode errorCode) => this.ErrorCode = errorCode;
|
||||||
/// <summary>
|
|
||||||
/// Constructor
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="code">Error code</param>
|
|
||||||
public MqttClientException(MqttClientErrorCode errorCode)
|
|
||||||
{
|
|
||||||
this.errorCode = errorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// error code
|
|
||||||
private MqttClientErrorCode errorCode;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Error code
|
|
||||||
/// </summary>
|
|
||||||
public MqttClientErrorCode ErrorCode
|
|
||||||
{
|
|
||||||
get { return this.errorCode; }
|
|
||||||
set { this.errorCode = value; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// MQTT client erroro code
|
/// Error code
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum MqttClientErrorCode
|
public MqttClientErrorCode ErrorCode { get; set; }
|
||||||
{
|
}
|
||||||
/// <summary>
|
|
||||||
/// Will error (topic, message or QoS level)
|
/// <summary>
|
||||||
/// </summary>
|
/// MQTT client erroro code
|
||||||
WillWrong = 1,
|
/// </summary>
|
||||||
|
public enum MqttClientErrorCode {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Keep alive period too large
|
/// Will error (topic, message or QoS level)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
KeepAliveWrong,
|
WillWrong = 1,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Topic contains wildcards
|
/// Keep alive period too large
|
||||||
/// </summary>
|
/// </summary>
|
||||||
TopicWildcard,
|
KeepAliveWrong,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Topic length wrong
|
/// Topic contains wildcards
|
||||||
/// </summary>
|
/// </summary>
|
||||||
TopicLength,
|
TopicWildcard,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// QoS level not allowed
|
/// Topic length wrong
|
||||||
/// </summary>
|
/// </summary>
|
||||||
QosNotAllowed,
|
TopicLength,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Topics list empty for subscribe
|
/// QoS level not allowed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
TopicsEmpty,
|
QosNotAllowed,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Qos levels list empty for subscribe
|
/// Topics list empty for subscribe
|
||||||
/// </summary>
|
/// </summary>
|
||||||
QosLevelsEmpty,
|
TopicsEmpty,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Topics / Qos Levels not match in subscribe
|
/// Qos levels list empty for subscribe
|
||||||
/// </summary>
|
/// </summary>
|
||||||
TopicsQosLevelsNotMatch,
|
QosLevelsEmpty,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Wrong message from broker
|
/// Topics / Qos Levels not match in subscribe
|
||||||
/// </summary>
|
/// </summary>
|
||||||
WrongBrokerMessage,
|
TopicsQosLevelsNotMatch,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Wrong Message Id
|
/// Wrong message from broker
|
||||||
/// </summary>
|
/// </summary>
|
||||||
WrongMessageId,
|
WrongBrokerMessage,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Inflight queue is full
|
/// Wrong Message Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
InflightQueueFull,
|
WrongMessageId,
|
||||||
|
|
||||||
// [v3.1.1]
|
/// <summary>
|
||||||
/// <summary>
|
/// Inflight queue is full
|
||||||
/// Invalid flag bits received
|
/// </summary>
|
||||||
/// </summary>
|
InflightQueueFull,
|
||||||
InvalidFlagBits,
|
|
||||||
|
// [v3.1.1]
|
||||||
// [v3.1.1]
|
/// <summary>
|
||||||
/// <summary>
|
/// Invalid flag bits received
|
||||||
/// Invalid connect flags received
|
/// </summary>
|
||||||
/// </summary>
|
InvalidFlagBits,
|
||||||
InvalidConnectFlags,
|
|
||||||
|
// [v3.1.1]
|
||||||
// [v3.1.1]
|
/// <summary>
|
||||||
/// <summary>
|
/// Invalid connect flags received
|
||||||
/// Invalid client id
|
/// </summary>
|
||||||
/// </summary>
|
InvalidConnectFlags,
|
||||||
InvalidClientId,
|
|
||||||
|
// [v3.1.1]
|
||||||
// [v3.1.1]
|
/// <summary>
|
||||||
/// <summary>
|
/// Invalid client id
|
||||||
/// Invalid protocol name
|
/// </summary>
|
||||||
/// </summary>
|
InvalidClientId,
|
||||||
InvalidProtocolName
|
|
||||||
}
|
// [v3.1.1]
|
||||||
|
/// <summary>
|
||||||
|
/// Invalid protocol name
|
||||||
|
/// </summary>
|
||||||
|
InvalidProtocolName
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,27 +16,23 @@ Contributors:
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace uPLibrary.Networking.M2Mqtt.Exceptions
|
namespace uPLibrary.Networking.M2Mqtt.Exceptions {
|
||||||
{
|
/// <summary>
|
||||||
|
/// Exception due to error communication with broker on socket
|
||||||
|
/// </summary>
|
||||||
|
public class MqttCommunicationException : Exception {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Exception due to error communication with broker on socket
|
/// Default constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttCommunicationException : Exception
|
public MqttCommunicationException() {
|
||||||
{
|
}
|
||||||
/// <summary>
|
|
||||||
/// Default constructor
|
/// <summary>
|
||||||
/// </summary>
|
/// Constructor
|
||||||
public MqttCommunicationException()
|
/// </summary>
|
||||||
{
|
/// <param name="e">Inner Exception</param>
|
||||||
}
|
public MqttCommunicationException(Exception e)
|
||||||
|
: base(String.Empty, e) {
|
||||||
/// <summary>
|
}
|
||||||
/// Constructor
|
}
|
||||||
/// </summary>
|
|
||||||
/// <param name="e">Inner Exception</param>
|
|
||||||
public MqttCommunicationException(Exception e)
|
|
||||||
: base(String.Empty, e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
{
|
: base(message, innerException) {
|
||||||
public MqttConnectionException(string message, Exception innerException)
|
}
|
||||||
: base(message, innerException)
|
}
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
}
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,55 +15,52 @@ Contributors:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace uPLibrary.Networking.M2Mqtt
|
namespace uPLibrary.Networking.M2Mqtt {
|
||||||
{
|
/// <summary>
|
||||||
|
/// Interface for channel under MQTT library
|
||||||
|
/// </summary>
|
||||||
|
public interface IMqttNetworkChannel {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interface for channel under MQTT library
|
/// Data available on channel
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IMqttNetworkChannel
|
Boolean DataAvailable { get; }
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Data available on channel
|
/// Receive data from the network channel
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool DataAvailable { get; }
|
/// <param name="buffer">Data buffer for receiving data</param>
|
||||||
|
/// <returns>Number of bytes received</returns>
|
||||||
/// <summary>
|
Int32 Receive(Byte[] buffer);
|
||||||
/// Receive data from the network channel
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
/// <param name="buffer">Data buffer for receiving data</param>
|
/// Receive data from the network channel with a specified timeout
|
||||||
/// <returns>Number of bytes received</returns>
|
/// </summary>
|
||||||
int Receive(byte[] buffer);
|
/// <param name="buffer">Data buffer for receiving data</param>
|
||||||
|
/// <param name="timeout">Timeout on receiving (in milliseconds)</param>
|
||||||
/// <summary>
|
/// <returns>Number of bytes received</returns>
|
||||||
/// Receive data from the network channel with a specified timeout
|
Int32 Receive(Byte[] buffer, Int32 timeout);
|
||||||
/// </summary>
|
|
||||||
/// <param name="buffer">Data buffer for receiving data</param>
|
/// <summary>
|
||||||
/// <param name="timeout">Timeout on receiving (in milliseconds)</param>
|
/// Send data on the network channel to the broker
|
||||||
/// <returns>Number of bytes received</returns>
|
/// </summary>
|
||||||
int Receive(byte[] buffer, int timeout);
|
/// <param name="buffer">Data buffer to send</param>
|
||||||
|
/// <returns>Number of byte sent</returns>
|
||||||
/// <summary>
|
Int32 Send(Byte[] buffer);
|
||||||
/// Send data on the network channel to the broker
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
/// <param name="buffer">Data buffer to send</param>
|
/// Close the network channel
|
||||||
/// <returns>Number of byte sent</returns>
|
/// </summary>
|
||||||
int Send(byte[] buffer);
|
void Close();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Close the network channel
|
/// Connect to remote server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Close();
|
void Connect();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Connect to remote server
|
/// Accept client connection
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Connect();
|
void Accept();
|
||||||
|
}
|
||||||
/// <summary>
|
|
||||||
/// Accept client connection
|
|
||||||
/// </summary>
|
|
||||||
void Accept();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
}
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
/// Internal event with a message
|
||||||
|
/// </summary>
|
||||||
|
public class MsgInternalEvent : InternalEvent {
|
||||||
|
#region Properties ...
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Internal event with a message
|
/// Related message
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MsgInternalEvent : InternalEvent
|
public MqttMsgBase Message { get; set; }
|
||||||
{
|
|
||||||
#region Properties ...
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
// related message
|
||||||
/// Related message
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
public MqttMsgBase Message
|
/// Constructor
|
||||||
{
|
/// </summary>
|
||||||
get { return this.msg; }
|
/// <param name="msg">Related message</param>
|
||||||
set { this.msg = value; }
|
public MsgInternalEvent(MqttMsgBase msg) => this.Message = msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
// related message
|
|
||||||
protected MqttMsgBase msg;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="msg">Related message</param>
|
|
||||||
public MsgInternalEvent(MqttMsgBase msg)
|
|
||||||
{
|
|
||||||
this.msg = msg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
/// Internal event for a published message
|
||||||
|
/// </summary>
|
||||||
|
public class MsgPublishedInternalEvent : MsgInternalEvent {
|
||||||
|
#region Properties...
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Internal event for a published message
|
/// Message published (or failed due to retries)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MsgPublishedInternalEvent : MsgInternalEvent
|
public Boolean IsPublished { get; internal set; }
|
||||||
{
|
|
||||||
#region Properties...
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
// published flag
|
||||||
/// Message published (or failed due to retries)
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
public bool IsPublished
|
/// Constructor
|
||||||
{
|
/// </summary>
|
||||||
get { return this.isPublished; }
|
/// <param name="msg">Message published</param>
|
||||||
internal set { this.isPublished = value; }
|
/// <param name="isPublished">Publish flag</param>
|
||||||
}
|
public MsgPublishedInternalEvent(MqttMsgBase msg, Boolean isPublished)
|
||||||
|
: base(msg) => this.IsPublished = isPublished;
|
||||||
#endregion
|
}
|
||||||
|
|
||||||
// published flag
|
|
||||||
bool isPublished;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="msg">Message published</param>
|
|
||||||
/// <param name="isPublished">Publish flag</param>
|
|
||||||
public MsgPublishedInternalEvent(MqttMsgBase msg, bool isPublished)
|
|
||||||
: base(msg)
|
|
||||||
{
|
|
||||||
this.isPublished = isPublished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
24
M2Mqtt/M2Mqtt.csproj
Normal file
24
M2Mqtt/M2Mqtt.csproj
Normal 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>
|
@ -17,259 +17,220 @@ Contributors:
|
|||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace uPLibrary.Networking.M2Mqtt.Messages
|
namespace uPLibrary.Networking.M2Mqtt.Messages {
|
||||||
{
|
/// <summary>
|
||||||
|
/// Base class for all MQTT messages
|
||||||
|
/// </summary>
|
||||||
|
public abstract class MqttMsgBase {
|
||||||
|
#region Constants...
|
||||||
|
|
||||||
|
// mask, offset and size for fixed header fields
|
||||||
|
internal const Byte MSG_TYPE_MASK = 0xF0;
|
||||||
|
internal const Byte MSG_TYPE_OFFSET = 0x04;
|
||||||
|
internal const Byte MSG_TYPE_SIZE = 0x04;
|
||||||
|
internal const Byte MSG_FLAG_BITS_MASK = 0x0F; // [v3.1.1]
|
||||||
|
internal const Byte MSG_FLAG_BITS_OFFSET = 0x00; // [v3.1.1]
|
||||||
|
internal const Byte MSG_FLAG_BITS_SIZE = 0x04; // [v3.1.1]
|
||||||
|
internal const Byte DUP_FLAG_MASK = 0x08;
|
||||||
|
internal const Byte DUP_FLAG_OFFSET = 0x03;
|
||||||
|
internal const Byte DUP_FLAG_SIZE = 0x01;
|
||||||
|
internal const Byte QOS_LEVEL_MASK = 0x06;
|
||||||
|
internal const Byte QOS_LEVEL_OFFSET = 0x01;
|
||||||
|
internal const Byte QOS_LEVEL_SIZE = 0x02;
|
||||||
|
internal const Byte RETAIN_FLAG_MASK = 0x01;
|
||||||
|
internal const Byte RETAIN_FLAG_OFFSET = 0x00;
|
||||||
|
internal const Byte RETAIN_FLAG_SIZE = 0x01;
|
||||||
|
|
||||||
|
// MQTT message types
|
||||||
|
internal const Byte MQTT_MSG_CONNECT_TYPE = 0x01;
|
||||||
|
internal const Byte MQTT_MSG_CONNACK_TYPE = 0x02;
|
||||||
|
internal const Byte MQTT_MSG_PUBLISH_TYPE = 0x03;
|
||||||
|
internal const Byte MQTT_MSG_PUBACK_TYPE = 0x04;
|
||||||
|
internal const Byte MQTT_MSG_PUBREC_TYPE = 0x05;
|
||||||
|
internal const Byte MQTT_MSG_PUBREL_TYPE = 0x06;
|
||||||
|
internal const Byte MQTT_MSG_PUBCOMP_TYPE = 0x07;
|
||||||
|
internal const Byte MQTT_MSG_SUBSCRIBE_TYPE = 0x08;
|
||||||
|
internal const Byte MQTT_MSG_SUBACK_TYPE = 0x09;
|
||||||
|
internal const Byte MQTT_MSG_UNSUBSCRIBE_TYPE = 0x0A;
|
||||||
|
internal const Byte MQTT_MSG_UNSUBACK_TYPE = 0x0B;
|
||||||
|
internal const Byte MQTT_MSG_PINGREQ_TYPE = 0x0C;
|
||||||
|
internal const Byte MQTT_MSG_PINGRESP_TYPE = 0x0D;
|
||||||
|
internal const Byte MQTT_MSG_DISCONNECT_TYPE = 0x0E;
|
||||||
|
|
||||||
|
// [v3.1.1] MQTT flag bits
|
||||||
|
internal const Byte MQTT_MSG_CONNECT_FLAG_BITS = 0x00;
|
||||||
|
internal const Byte MQTT_MSG_CONNACK_FLAG_BITS = 0x00;
|
||||||
|
internal const Byte MQTT_MSG_PUBLISH_FLAG_BITS = 0x00; // just defined as 0x00 but depends on publish props (dup, qos, retain)
|
||||||
|
internal const Byte MQTT_MSG_PUBACK_FLAG_BITS = 0x00;
|
||||||
|
internal const Byte MQTT_MSG_PUBREC_FLAG_BITS = 0x00;
|
||||||
|
internal const Byte MQTT_MSG_PUBREL_FLAG_BITS = 0x02;
|
||||||
|
internal const Byte MQTT_MSG_PUBCOMP_FLAG_BITS = 0x00;
|
||||||
|
internal const Byte MQTT_MSG_SUBSCRIBE_FLAG_BITS = 0x02;
|
||||||
|
internal const Byte MQTT_MSG_SUBACK_FLAG_BITS = 0x00;
|
||||||
|
internal const Byte MQTT_MSG_UNSUBSCRIBE_FLAG_BITS = 0x02;
|
||||||
|
internal const Byte MQTT_MSG_UNSUBACK_FLAG_BITS = 0x00;
|
||||||
|
internal const Byte MQTT_MSG_PINGREQ_FLAG_BITS = 0x00;
|
||||||
|
internal const Byte MQTT_MSG_PINGRESP_FLAG_BITS = 0x00;
|
||||||
|
internal const Byte MQTT_MSG_DISCONNECT_FLAG_BITS = 0x00;
|
||||||
|
|
||||||
|
// QOS levels
|
||||||
|
public const Byte QOS_LEVEL_AT_MOST_ONCE = 0x00;
|
||||||
|
public const Byte QOS_LEVEL_AT_LEAST_ONCE = 0x01;
|
||||||
|
public const Byte QOS_LEVEL_EXACTLY_ONCE = 0x02;
|
||||||
|
|
||||||
|
// SUBSCRIBE QoS level granted failure [v3.1.1]
|
||||||
|
public const Byte QOS_LEVEL_GRANTED_FAILURE = 0x80;
|
||||||
|
|
||||||
|
internal const UInt16 MAX_TOPIC_LENGTH = 65535;
|
||||||
|
internal const UInt16 MIN_TOPIC_LENGTH = 1;
|
||||||
|
internal const Byte MESSAGE_ID_SIZE = 2;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties...
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Base class for all MQTT messages
|
/// Message type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class MqttMsgBase
|
public Byte Type { get; set; }
|
||||||
{
|
|
||||||
#region Constants...
|
/// <summary>
|
||||||
|
/// Duplicate message flag
|
||||||
// mask, offset and size for fixed header fields
|
/// </summary>
|
||||||
internal const byte MSG_TYPE_MASK = 0xF0;
|
public Boolean DupFlag { get; set; }
|
||||||
internal const byte MSG_TYPE_OFFSET = 0x04;
|
|
||||||
internal const byte MSG_TYPE_SIZE = 0x04;
|
/// <summary>
|
||||||
internal const byte MSG_FLAG_BITS_MASK = 0x0F; // [v3.1.1]
|
/// Quality of Service level
|
||||||
internal const byte MSG_FLAG_BITS_OFFSET = 0x00; // [v3.1.1]
|
/// </summary>
|
||||||
internal const byte MSG_FLAG_BITS_SIZE = 0x04; // [v3.1.1]
|
public Byte QosLevel { get; set; }
|
||||||
internal const byte DUP_FLAG_MASK = 0x08;
|
|
||||||
internal const byte DUP_FLAG_OFFSET = 0x03;
|
/// <summary>
|
||||||
internal const byte DUP_FLAG_SIZE = 0x01;
|
/// Retain message flag
|
||||||
internal const byte QOS_LEVEL_MASK = 0x06;
|
/// </summary>
|
||||||
internal const byte QOS_LEVEL_OFFSET = 0x01;
|
public Boolean Retain { get; set; }
|
||||||
internal const byte QOS_LEVEL_SIZE = 0x02;
|
|
||||||
internal const byte RETAIN_FLAG_MASK = 0x01;
|
/// <summary>
|
||||||
internal const byte RETAIN_FLAG_OFFSET = 0x00;
|
/// Message identifier for the message
|
||||||
internal const byte RETAIN_FLAG_SIZE = 0x01;
|
/// </summary>
|
||||||
|
public UInt16 MessageId { get; set; }
|
||||||
// MQTT message types
|
|
||||||
internal const byte MQTT_MSG_CONNECT_TYPE = 0x01;
|
#endregion
|
||||||
internal const byte MQTT_MSG_CONNACK_TYPE = 0x02;
|
|
||||||
internal const byte MQTT_MSG_PUBLISH_TYPE = 0x03;
|
// message type
|
||||||
internal const byte MQTT_MSG_PUBACK_TYPE = 0x04;
|
// duplicate delivery
|
||||||
internal const byte MQTT_MSG_PUBREC_TYPE = 0x05;
|
// quality of service level
|
||||||
internal const byte MQTT_MSG_PUBREL_TYPE = 0x06;
|
// retain flag
|
||||||
internal const byte MQTT_MSG_PUBCOMP_TYPE = 0x07;
|
// message identifier
|
||||||
internal const byte MQTT_MSG_SUBSCRIBE_TYPE = 0x08;
|
|
||||||
internal const byte MQTT_MSG_SUBACK_TYPE = 0x09;
|
/// <summary>
|
||||||
internal const byte MQTT_MSG_UNSUBSCRIBE_TYPE = 0x0A;
|
/// Returns message bytes rapresentation
|
||||||
internal const byte MQTT_MSG_UNSUBACK_TYPE = 0x0B;
|
/// </summary>
|
||||||
internal const byte MQTT_MSG_PINGREQ_TYPE = 0x0C;
|
/// <param name="protocolVersion">Protocol version</param>
|
||||||
internal const byte MQTT_MSG_PINGRESP_TYPE = 0x0D;
|
/// <returns>Bytes rapresentation</returns>
|
||||||
internal const byte MQTT_MSG_DISCONNECT_TYPE = 0x0E;
|
public abstract Byte[] GetBytes(Byte protocolVersion);
|
||||||
|
|
||||||
// [v3.1.1] MQTT flag bits
|
/// <summary>
|
||||||
internal const byte MQTT_MSG_CONNECT_FLAG_BITS = 0x00;
|
/// Encode remaining length and insert it into message buffer
|
||||||
internal const byte MQTT_MSG_CONNACK_FLAG_BITS = 0x00;
|
/// </summary>
|
||||||
internal const byte MQTT_MSG_PUBLISH_FLAG_BITS = 0x00; // just defined as 0x00 but depends on publish props (dup, qos, retain)
|
/// <param name="remainingLength">Remaining length value to encode</param>
|
||||||
internal const byte MQTT_MSG_PUBACK_FLAG_BITS = 0x00;
|
/// <param name="buffer">Message buffer for inserting encoded value</param>
|
||||||
internal const byte MQTT_MSG_PUBREC_FLAG_BITS = 0x00;
|
/// <param name="index">Index from which insert encoded value into buffer</param>
|
||||||
internal const byte MQTT_MSG_PUBREL_FLAG_BITS = 0x02;
|
/// <returns>Index updated</returns>
|
||||||
internal const byte MQTT_MSG_PUBCOMP_FLAG_BITS = 0x00;
|
protected Int32 EncodeRemainingLength(Int32 remainingLength, Byte[] buffer, Int32 index) {
|
||||||
internal const byte MQTT_MSG_SUBSCRIBE_FLAG_BITS = 0x02;
|
do {
|
||||||
internal const byte MQTT_MSG_SUBACK_FLAG_BITS = 0x00;
|
Int32 digit = remainingLength % 128;
|
||||||
internal const byte MQTT_MSG_UNSUBSCRIBE_FLAG_BITS = 0x02;
|
remainingLength /= 128;
|
||||||
internal const byte MQTT_MSG_UNSUBACK_FLAG_BITS = 0x00;
|
if (remainingLength > 0) {
|
||||||
internal const byte MQTT_MSG_PINGREQ_FLAG_BITS = 0x00;
|
digit |= 0x80;
|
||||||
internal const byte MQTT_MSG_PINGRESP_FLAG_BITS = 0x00;
|
}
|
||||||
internal const byte MQTT_MSG_DISCONNECT_FLAG_BITS = 0x00;
|
|
||||||
|
buffer[index++] = (Byte)digit;
|
||||||
// QOS levels
|
} while (remainingLength > 0);
|
||||||
public const byte QOS_LEVEL_AT_MOST_ONCE = 0x00;
|
return index;
|
||||||
public const byte QOS_LEVEL_AT_LEAST_ONCE = 0x01;
|
}
|
||||||
public const byte QOS_LEVEL_EXACTLY_ONCE = 0x02;
|
|
||||||
|
/// <summary>
|
||||||
// SUBSCRIBE QoS level granted failure [v3.1.1]
|
/// Decode remaining length reading bytes from socket
|
||||||
public const byte QOS_LEVEL_GRANTED_FAILURE = 0x80;
|
/// </summary>
|
||||||
|
/// <param name="channel">Channel from reading bytes</param>
|
||||||
internal const ushort MAX_TOPIC_LENGTH = 65535;
|
/// <returns>Decoded remaining length</returns>
|
||||||
internal const ushort MIN_TOPIC_LENGTH = 1;
|
protected static Int32 DecodeRemainingLength(IMqttNetworkChannel channel) {
|
||||||
internal const byte MESSAGE_ID_SIZE = 2;
|
Int32 multiplier = 1;
|
||||||
|
Int32 value = 0;
|
||||||
#endregion
|
Byte[] nextByte = new Byte[1];
|
||||||
|
Int32 digit;
|
||||||
#region Properties...
|
do {
|
||||||
|
// next digit from stream
|
||||||
/// <summary>
|
_ = channel.Receive(nextByte);
|
||||||
/// Message type
|
digit = nextByte[0];
|
||||||
/// </summary>
|
value += (digit & 127) * multiplier;
|
||||||
public byte Type
|
multiplier *= 128;
|
||||||
{
|
} while ((digit & 128) != 0);
|
||||||
get { return this.type; }
|
return value;
|
||||||
set { this.type = value; }
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Duplicate message flag
|
|
||||||
/// </summary>
|
|
||||||
public bool DupFlag
|
|
||||||
{
|
|
||||||
get { return this.dupFlag; }
|
|
||||||
set { this.dupFlag = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Quality of Service level
|
|
||||||
/// </summary>
|
|
||||||
public byte QosLevel
|
|
||||||
{
|
|
||||||
get { return this.qosLevel; }
|
|
||||||
set { this.qosLevel = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retain message flag
|
|
||||||
/// </summary>
|
|
||||||
public bool Retain
|
|
||||||
{
|
|
||||||
get { return this.retain; }
|
|
||||||
set { this.retain = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Message identifier for the message
|
|
||||||
/// </summary>
|
|
||||||
public ushort MessageId
|
|
||||||
{
|
|
||||||
get { return this.messageId; }
|
|
||||||
set { this.messageId = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
// message type
|
|
||||||
protected byte type;
|
|
||||||
// duplicate delivery
|
|
||||||
protected bool dupFlag;
|
|
||||||
// quality of service level
|
|
||||||
protected byte qosLevel;
|
|
||||||
// retain flag
|
|
||||||
protected bool retain;
|
|
||||||
// message identifier
|
|
||||||
protected ushort messageId;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns message bytes rapresentation
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="protocolVersion">Protocol version</param>
|
|
||||||
/// <returns>Bytes rapresentation</returns>
|
|
||||||
public abstract byte[] GetBytes(byte protocolVersion);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Encode remaining length and insert it into message buffer
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="remainingLength">Remaining length value to encode</param>
|
|
||||||
/// <param name="buffer">Message buffer for inserting encoded value</param>
|
|
||||||
/// <param name="index">Index from which insert encoded value into buffer</param>
|
|
||||||
/// <returns>Index updated</returns>
|
|
||||||
protected int encodeRemainingLength(int remainingLength, byte[] buffer, int index)
|
|
||||||
{
|
|
||||||
int digit = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
digit = remainingLength % 128;
|
|
||||||
remainingLength /= 128;
|
|
||||||
if (remainingLength > 0)
|
|
||||||
digit = digit | 0x80;
|
|
||||||
buffer[index++] = (byte)digit;
|
|
||||||
} while (remainingLength > 0);
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Decode remaining length reading bytes from socket
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="channel">Channel from reading bytes</param>
|
|
||||||
/// <returns>Decoded remaining length</returns>
|
|
||||||
protected static int decodeRemainingLength(IMqttNetworkChannel channel)
|
|
||||||
{
|
|
||||||
int multiplier = 1;
|
|
||||||
int value = 0;
|
|
||||||
int digit = 0;
|
|
||||||
byte[] nextByte = new byte[1];
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// next digit from stream
|
|
||||||
channel.Receive(nextByte);
|
|
||||||
digit = nextByte[0];
|
|
||||||
value += ((digit & 127) * multiplier);
|
|
||||||
multiplier *= 128;
|
|
||||||
} while ((digit & 128) != 0);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if TRACE
|
#if TRACE
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a string representation of the message for tracing
|
/// Returns a string representation of the message for tracing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">Message name</param>
|
/// <param name="name">Message name</param>
|
||||||
/// <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("(");
|
||||||
{
|
Boolean addComma = false;
|
||||||
sb.Append("(");
|
for (Int32 i = 0; i < fieldValues.Length; i++) {
|
||||||
bool addComma = false;
|
if (fieldValues[i] != null) {
|
||||||
for (int i = 0; i < fieldValues.Length; i++)
|
if (addComma) {
|
||||||
{
|
_ = sb.Append(",");
|
||||||
if (fieldValues[i] != null)
|
}
|
||||||
{
|
|
||||||
if (addComma)
|
_ = sb.Append(fieldNames[i]);
|
||||||
{
|
_ = sb.Append(":");
|
||||||
sb.Append(",");
|
_ = sb.Append(this.GetStringObject(fieldValues[i]));
|
||||||
}
|
addComma = true;
|
||||||
|
}
|
||||||
sb.Append(fieldNames[i]);
|
}
|
||||||
sb.Append(":");
|
_ = sb.Append(")");
|
||||||
sb.Append(GetStringObject(fieldValues[i]));
|
}
|
||||||
addComma = true;
|
|
||||||
}
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
sb.Append(")");
|
|
||||||
}
|
Object GetStringObject(Object value) {
|
||||||
|
if (value is Byte[] binary) {
|
||||||
return sb.ToString();
|
String hexChars = "0123456789ABCDEF";
|
||||||
}
|
StringBuilder sb = new StringBuilder(binary.Length * 2);
|
||||||
|
for (Int32 i = 0; i < binary.Length; ++i) {
|
||||||
object GetStringObject(object value)
|
_ = sb.Append(hexChars[binary[i] >> 4]);
|
||||||
{
|
_ = sb.Append(hexChars[binary[i] & 0x0F]);
|
||||||
byte[] binary = value as byte[];
|
}
|
||||||
if (binary != null)
|
|
||||||
{
|
return sb.ToString();
|
||||||
string hexChars = "0123456789ABCDEF";
|
}
|
||||||
StringBuilder sb = new StringBuilder(binary.Length * 2);
|
|
||||||
for (int i = 0; i < binary.Length; ++i)
|
if (value is Object[] list) {
|
||||||
{
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.Append(hexChars[binary[i] >> 4]);
|
_ = sb.Append('[');
|
||||||
sb.Append(hexChars[binary[i] & 0x0F]);
|
for (Int32 i = 0; i < list.Length; ++i) {
|
||||||
}
|
if (i > 0) {
|
||||||
|
_ = sb.Append(',');
|
||||||
return sb.ToString();
|
}
|
||||||
}
|
|
||||||
|
_ = sb.Append(list[i]);
|
||||||
object[] list = value as object[];
|
}
|
||||||
if (list != null)
|
_ = sb.Append(']');
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder();
|
return sb.ToString();
|
||||||
sb.Append('[');
|
}
|
||||||
for (int i = 0; i < list.Length; ++i)
|
|
||||||
{
|
return value;
|
||||||
if (i > 0) sb.Append(',');
|
}
|
||||||
sb.Append(list[i]);
|
|
||||||
}
|
|
||||||
sb.Append(']');
|
|
||||||
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,175 +17,153 @@ 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>
|
||||||
|
/// Class for CONNACK message from broker to client
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgConnack : MqttMsgBase {
|
||||||
|
#region Constants...
|
||||||
|
|
||||||
|
// return codes for CONNACK message
|
||||||
|
public const Byte CONN_ACCEPTED = 0x00;
|
||||||
|
public const Byte CONN_REFUSED_PROT_VERS = 0x01;
|
||||||
|
public const Byte CONN_REFUSED_IDENT_REJECTED = 0x02;
|
||||||
|
public const Byte CONN_REFUSED_SERVER_UNAVAILABLE = 0x03;
|
||||||
|
public const Byte CONN_REFUSED_USERNAME_PASSWORD = 0x04;
|
||||||
|
public const Byte CONN_REFUSED_NOT_AUTHORIZED = 0x05;
|
||||||
|
|
||||||
|
//private const Byte TOPIC_NAME_COMP_RESP_BYTE_OFFSET = 0;
|
||||||
|
private const Byte TOPIC_NAME_COMP_RESP_BYTE_SIZE = 1;
|
||||||
|
// [v3.1.1] connect acknowledge flags replace "old" topic name compression respone (not used in 3.1)
|
||||||
|
private const Byte CONN_ACK_FLAGS_BYTE_OFFSET = 0;
|
||||||
|
private const Byte CONN_ACK_FLAGS_BYTE_SIZE = 1;
|
||||||
|
// [v3.1.1] session present flag
|
||||||
|
private const Byte SESSION_PRESENT_FLAG_MASK = 0x01;
|
||||||
|
private const Byte SESSION_PRESENT_FLAG_OFFSET = 0x00;
|
||||||
|
//private const Byte SESSION_PRESENT_FLAG_SIZE = 0x01;
|
||||||
|
private const Byte CONN_RETURN_CODE_BYTE_OFFSET = 1;
|
||||||
|
private const Byte CONN_RETURN_CODE_BYTE_SIZE = 1;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties...
|
||||||
|
|
||||||
|
// [v3.1.1] session present flag
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class for CONNACK message from broker to client
|
/// Session present flag
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgConnack : MqttMsgBase
|
public Boolean SessionPresent { get; set; }
|
||||||
{
|
|
||||||
#region Constants...
|
/// <summary>
|
||||||
|
/// Return Code
|
||||||
// return codes for CONNACK message
|
/// </summary>
|
||||||
public const byte CONN_ACCEPTED = 0x00;
|
public Byte ReturnCode { get; set; }
|
||||||
public const byte CONN_REFUSED_PROT_VERS = 0x01;
|
|
||||||
public const byte CONN_REFUSED_IDENT_REJECTED = 0x02;
|
#endregion
|
||||||
public const byte CONN_REFUSED_SERVER_UNAVAILABLE = 0x03;
|
|
||||||
public const byte CONN_REFUSED_USERNAME_PASSWORD = 0x04;
|
// [v3.1.1] session present flag
|
||||||
public const byte CONN_REFUSED_NOT_AUTHORIZED = 0x05;
|
|
||||||
|
/// <summary>
|
||||||
private const byte TOPIC_NAME_COMP_RESP_BYTE_OFFSET = 0;
|
/// Constructor
|
||||||
private const byte TOPIC_NAME_COMP_RESP_BYTE_SIZE = 1;
|
/// </summary>
|
||||||
// [v3.1.1] connect acknowledge flags replace "old" topic name compression respone (not used in 3.1)
|
public MqttMsgConnack() => this.Type = MQTT_MSG_CONNACK_TYPE;
|
||||||
private const byte CONN_ACK_FLAGS_BYTE_OFFSET = 0;
|
|
||||||
private const byte CONN_ACK_FLAGS_BYTE_SIZE = 1;
|
/// <summary>
|
||||||
// [v3.1.1] session present flag
|
/// Parse bytes for a CONNACK message
|
||||||
private const byte SESSION_PRESENT_FLAG_MASK = 0x01;
|
/// </summary>
|
||||||
private const byte SESSION_PRESENT_FLAG_OFFSET = 0x00;
|
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
||||||
private const byte SESSION_PRESENT_FLAG_SIZE = 0x01;
|
/// <param name="protocolVersion">Protocol Version</param>
|
||||||
private const byte CONN_RETURN_CODE_BYTE_OFFSET = 1;
|
/// <param name="channel">Channel connected to the broker</param>
|
||||||
private const byte CONN_RETURN_CODE_BYTE_SIZE = 1;
|
/// <returns>CONNACK message instance</returns>
|
||||||
|
public static MqttMsgConnack Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
|
||||||
#endregion
|
Byte[] buffer;
|
||||||
|
MqttMsgConnack msg = new MqttMsgConnack();
|
||||||
#region Properties...
|
|
||||||
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
|
||||||
// [v3.1.1] session present flag
|
// [v3.1.1] check flag bits
|
||||||
/// <summary>
|
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_CONNACK_FLAG_BITS) {
|
||||||
/// Session present flag
|
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
||||||
/// </summary>
|
}
|
||||||
public bool SessionPresent
|
}
|
||||||
{
|
|
||||||
get { return this.sessionPresent; }
|
// get remaining length and allocate buffer
|
||||||
set { this.sessionPresent = value; }
|
Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
|
||||||
}
|
buffer = new Byte[remainingLength];
|
||||||
|
|
||||||
/// <summary>
|
// read bytes from socket...
|
||||||
/// Return Code
|
_ = channel.Receive(buffer);
|
||||||
/// </summary>
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
|
||||||
public byte ReturnCode
|
// [v3.1.1] ... set session present flag ...
|
||||||
{
|
msg.SessionPresent = (buffer[CONN_ACK_FLAGS_BYTE_OFFSET] & SESSION_PRESENT_FLAG_MASK) != 0x00;
|
||||||
get { return this.returnCode; }
|
}
|
||||||
set { this.returnCode = value; }
|
// ...and set return code from broker
|
||||||
}
|
msg.ReturnCode = buffer[CONN_RETURN_CODE_BYTE_OFFSET];
|
||||||
|
|
||||||
#endregion
|
return msg;
|
||||||
|
}
|
||||||
// [v3.1.1] session present flag
|
|
||||||
private bool sessionPresent;
|
public override Byte[] GetBytes(Byte ProtocolVersion) {
|
||||||
|
Int32 varHeaderSize = 0;
|
||||||
// return code for CONNACK message
|
Int32 payloadSize = 0;
|
||||||
private byte returnCode;
|
Int32 remainingLength = 0;
|
||||||
|
Byte[] buffer;
|
||||||
/// <summary>
|
Int32 index = 0;
|
||||||
/// Constructor
|
|
||||||
/// </summary>
|
if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
|
||||||
public MqttMsgConnack()
|
// flags byte and connect return code
|
||||||
{
|
varHeaderSize += CONN_ACK_FLAGS_BYTE_SIZE + CONN_RETURN_CODE_BYTE_SIZE;
|
||||||
this.type = MQTT_MSG_CONNACK_TYPE;
|
} else {
|
||||||
}
|
// topic name compression response and connect return code
|
||||||
|
varHeaderSize += TOPIC_NAME_COMP_RESP_BYTE_SIZE + CONN_RETURN_CODE_BYTE_SIZE;
|
||||||
/// <summary>
|
}
|
||||||
/// Parse bytes for a CONNACK message
|
|
||||||
/// </summary>
|
remainingLength += varHeaderSize + payloadSize;
|
||||||
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
|
||||||
/// <param name="protocolVersion">Protocol Version</param>
|
// first byte of fixed header
|
||||||
/// <param name="channel">Channel connected to the broker</param>
|
Int32 fixedHeaderSize = 1;
|
||||||
/// <returns>CONNACK message instance</returns>
|
|
||||||
public static MqttMsgConnack Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
|
Int32 temp = remainingLength;
|
||||||
{
|
// increase fixed header size based on remaining length
|
||||||
byte[] buffer;
|
// (each remaining length byte can encode until 128)
|
||||||
MqttMsgConnack msg = new MqttMsgConnack();
|
do {
|
||||||
|
fixedHeaderSize++;
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
temp /= 128;
|
||||||
{
|
} while (temp > 0);
|
||||||
// [v3.1.1] check flag bits
|
|
||||||
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_CONNACK_FLAG_BITS)
|
// allocate buffer for message
|
||||||
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
||||||
}
|
|
||||||
|
// first fixed header byte
|
||||||
// get remaining length and allocate buffer
|
buffer[index++] = ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
|
||||||
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
|
? (Byte)((MQTT_MSG_CONNACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_CONNACK_FLAG_BITS)
|
||||||
buffer = new byte[remainingLength];
|
: (Byte)(MQTT_MSG_CONNACK_TYPE << MSG_TYPE_OFFSET);
|
||||||
|
|
||||||
// read bytes from socket...
|
// encode remaining length
|
||||||
channel.Receive(buffer);
|
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] ... set session present flag ...
|
// [v3.1.1] session present flag
|
||||||
msg.sessionPresent = (buffer[CONN_ACK_FLAGS_BYTE_OFFSET] & SESSION_PRESENT_FLAG_MASK) != 0x00;
|
buffer[index++] = this.SessionPresent ? (Byte)(1 << SESSION_PRESENT_FLAG_OFFSET) : (Byte)0x00;
|
||||||
}
|
} else {
|
||||||
// ...and set return code from broker
|
// topic name compression response (reserved values. not used);
|
||||||
msg.returnCode = buffer[CONN_RETURN_CODE_BYTE_OFFSET];
|
buffer[index++] = 0x00;
|
||||||
|
}
|
||||||
return msg;
|
|
||||||
}
|
// connect return code
|
||||||
|
buffer[index++] = this.ReturnCode;
|
||||||
public override byte[] GetBytes(byte ProtocolVersion)
|
|
||||||
{
|
return buffer;
|
||||||
int fixedHeaderSize = 0;
|
}
|
||||||
int varHeaderSize = 0;
|
|
||||||
int payloadSize = 0;
|
public override String ToString() =>
|
||||||
int remainingLength = 0;
|
|
||||||
byte[] buffer;
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
|
||||||
// flags byte and connect return code
|
|
||||||
varHeaderSize += (CONN_ACK_FLAGS_BYTE_SIZE + CONN_RETURN_CODE_BYTE_SIZE);
|
|
||||||
else
|
|
||||||
// topic name compression response and connect return code
|
|
||||||
varHeaderSize += (TOPIC_NAME_COMP_RESP_BYTE_SIZE + CONN_RETURN_CODE_BYTE_SIZE);
|
|
||||||
|
|
||||||
remainingLength += (varHeaderSize + payloadSize);
|
|
||||||
|
|
||||||
// first byte of fixed header
|
|
||||||
fixedHeaderSize = 1;
|
|
||||||
|
|
||||||
int temp = remainingLength;
|
|
||||||
// increase fixed header size based on remaining length
|
|
||||||
// (each remaining length byte can encode until 128)
|
|
||||||
do
|
|
||||||
{
|
|
||||||
fixedHeaderSize++;
|
|
||||||
temp = temp / 128;
|
|
||||||
} while (temp > 0);
|
|
||||||
|
|
||||||
// allocate buffer for message
|
|
||||||
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
|
||||||
|
|
||||||
// first fixed header byte
|
|
||||||
if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
|
||||||
buffer[index++] = (MQTT_MSG_CONNACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_CONNACK_FLAG_BITS; // [v.3.1.1]
|
|
||||||
else
|
|
||||||
buffer[index++] = (byte)(MQTT_MSG_CONNACK_TYPE << MSG_TYPE_OFFSET);
|
|
||||||
|
|
||||||
// encode remaining length
|
|
||||||
index = this.encodeRemainingLength(remainingLength, buffer, index);
|
|
||||||
|
|
||||||
if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
|
||||||
// [v3.1.1] session present flag
|
|
||||||
buffer[index++] = this.sessionPresent ? (byte)(1 << SESSION_PRESENT_FLAG_OFFSET) : (byte)0x00;
|
|
||||||
else
|
|
||||||
// topic name compression response (reserved values. not used);
|
|
||||||
buffer[index++] = 0x00;
|
|
||||||
|
|
||||||
// connect return code
|
|
||||||
buffer[index++] = this.returnCode;
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
#if TRACE
|
#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
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -14,31 +14,26 @@ 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>
|
||||||
|
/// Event Args class for CONNECT message received from client
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgConnectEventArgs : EventArgs {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event Args class for CONNECT message received from client
|
/// Message received from client
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgConnectEventArgs : EventArgs
|
public MqttMsgConnect Message { get; private set; }
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Message received from client
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public MqttMsgConnect Message { get; private set; }
|
/// <param name="msg">CONNECT message received from client</param>
|
||||||
|
public MqttMsgConnectEventArgs(MqttMsgConnect connect) => this.Message = connect;
|
||||||
/// <summary>
|
}
|
||||||
/// Constructor
|
}
|
||||||
/// </summary>
|
|
||||||
/// <param name="msg">CONNECT message received from client</param>
|
|
||||||
public MqttMsgConnectEventArgs(MqttMsgConnect connect)
|
|
||||||
{
|
|
||||||
this.Message = connect;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -15,145 +15,137 @@ Contributors:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace uPLibrary.Networking.M2Mqtt.Messages
|
namespace uPLibrary.Networking.M2Mqtt.Messages {
|
||||||
{
|
/// <summary>
|
||||||
|
/// Context for MQTT message
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgContext {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Context for MQTT message
|
/// MQTT message
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgContext
|
public MqttMsgBase Message { get; set; }
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// MQTT message
|
|
||||||
/// </summary>
|
|
||||||
public MqttMsgBase Message { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// MQTT message state
|
|
||||||
/// </summary>
|
|
||||||
public MqttMsgState State { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Flow of the message
|
|
||||||
/// </summary>
|
|
||||||
public MqttMsgFlow Flow { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Timestamp in ticks (for retry)
|
|
||||||
/// </summary>
|
|
||||||
public int Timestamp { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempt (for retry)
|
|
||||||
/// </summary>
|
|
||||||
public int Attempt { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Unique key
|
|
||||||
/// </summary>
|
|
||||||
public string Key
|
|
||||||
{
|
|
||||||
get { return this.Flow + "_" + this.Message.MessageId; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Flow of the message
|
|
||||||
/// </summary>
|
|
||||||
public enum MqttMsgFlow
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// To publish to subscribers
|
|
||||||
/// </summary>
|
|
||||||
ToPublish,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// To acknowledge to publisher
|
|
||||||
/// </summary>
|
|
||||||
ToAcknowledge
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// MQTT message state
|
/// MQTT message state
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum MqttMsgState
|
public MqttMsgState State { get; set; }
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// QOS = 0, Message queued
|
/// Flow of the message
|
||||||
/// </summary>
|
/// </summary>
|
||||||
QueuedQos0,
|
public MqttMsgFlow Flow { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// QOS = 1, Message queued
|
/// Timestamp in ticks (for retry)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
QueuedQos1,
|
public Int32 Timestamp { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// QOS = 2, Message queued
|
/// Attempt (for retry)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
QueuedQos2,
|
public Int32 Attempt { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// QOS = 1, PUBLISH sent, wait for PUBACK
|
/// Unique key
|
||||||
/// </summary>
|
/// </summary>
|
||||||
WaitForPuback,
|
public String Key => this.Flow + "_" + this.Message.MessageId;
|
||||||
|
}
|
||||||
/// <summary>
|
|
||||||
/// QOS = 2, PUBLISH sent, wait for PUBREC
|
/// <summary>
|
||||||
/// </summary>
|
/// Flow of the message
|
||||||
WaitForPubrec,
|
/// </summary>
|
||||||
|
public enum MqttMsgFlow {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// QOS = 2, PUBREC sent, wait for PUBREL
|
/// To publish to subscribers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
WaitForPubrel,
|
ToPublish,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// QOS = 2, PUBREL sent, wait for PUBCOMP
|
/// To acknowledge to publisher
|
||||||
/// </summary>
|
/// </summary>
|
||||||
WaitForPubcomp,
|
ToAcknowledge
|
||||||
|
}
|
||||||
/// <summary>
|
|
||||||
/// QOS = 2, start first phase handshake send PUBREC
|
/// <summary>
|
||||||
/// </summary>
|
/// MQTT message state
|
||||||
SendPubrec,
|
/// </summary>
|
||||||
|
public enum MqttMsgState {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// QOS = 2, start second phase handshake send PUBREL
|
/// QOS = 0, Message queued
|
||||||
/// </summary>
|
/// </summary>
|
||||||
SendPubrel,
|
QueuedQos0,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// QOS = 2, end second phase handshake send PUBCOMP
|
/// QOS = 1, Message queued
|
||||||
/// </summary>
|
/// </summary>
|
||||||
SendPubcomp,
|
QueuedQos1,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// QOS = 1, PUBLISH received, send PUBACK
|
/// QOS = 2, Message queued
|
||||||
/// </summary>
|
/// </summary>
|
||||||
SendPuback,
|
QueuedQos2,
|
||||||
|
|
||||||
// [v3.1.1] SUBSCRIBE isn't "officially" QOS = 1
|
/// <summary>
|
||||||
/// <summary>
|
/// QOS = 1, PUBLISH sent, wait for PUBACK
|
||||||
/// Send SUBSCRIBE message
|
/// </summary>
|
||||||
/// </summary>
|
WaitForPuback,
|
||||||
SendSubscribe,
|
|
||||||
|
/// <summary>
|
||||||
// [v3.1.1] UNSUBSCRIBE isn't "officially" QOS = 1
|
/// QOS = 2, PUBLISH sent, wait for PUBREC
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Send UNSUBSCRIBE message
|
WaitForPubrec,
|
||||||
/// </summary>
|
|
||||||
SendUnsubscribe,
|
/// <summary>
|
||||||
|
/// QOS = 2, PUBREC sent, wait for PUBREL
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// (QOS = 1), SUBSCRIBE sent, wait for SUBACK
|
WaitForPubrel,
|
||||||
/// </summary>
|
|
||||||
WaitForSuback,
|
/// <summary>
|
||||||
|
/// QOS = 2, PUBREL sent, wait for PUBCOMP
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// (QOS = 1), UNSUBSCRIBE sent, wait for UNSUBACK
|
WaitForPubcomp,
|
||||||
/// </summary>
|
|
||||||
WaitForUnsuback
|
/// <summary>
|
||||||
}
|
/// QOS = 2, start first phase handshake send PUBREC
|
||||||
|
/// </summary>
|
||||||
|
SendPubrec,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// QOS = 2, start second phase handshake send PUBREL
|
||||||
|
/// </summary>
|
||||||
|
SendPubrel,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// QOS = 2, end second phase handshake send PUBCOMP
|
||||||
|
/// </summary>
|
||||||
|
SendPubcomp,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// QOS = 1, PUBLISH received, send PUBACK
|
||||||
|
/// </summary>
|
||||||
|
SendPuback,
|
||||||
|
|
||||||
|
// [v3.1.1] SUBSCRIBE isn't "officially" QOS = 1
|
||||||
|
/// <summary>
|
||||||
|
/// Send SUBSCRIBE message
|
||||||
|
/// </summary>
|
||||||
|
SendSubscribe,
|
||||||
|
|
||||||
|
// [v3.1.1] UNSUBSCRIBE isn't "officially" QOS = 1
|
||||||
|
/// <summary>
|
||||||
|
/// Send UNSUBSCRIBE message
|
||||||
|
/// </summary>
|
||||||
|
SendUnsubscribe,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// (QOS = 1), SUBSCRIBE sent, wait for SUBACK
|
||||||
|
/// </summary>
|
||||||
|
WaitForSuback,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// (QOS = 1), UNSUBSCRIBE sent, wait for UNSUBACK
|
||||||
|
/// </summary>
|
||||||
|
WaitForUnsuback
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,73 +14,66 @@ 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>
|
||||||
|
/// Class for DISCONNECT message from client to broker
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgDisconnect : MqttMsgBase {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class for DISCONNECT message from client to broker
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgDisconnect : MqttMsgBase
|
public MqttMsgDisconnect() => this.Type = MQTT_MSG_DISCONNECT_TYPE;
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor
|
/// Parse bytes for a DISCONNECT message
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public MqttMsgDisconnect()
|
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
||||||
{
|
/// <param name="protocolVersion">Protocol Version</param>
|
||||||
this.type = MQTT_MSG_DISCONNECT_TYPE;
|
/// <param name="channel">Channel connected to the broker</param>
|
||||||
}
|
/// <returns>DISCONNECT message instance</returns>
|
||||||
|
public static MqttMsgDisconnect Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
|
||||||
/// <summary>
|
MqttMsgDisconnect msg = new MqttMsgDisconnect();
|
||||||
/// Parse bytes for a DISCONNECT message
|
|
||||||
/// </summary>
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
|
||||||
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
// [v3.1.1] check flag bits
|
||||||
/// <param name="protocolVersion">Protocol Version</param>
|
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_DISCONNECT_FLAG_BITS) {
|
||||||
/// <param name="channel">Channel connected to the broker</param>
|
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
||||||
/// <returns>DISCONNECT message instance</returns>
|
}
|
||||||
public static MqttMsgDisconnect Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
|
}
|
||||||
{
|
|
||||||
MqttMsgDisconnect msg = new MqttMsgDisconnect();
|
// get remaining length and allocate buffer
|
||||||
|
_ = DecodeRemainingLength(channel);
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
// NOTE : remainingLength must be 0
|
||||||
{
|
|
||||||
// [v3.1.1] check flag bits
|
return msg;
|
||||||
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_DISCONNECT_FLAG_BITS)
|
}
|
||||||
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
|
||||||
}
|
public override Byte[] GetBytes(Byte protocolVersion) {
|
||||||
|
Byte[] buffer = new Byte[2];
|
||||||
// get remaining length and allocate buffer
|
Int32 index = 0;
|
||||||
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
|
|
||||||
// NOTE : remainingLength must be 0
|
// first fixed header byte
|
||||||
|
buffer[index++] = protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
|
||||||
return msg;
|
? (Byte)((MQTT_MSG_DISCONNECT_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_DISCONNECT_FLAG_BITS)
|
||||||
}
|
: (Byte)(MQTT_MSG_DISCONNECT_TYPE << MSG_TYPE_OFFSET);
|
||||||
|
|
||||||
public override byte[] GetBytes(byte protocolVersion)
|
buffer[index++] = 0x00;
|
||||||
{
|
|
||||||
byte[] buffer = new byte[2];
|
return buffer;
|
||||||
int index = 0;
|
}
|
||||||
|
|
||||||
// first fixed header byte
|
public override String ToString() =>
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
|
||||||
buffer[index++] = (MQTT_MSG_DISCONNECT_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_DISCONNECT_FLAG_BITS; // [v.3.1.1]
|
|
||||||
else
|
|
||||||
buffer[index++] = (MQTT_MSG_DISCONNECT_TYPE << MSG_TYPE_OFFSET);
|
|
||||||
buffer[index++] = 0x00;
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
#if TRACE
|
#if TRACE
|
||||||
return this.GetTraceString(
|
this.GetTraceString(
|
||||||
"DISCONNECT",
|
"DISCONNECT",
|
||||||
null,
|
null,
|
||||||
null);
|
null);
|
||||||
#else
|
#else
|
||||||
return base.ToString();
|
base.ToString();
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,73 +14,66 @@ 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>
|
||||||
|
/// Class for PINGREQ message from client to broker
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgPingReq : MqttMsgBase {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class for PINGREQ message from client to broker
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgPingReq : MqttMsgBase
|
public MqttMsgPingReq() => this.Type = MQTT_MSG_PINGREQ_TYPE;
|
||||||
{
|
|
||||||
/// <summary>
|
public override Byte[] GetBytes(Byte protocolVersion) {
|
||||||
/// Constructor
|
Byte[] buffer = new Byte[2];
|
||||||
/// </summary>
|
Int32 index = 0;
|
||||||
public MqttMsgPingReq()
|
|
||||||
{
|
// first fixed header byte
|
||||||
this.type = MQTT_MSG_PINGREQ_TYPE;
|
buffer[index++] = protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
|
||||||
}
|
? (Byte)((MQTT_MSG_PINGREQ_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PINGREQ_FLAG_BITS)
|
||||||
|
: (Byte)(MQTT_MSG_PINGREQ_TYPE << MSG_TYPE_OFFSET);
|
||||||
public override byte[] GetBytes(byte protocolVersion)
|
|
||||||
{
|
buffer[index++] = 0x00;
|
||||||
byte[] buffer = new byte[2];
|
|
||||||
int index = 0;
|
return buffer;
|
||||||
|
}
|
||||||
// first fixed header byte
|
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
/// <summary>
|
||||||
buffer[index++] = (MQTT_MSG_PINGREQ_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PINGREQ_FLAG_BITS; // [v.3.1.1]
|
/// Parse bytes for a PINGREQ message
|
||||||
else
|
/// </summary>
|
||||||
buffer[index++] = (MQTT_MSG_PINGREQ_TYPE << MSG_TYPE_OFFSET);
|
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
||||||
buffer[index++] = 0x00;
|
/// <param name="protocolVersion">Protocol Version</param>
|
||||||
|
/// <param name="channel">Channel connected to the broker</param>
|
||||||
return buffer;
|
/// <returns>PINGREQ message instance</returns>
|
||||||
}
|
public static MqttMsgPingReq Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
|
||||||
|
MqttMsgPingReq msg = new MqttMsgPingReq();
|
||||||
/// <summary>
|
|
||||||
/// Parse bytes for a PINGREQ message
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
|
||||||
/// </summary>
|
// [v3.1.1] check flag bits
|
||||||
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGREQ_FLAG_BITS) {
|
||||||
/// <param name="protocolVersion">Protocol Version</param>
|
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
||||||
/// <param name="channel">Channel connected to the broker</param>
|
}
|
||||||
/// <returns>PINGREQ message instance</returns>
|
}
|
||||||
public static MqttMsgPingReq Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
|
|
||||||
{
|
// already know remaininglength is zero (MQTT specification),
|
||||||
MqttMsgPingReq msg = new MqttMsgPingReq();
|
// so it isn't necessary to read other data from socket
|
||||||
|
_ = DecodeRemainingLength(channel);
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
|
||||||
{
|
return msg;
|
||||||
// [v3.1.1] check flag bits
|
}
|
||||||
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGREQ_FLAG_BITS)
|
|
||||||
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
public override String ToString() =>
|
||||||
}
|
|
||||||
|
|
||||||
// already know remaininglength is zero (MQTT specification),
|
|
||||||
// so it isn't necessary to read other data from socket
|
|
||||||
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
|
|
||||||
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
#if TRACE
|
#if TRACE
|
||||||
return this.GetTraceString(
|
this.GetTraceString(
|
||||||
"PINGREQ",
|
"PINGREQ",
|
||||||
null,
|
null,
|
||||||
null);
|
null);
|
||||||
#else
|
#else
|
||||||
return base.ToString();
|
base.ToString();
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,71 +17,63 @@ 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>
|
||||||
|
/// Class for PINGRESP message from client to broker
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgPingResp : MqttMsgBase {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class for PINGRESP message from client to broker
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgPingResp : MqttMsgBase
|
public MqttMsgPingResp() => this.Type = MQTT_MSG_PINGRESP_TYPE;
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor
|
/// Parse bytes for a PINGRESP message
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public MqttMsgPingResp()
|
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
||||||
{
|
/// <param name="protocolVersion">Protocol Version</param>
|
||||||
this.type = MQTT_MSG_PINGRESP_TYPE;
|
/// <param name="channel">Channel connected to the broker</param>
|
||||||
}
|
/// <returns>PINGRESP message instance</returns>
|
||||||
|
public static MqttMsgPingResp Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
|
||||||
/// <summary>
|
MqttMsgPingResp msg = new MqttMsgPingResp();
|
||||||
/// Parse bytes for a PINGRESP message
|
|
||||||
/// </summary>
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
|
||||||
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
// [v3.1.1] check flag bits
|
||||||
/// <param name="protocolVersion">Protocol Version</param>
|
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGRESP_FLAG_BITS) {
|
||||||
/// <param name="channel">Channel connected to the broker</param>
|
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
||||||
/// <returns>PINGRESP message instance</returns>
|
}
|
||||||
public static MqttMsgPingResp Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
|
}
|
||||||
{
|
|
||||||
MqttMsgPingResp msg = new MqttMsgPingResp();
|
// already know remaininglength is zero (MQTT specification),
|
||||||
|
// so it isn't necessary to read other data from socket
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
_ = DecodeRemainingLength(channel);
|
||||||
{
|
|
||||||
// [v3.1.1] check flag bits
|
return msg;
|
||||||
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGRESP_FLAG_BITS)
|
}
|
||||||
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
|
||||||
}
|
public override Byte[] GetBytes(Byte protocolVersion) {
|
||||||
|
Byte[] buffer = new Byte[2];
|
||||||
// already know remaininglength is zero (MQTT specification),
|
Int32 index = 0;
|
||||||
// so it isn't necessary to read other data from socket
|
|
||||||
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
|
// first fixed header byte
|
||||||
|
buffer[index++] = protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
|
||||||
return msg;
|
? (Byte)((MQTT_MSG_PINGRESP_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PINGRESP_FLAG_BITS)
|
||||||
}
|
: (Byte)(MQTT_MSG_PINGRESP_TYPE << MSG_TYPE_OFFSET);
|
||||||
|
|
||||||
public override byte[] GetBytes(byte protocolVersion)
|
buffer[index++] = 0x00;
|
||||||
{
|
|
||||||
byte[] buffer = new byte[2];
|
return buffer;
|
||||||
int index = 0;
|
}
|
||||||
|
|
||||||
// first fixed header byte
|
public override String ToString() =>
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
|
||||||
buffer[index++] = (MQTT_MSG_PINGRESP_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PINGRESP_FLAG_BITS; // [v.3.1.1]
|
|
||||||
else
|
|
||||||
buffer[index++] = (MQTT_MSG_PINGRESP_TYPE << MSG_TYPE_OFFSET);
|
|
||||||
buffer[index++] = 0x00;
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
#if TRACE
|
#if TRACE
|
||||||
return this.GetTraceString(
|
this.GetTraceString(
|
||||||
"PINGRESP",
|
"PINGRESP",
|
||||||
null,
|
null,
|
||||||
null);
|
null);
|
||||||
#else
|
#else
|
||||||
return base.ToString();
|
base.ToString();
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,112 +14,102 @@ 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>
|
||||||
|
/// Class for PUBACK message from broker to client
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgPuback : MqttMsgBase {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class for PUBACK message from broker to client
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgPuback : MqttMsgBase
|
public MqttMsgPuback() => this.Type = MQTT_MSG_PUBACK_TYPE;
|
||||||
{
|
|
||||||
/// <summary>
|
public override Byte[] GetBytes(Byte protocolVersion) {
|
||||||
/// Constructor
|
Int32 varHeaderSize = 0;
|
||||||
/// </summary>
|
Int32 payloadSize = 0;
|
||||||
public MqttMsgPuback()
|
Int32 remainingLength = 0;
|
||||||
{
|
Byte[] buffer;
|
||||||
this.type = MQTT_MSG_PUBACK_TYPE;
|
Int32 index = 0;
|
||||||
}
|
|
||||||
|
// message identifier
|
||||||
public override byte[] GetBytes(byte protocolVersion)
|
varHeaderSize += MESSAGE_ID_SIZE;
|
||||||
{
|
|
||||||
int fixedHeaderSize = 0;
|
remainingLength += varHeaderSize + payloadSize;
|
||||||
int varHeaderSize = 0;
|
|
||||||
int payloadSize = 0;
|
// first byte of fixed header
|
||||||
int remainingLength = 0;
|
Int32 fixedHeaderSize = 1;
|
||||||
byte[] buffer;
|
|
||||||
int index = 0;
|
Int32 temp = remainingLength;
|
||||||
|
// increase fixed header size based on remaining length
|
||||||
// message identifier
|
// (each remaining length byte can encode until 128)
|
||||||
varHeaderSize += MESSAGE_ID_SIZE;
|
do {
|
||||||
|
fixedHeaderSize++;
|
||||||
remainingLength += (varHeaderSize + payloadSize);
|
temp /= 128;
|
||||||
|
} while (temp > 0);
|
||||||
// first byte of fixed header
|
|
||||||
fixedHeaderSize = 1;
|
// allocate buffer for message
|
||||||
|
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
||||||
int temp = remainingLength;
|
|
||||||
// increase fixed header size based on remaining length
|
// first fixed header byte
|
||||||
// (each remaining length byte can encode until 128)
|
buffer[index++] = protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
|
||||||
do
|
? (Byte)((MQTT_MSG_PUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBACK_FLAG_BITS)
|
||||||
{
|
: (Byte)(MQTT_MSG_PUBACK_TYPE << MSG_TYPE_OFFSET);
|
||||||
fixedHeaderSize++;
|
|
||||||
temp = temp / 128;
|
// encode remaining length
|
||||||
} while (temp > 0);
|
index = this.EncodeRemainingLength(remainingLength, buffer, index);
|
||||||
|
|
||||||
// allocate buffer for message
|
// get message identifier
|
||||||
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
|
||||||
|
buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
|
||||||
// first fixed header byte
|
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
return buffer;
|
||||||
buffer[index++] = (MQTT_MSG_PUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBACK_FLAG_BITS; // [v.3.1.1]
|
}
|
||||||
else
|
|
||||||
buffer[index++] = (MQTT_MSG_PUBACK_TYPE << MSG_TYPE_OFFSET);
|
/// <summary>
|
||||||
|
/// Parse bytes for a PUBACK message
|
||||||
// encode remaining length
|
/// </summary>
|
||||||
index = this.encodeRemainingLength(remainingLength, buffer, index);
|
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
||||||
|
/// <param name="protocolVersion">Protocol Version</param>
|
||||||
// get message identifier
|
/// <param name="channel">Channel connected to the broker</param>
|
||||||
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB
|
/// <returns>PUBACK message instance</returns>
|
||||||
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB
|
public static MqttMsgPuback Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
|
||||||
|
Byte[] buffer;
|
||||||
return buffer;
|
Int32 index = 0;
|
||||||
}
|
MqttMsgPuback msg = new MqttMsgPuback();
|
||||||
|
|
||||||
/// <summary>
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
|
||||||
/// Parse bytes for a PUBACK message
|
// [v3.1.1] check flag bits
|
||||||
/// </summary>
|
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBACK_FLAG_BITS) {
|
||||||
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
||||||
/// <param name="protocolVersion">Protocol Version</param>
|
}
|
||||||
/// <param name="channel">Channel connected to the broker</param>
|
}
|
||||||
/// <returns>PUBACK message instance</returns>
|
|
||||||
public static MqttMsgPuback Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
|
// get remaining length and allocate buffer
|
||||||
{
|
Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
|
||||||
byte[] buffer;
|
buffer = new Byte[remainingLength];
|
||||||
int index = 0;
|
|
||||||
MqttMsgPuback msg = new MqttMsgPuback();
|
// read bytes from socket...
|
||||||
|
_ = channel.Receive(buffer);
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
|
||||||
{
|
// message id
|
||||||
// [v3.1.1] check flag bits
|
msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
|
||||||
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBACK_FLAG_BITS)
|
msg.MessageId |= buffer[index++];
|
||||||
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
|
||||||
}
|
return msg;
|
||||||
|
}
|
||||||
// get remaining length and allocate buffer
|
|
||||||
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
|
public override String ToString() =>
|
||||||
buffer = new byte[remainingLength];
|
|
||||||
|
|
||||||
// read bytes from socket...
|
|
||||||
channel.Receive(buffer);
|
|
||||||
|
|
||||||
// message id
|
|
||||||
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
|
|
||||||
msg.messageId |= (buffer[index++]);
|
|
||||||
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
#if TRACE
|
#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
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,112 +14,102 @@ 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>
|
||||||
|
/// Class for PUBCOMP message from broker to client
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgPubcomp : MqttMsgBase {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class for PUBCOMP message from broker to client
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgPubcomp : MqttMsgBase
|
public MqttMsgPubcomp() => this.Type = MQTT_MSG_PUBCOMP_TYPE;
|
||||||
{
|
|
||||||
/// <summary>
|
public override Byte[] GetBytes(Byte protocolVersion) {
|
||||||
/// Constructor
|
Int32 varHeaderSize = 0;
|
||||||
/// </summary>
|
Int32 payloadSize = 0;
|
||||||
public MqttMsgPubcomp()
|
Int32 remainingLength = 0;
|
||||||
{
|
Byte[] buffer;
|
||||||
this.type = MQTT_MSG_PUBCOMP_TYPE;
|
Int32 index = 0;
|
||||||
}
|
|
||||||
|
// message identifier
|
||||||
public override byte[] GetBytes(byte protocolVersion)
|
varHeaderSize += MESSAGE_ID_SIZE;
|
||||||
{
|
|
||||||
int fixedHeaderSize = 0;
|
remainingLength += varHeaderSize + payloadSize;
|
||||||
int varHeaderSize = 0;
|
|
||||||
int payloadSize = 0;
|
// first byte of fixed header
|
||||||
int remainingLength = 0;
|
Int32 fixedHeaderSize = 1;
|
||||||
byte[] buffer;
|
|
||||||
int index = 0;
|
Int32 temp = remainingLength;
|
||||||
|
// increase fixed header size based on remaining length
|
||||||
// message identifier
|
// (each remaining length byte can encode until 128)
|
||||||
varHeaderSize += MESSAGE_ID_SIZE;
|
do {
|
||||||
|
fixedHeaderSize++;
|
||||||
remainingLength += (varHeaderSize + payloadSize);
|
temp /= 128;
|
||||||
|
} while (temp > 0);
|
||||||
// first byte of fixed header
|
|
||||||
fixedHeaderSize = 1;
|
// allocate buffer for message
|
||||||
|
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
||||||
int temp = remainingLength;
|
|
||||||
// increase fixed header size based on remaining length
|
// first fixed header byte
|
||||||
// (each remaining length byte can encode until 128)
|
buffer[index++] = protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
|
||||||
do
|
? (Byte)((MQTT_MSG_PUBCOMP_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBCOMP_FLAG_BITS)
|
||||||
{
|
: (Byte)(MQTT_MSG_PUBCOMP_TYPE << MSG_TYPE_OFFSET);
|
||||||
fixedHeaderSize++;
|
|
||||||
temp = temp / 128;
|
// encode remaining length
|
||||||
} while (temp > 0);
|
index = this.EncodeRemainingLength(remainingLength, buffer, index);
|
||||||
|
|
||||||
// allocate buffer for message
|
// get message identifier
|
||||||
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
|
||||||
|
buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
|
||||||
// first fixed header byte
|
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
return buffer;
|
||||||
buffer[index++] = (MQTT_MSG_PUBCOMP_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBCOMP_FLAG_BITS; // [v.3.1.1]
|
}
|
||||||
else
|
|
||||||
buffer[index++] = (MQTT_MSG_PUBCOMP_TYPE << MSG_TYPE_OFFSET);
|
/// <summary>
|
||||||
|
/// Parse bytes for a PUBCOMP message
|
||||||
// encode remaining length
|
/// </summary>
|
||||||
index = this.encodeRemainingLength(remainingLength, buffer, index);
|
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
||||||
|
/// <param name="protocolVersion">Protocol Version</param>
|
||||||
// get message identifier
|
/// <param name="channel">Channel connected to the broker</param>
|
||||||
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB
|
/// <returns>PUBCOMP message instance</returns>
|
||||||
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB
|
public static MqttMsgPubcomp Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
|
||||||
|
Byte[] buffer;
|
||||||
return buffer;
|
Int32 index = 0;
|
||||||
}
|
MqttMsgPubcomp msg = new MqttMsgPubcomp();
|
||||||
|
|
||||||
/// <summary>
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
|
||||||
/// Parse bytes for a PUBCOMP message
|
// [v3.1.1] check flag bits
|
||||||
/// </summary>
|
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBCOMP_FLAG_BITS) {
|
||||||
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
||||||
/// <param name="protocolVersion">Protocol Version</param>
|
}
|
||||||
/// <param name="channel">Channel connected to the broker</param>
|
}
|
||||||
/// <returns>PUBCOMP message instance</returns>
|
|
||||||
public static MqttMsgPubcomp Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
|
// get remaining length and allocate buffer
|
||||||
{
|
Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
|
||||||
byte[] buffer;
|
buffer = new Byte[remainingLength];
|
||||||
int index = 0;
|
|
||||||
MqttMsgPubcomp msg = new MqttMsgPubcomp();
|
// read bytes from socket...
|
||||||
|
_ = channel.Receive(buffer);
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
|
||||||
{
|
// message id
|
||||||
// [v3.1.1] check flag bits
|
msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
|
||||||
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBCOMP_FLAG_BITS)
|
msg.MessageId |= buffer[index++];
|
||||||
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
|
||||||
}
|
return msg;
|
||||||
|
}
|
||||||
// get remaining length and allocate buffer
|
|
||||||
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
|
public override String ToString() =>
|
||||||
buffer = new byte[remainingLength];
|
|
||||||
|
|
||||||
// read bytes from socket...
|
|
||||||
channel.Receive(buffer);
|
|
||||||
|
|
||||||
// message id
|
|
||||||
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
|
|
||||||
msg.messageId |= (buffer[index++]);
|
|
||||||
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
#if TRACE
|
#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
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,98 +14,66 @@ 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>
|
||||||
|
/// Event Args class for PUBLISH message received from broker
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgPublishEventArgs : EventArgs {
|
||||||
|
#region Properties...
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event Args class for PUBLISH message received from broker
|
/// Message topic
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgPublishEventArgs : EventArgs
|
public String Topic { get; internal set; }
|
||||||
{
|
|
||||||
#region Properties...
|
/// <summary>
|
||||||
|
/// Message data
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Message topic
|
public Byte[] Message { get; internal set; }
|
||||||
/// </summary>
|
|
||||||
public string Topic
|
/// <summary>
|
||||||
{
|
/// Duplicate message flag
|
||||||
get { return this.topic; }
|
/// </summary>
|
||||||
internal set { this.topic = value; }
|
public Boolean DupFlag { get; set; }
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
/// <summary>
|
/// Quality of Service level
|
||||||
/// Message data
|
/// </summary>
|
||||||
/// </summary>
|
public Byte QosLevel { get; internal set; }
|
||||||
public byte[] Message
|
|
||||||
{
|
/// <summary>
|
||||||
get { return this.message; }
|
/// Retain message flag
|
||||||
internal set { this.message = value; }
|
/// </summary>
|
||||||
}
|
public Boolean Retain { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
#endregion
|
||||||
/// Duplicate message flag
|
|
||||||
/// </summary>
|
// message topic
|
||||||
public bool DupFlag
|
|
||||||
{
|
/// <summary>
|
||||||
get { return this.dupFlag; }
|
/// Constructor
|
||||||
set { this.dupFlag = value; }
|
/// </summary>
|
||||||
}
|
/// <param name="topic">Message topic</param>
|
||||||
|
/// <param name="message">Message data</param>
|
||||||
/// <summary>
|
/// <param name="dupFlag">Duplicate delivery flag</param>
|
||||||
/// Quality of Service level
|
/// <param name="qosLevel">Quality of Service level</param>
|
||||||
/// </summary>
|
/// <param name="retain">Retain flag</param>
|
||||||
public byte QosLevel
|
public MqttMsgPublishEventArgs(String topic,
|
||||||
{
|
Byte[] message,
|
||||||
get { return this.qosLevel; }
|
Boolean dupFlag,
|
||||||
internal set { this.qosLevel = value; }
|
Byte qosLevel,
|
||||||
}
|
Boolean retain) {
|
||||||
|
this.Topic = topic;
|
||||||
/// <summary>
|
this.Message = message;
|
||||||
/// Retain message flag
|
this.DupFlag = dupFlag;
|
||||||
/// </summary>
|
this.QosLevel = qosLevel;
|
||||||
public bool Retain
|
this.Retain = retain;
|
||||||
{
|
}
|
||||||
get { return this.retain; }
|
}
|
||||||
internal set { this.retain = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
// message topic
|
|
||||||
private string topic;
|
|
||||||
// message data
|
|
||||||
private byte[] message;
|
|
||||||
// duplicate delivery
|
|
||||||
private bool dupFlag;
|
|
||||||
// quality of service level
|
|
||||||
private byte qosLevel;
|
|
||||||
// retain flag
|
|
||||||
private bool retain;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="topic">Message topic</param>
|
|
||||||
/// <param name="message">Message data</param>
|
|
||||||
/// <param name="dupFlag">Duplicate delivery flag</param>
|
|
||||||
/// <param name="qosLevel">Quality of Service level</param>
|
|
||||||
/// <param name="retain">Retain flag</param>
|
|
||||||
public MqttMsgPublishEventArgs(string topic,
|
|
||||||
byte[] message,
|
|
||||||
bool dupFlag,
|
|
||||||
byte qosLevel,
|
|
||||||
bool retain)
|
|
||||||
{
|
|
||||||
this.topic = topic;
|
|
||||||
this.message = message;
|
|
||||||
this.dupFlag = dupFlag;
|
|
||||||
this.qosLevel = qosLevel;
|
|
||||||
this.retain = retain;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -14,65 +14,49 @@ 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>
|
||||||
|
/// Event Args class for published message
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgPublishedEventArgs : EventArgs {
|
||||||
|
#region Properties...
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event Args class for published message
|
/// Message identifier
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgPublishedEventArgs : EventArgs
|
public UInt16 MessageId { get; internal set; }
|
||||||
{
|
|
||||||
#region Properties...
|
/// <summary>
|
||||||
|
/// Message published (or failed due to retries)
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Message identifier
|
public Boolean IsPublished { get; internal set; }
|
||||||
/// </summary>
|
|
||||||
public ushort MessageId
|
#endregion
|
||||||
{
|
|
||||||
get { return this.messageId; }
|
// message identifier
|
||||||
internal set { this.messageId = value; }
|
|
||||||
}
|
/// <summary>
|
||||||
|
/// Constructor (published message)
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Message published (or failed due to retries)
|
/// <param name="messageId">Message identifier published</param>
|
||||||
/// </summary>
|
public MqttMsgPublishedEventArgs(UInt16 messageId)
|
||||||
public bool IsPublished
|
: this(messageId, true) {
|
||||||
{
|
}
|
||||||
get { return this.isPublished; }
|
|
||||||
internal set { this.isPublished = value; }
|
/// <summary>
|
||||||
}
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
#endregion
|
/// <param name="messageId">Message identifier</param>
|
||||||
|
/// <param name="isPublished">Publish flag</param>
|
||||||
// message identifier
|
public MqttMsgPublishedEventArgs(UInt16 messageId, Boolean isPublished) {
|
||||||
ushort messageId;
|
this.MessageId = messageId;
|
||||||
|
this.IsPublished = isPublished;
|
||||||
// published flag
|
}
|
||||||
bool isPublished;
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor (published message)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageId">Message identifier published</param>
|
|
||||||
public MqttMsgPublishedEventArgs(ushort messageId)
|
|
||||||
: this(messageId, true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageId">Message identifier</param>
|
|
||||||
/// <param name="isPublished">Publish flag</param>
|
|
||||||
public MqttMsgPublishedEventArgs(ushort messageId, bool isPublished)
|
|
||||||
{
|
|
||||||
this.messageId = messageId;
|
|
||||||
this.isPublished = isPublished;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -14,112 +14,102 @@ 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>
|
||||||
|
/// Class for PUBREC message from broker to client
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgPubrec : MqttMsgBase {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class for PUBREC message from broker to client
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgPubrec : MqttMsgBase
|
public MqttMsgPubrec() => this.Type = MQTT_MSG_PUBREC_TYPE;
|
||||||
{
|
|
||||||
/// <summary>
|
public override Byte[] GetBytes(Byte protocolVersion) {
|
||||||
/// Constructor
|
Int32 varHeaderSize = 0;
|
||||||
/// </summary>
|
Int32 payloadSize = 0;
|
||||||
public MqttMsgPubrec()
|
Int32 remainingLength = 0;
|
||||||
{
|
Byte[] buffer;
|
||||||
this.type = MQTT_MSG_PUBREC_TYPE;
|
Int32 index = 0;
|
||||||
}
|
|
||||||
|
// message identifier
|
||||||
public override byte[] GetBytes(byte protocolVersion)
|
varHeaderSize += MESSAGE_ID_SIZE;
|
||||||
{
|
|
||||||
int fixedHeaderSize = 0;
|
remainingLength += varHeaderSize + payloadSize;
|
||||||
int varHeaderSize = 0;
|
|
||||||
int payloadSize = 0;
|
// first byte of fixed header
|
||||||
int remainingLength = 0;
|
Int32 fixedHeaderSize = 1;
|
||||||
byte[] buffer;
|
|
||||||
int index = 0;
|
Int32 temp = remainingLength;
|
||||||
|
// increase fixed header size based on remaining length
|
||||||
// message identifier
|
// (each remaining length byte can encode until 128)
|
||||||
varHeaderSize += MESSAGE_ID_SIZE;
|
do {
|
||||||
|
fixedHeaderSize++;
|
||||||
remainingLength += (varHeaderSize + payloadSize);
|
temp /= 128;
|
||||||
|
} while (temp > 0);
|
||||||
// first byte of fixed header
|
|
||||||
fixedHeaderSize = 1;
|
// allocate buffer for message
|
||||||
|
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
||||||
int temp = remainingLength;
|
|
||||||
// increase fixed header size based on remaining length
|
// first fixed header byte
|
||||||
// (each remaining length byte can encode until 128)
|
buffer[index++] = protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
|
||||||
do
|
? (Byte)((MQTT_MSG_PUBREC_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBREC_FLAG_BITS)
|
||||||
{
|
: (Byte)(MQTT_MSG_PUBREC_TYPE << MSG_TYPE_OFFSET);
|
||||||
fixedHeaderSize++;
|
|
||||||
temp = temp / 128;
|
// encode remaining length
|
||||||
} while (temp > 0);
|
index = this.EncodeRemainingLength(remainingLength, buffer, index);
|
||||||
|
|
||||||
// allocate buffer for message
|
// get message identifier
|
||||||
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
|
||||||
|
buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
|
||||||
// first fixed header byte
|
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
return buffer;
|
||||||
buffer[index++] = (MQTT_MSG_PUBREC_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBREC_FLAG_BITS; // [v.3.1.1]
|
}
|
||||||
else
|
|
||||||
buffer[index++] = (MQTT_MSG_PUBREC_TYPE << MSG_TYPE_OFFSET);
|
/// <summary>
|
||||||
|
/// Parse bytes for a PUBREC message
|
||||||
// encode remaining length
|
/// </summary>
|
||||||
index = this.encodeRemainingLength(remainingLength, buffer, index);
|
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
||||||
|
/// <param name="protocolVersion">Protocol Version</param>
|
||||||
// get message identifier
|
/// <param name="channel">Channel connected to the broker</param>
|
||||||
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB
|
/// <returns>PUBREC message instance</returns>
|
||||||
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB
|
public static MqttMsgPubrec Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
|
||||||
|
Byte[] buffer;
|
||||||
return buffer;
|
Int32 index = 0;
|
||||||
}
|
MqttMsgPubrec msg = new MqttMsgPubrec();
|
||||||
|
|
||||||
/// <summary>
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
|
||||||
/// Parse bytes for a PUBREC message
|
// [v3.1.1] check flag bits
|
||||||
/// </summary>
|
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBREC_FLAG_BITS) {
|
||||||
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
||||||
/// <param name="protocolVersion">Protocol Version</param>
|
}
|
||||||
/// <param name="channel">Channel connected to the broker</param>
|
}
|
||||||
/// <returns>PUBREC message instance</returns>
|
|
||||||
public static MqttMsgPubrec Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
|
// get remaining length and allocate buffer
|
||||||
{
|
Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
|
||||||
byte[] buffer;
|
buffer = new Byte[remainingLength];
|
||||||
int index = 0;
|
|
||||||
MqttMsgPubrec msg = new MqttMsgPubrec();
|
// read bytes from socket...
|
||||||
|
_ = channel.Receive(buffer);
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
|
||||||
{
|
// message id
|
||||||
// [v3.1.1] check flag bits
|
msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
|
||||||
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBREC_FLAG_BITS)
|
msg.MessageId |= buffer[index++];
|
||||||
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
|
||||||
}
|
return msg;
|
||||||
|
}
|
||||||
// get remaining length and allocate buffer
|
|
||||||
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
|
public override String ToString() =>
|
||||||
buffer = new byte[remainingLength];
|
|
||||||
|
|
||||||
// read bytes from socket...
|
|
||||||
channel.Receive(buffer);
|
|
||||||
|
|
||||||
// message id
|
|
||||||
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
|
|
||||||
msg.messageId |= (buffer[index++]);
|
|
||||||
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
#if TRACE
|
#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
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,127 +16,117 @@ Contributors:
|
|||||||
|
|
||||||
using uPLibrary.Networking.M2Mqtt.Exceptions;
|
using uPLibrary.Networking.M2Mqtt.Exceptions;
|
||||||
|
|
||||||
namespace uPLibrary.Networking.M2Mqtt.Messages
|
namespace uPLibrary.Networking.M2Mqtt.Messages {
|
||||||
{
|
/// <summary>
|
||||||
|
/// Class for PUBREL message from client top broker
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgPubrel : MqttMsgBase {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class for PUBREL message from client top broker
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgPubrel : MqttMsgBase
|
public MqttMsgPubrel() {
|
||||||
{
|
this.Type = MQTT_MSG_PUBREL_TYPE;
|
||||||
/// <summary>
|
// PUBREL message use QoS Level 1 (not "officially" in 3.1.1)
|
||||||
/// Constructor
|
this.QosLevel = QOS_LEVEL_AT_LEAST_ONCE;
|
||||||
/// </summary>
|
}
|
||||||
public MqttMsgPubrel()
|
|
||||||
{
|
public override System.Byte[] GetBytes(System.Byte protocolVersion) {
|
||||||
this.type = MQTT_MSG_PUBREL_TYPE;
|
System.Int32 varHeaderSize = 0;
|
||||||
// PUBREL message use QoS Level 1 (not "officially" in 3.1.1)
|
System.Int32 payloadSize = 0;
|
||||||
this.qosLevel = QOS_LEVEL_AT_LEAST_ONCE;
|
System.Int32 remainingLength = 0;
|
||||||
}
|
System.Byte[] buffer;
|
||||||
|
System.Int32 index = 0;
|
||||||
public override byte[] GetBytes(byte protocolVersion)
|
|
||||||
{
|
// message identifier
|
||||||
int fixedHeaderSize = 0;
|
varHeaderSize += MESSAGE_ID_SIZE;
|
||||||
int varHeaderSize = 0;
|
|
||||||
int payloadSize = 0;
|
remainingLength += varHeaderSize + payloadSize;
|
||||||
int remainingLength = 0;
|
|
||||||
byte[] buffer;
|
// first byte of fixed header
|
||||||
int index = 0;
|
System.Int32 fixedHeaderSize = 1;
|
||||||
|
|
||||||
// message identifier
|
System.Int32 temp = remainingLength;
|
||||||
varHeaderSize += MESSAGE_ID_SIZE;
|
// increase fixed header size based on remaining length
|
||||||
|
// (each remaining length byte can encode until 128)
|
||||||
remainingLength += (varHeaderSize + payloadSize);
|
do {
|
||||||
|
fixedHeaderSize++;
|
||||||
// first byte of fixed header
|
temp /= 128;
|
||||||
fixedHeaderSize = 1;
|
} while (temp > 0);
|
||||||
|
|
||||||
int temp = remainingLength;
|
// allocate buffer for message
|
||||||
// increase fixed header size based on remaining length
|
buffer = new System.Byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
||||||
// (each remaining length byte can encode until 128)
|
|
||||||
do
|
// first fixed header byte
|
||||||
{
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
|
||||||
fixedHeaderSize++;
|
buffer[index++] = (MQTT_MSG_PUBREL_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBREL_FLAG_BITS; // [v.3.1.1]
|
||||||
temp = temp / 128;
|
} else {
|
||||||
} while (temp > 0);
|
buffer[index] = (System.Byte)((MQTT_MSG_PUBREL_TYPE << MSG_TYPE_OFFSET) |
|
||||||
|
(this.QosLevel << QOS_LEVEL_OFFSET));
|
||||||
// allocate buffer for message
|
buffer[index] |= this.DupFlag ? (System.Byte)(1 << DUP_FLAG_OFFSET) : (System.Byte)0x00;
|
||||||
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
index++;
|
||||||
|
}
|
||||||
// first fixed header byte
|
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
// encode remaining length
|
||||||
buffer[index++] = (MQTT_MSG_PUBREL_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBREL_FLAG_BITS; // [v.3.1.1]
|
index = this.EncodeRemainingLength(remainingLength, buffer, index);
|
||||||
else
|
|
||||||
{
|
// get next message identifier
|
||||||
buffer[index] = (byte)((MQTT_MSG_PUBREL_TYPE << MSG_TYPE_OFFSET) |
|
buffer[index++] = (System.Byte)((this.MessageId >> 8) & 0x00FF); // MSB
|
||||||
(this.qosLevel << QOS_LEVEL_OFFSET));
|
buffer[index++] = (System.Byte)(this.MessageId & 0x00FF); // LSB
|
||||||
buffer[index] |= this.dupFlag ? (byte)(1 << DUP_FLAG_OFFSET) : (byte)0x00;
|
|
||||||
index++;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// encode remaining length
|
/// <summary>
|
||||||
index = this.encodeRemainingLength(remainingLength, buffer, index);
|
/// Parse bytes for a PUBREL message
|
||||||
|
/// </summary>
|
||||||
// get next message identifier
|
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
||||||
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB
|
/// <param name="protocolVersion">Protocol Version</param>
|
||||||
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB
|
/// <param name="channel">Channel connected to the broker</param>
|
||||||
|
/// <returns>PUBREL message instance</returns>
|
||||||
return buffer;
|
public static MqttMsgPubrel Parse(System.Byte fixedHeaderFirstByte, System.Byte protocolVersion, IMqttNetworkChannel channel) {
|
||||||
}
|
System.Byte[] buffer;
|
||||||
|
System.Int32 index = 0;
|
||||||
/// <summary>
|
MqttMsgPubrel msg = new MqttMsgPubrel();
|
||||||
/// Parse bytes for a PUBREL message
|
|
||||||
/// </summary>
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
|
||||||
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
// [v3.1.1] check flag bits
|
||||||
/// <param name="protocolVersion">Protocol Version</param>
|
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBREL_FLAG_BITS) {
|
||||||
/// <param name="channel">Channel connected to the broker</param>
|
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
||||||
/// <returns>PUBREL message instance</returns>
|
}
|
||||||
public static MqttMsgPubrel Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
|
}
|
||||||
{
|
|
||||||
byte[] buffer;
|
// get remaining length and allocate buffer
|
||||||
int index = 0;
|
System.Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
|
||||||
MqttMsgPubrel msg = new MqttMsgPubrel();
|
buffer = new System.Byte[remainingLength];
|
||||||
|
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
// read bytes from socket...
|
||||||
{
|
_ = channel.Receive(buffer);
|
||||||
// [v3.1.1] check flag bits
|
|
||||||
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBREL_FLAG_BITS)
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1) {
|
||||||
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
// only 3.1.0
|
||||||
}
|
|
||||||
|
// read QoS level from fixed header (would be QoS Level 1)
|
||||||
// get remaining length and allocate buffer
|
msg.QosLevel = (System.Byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
|
||||||
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
|
// read DUP flag from fixed header
|
||||||
buffer = new byte[remainingLength];
|
msg.DupFlag = (fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET == 0x01;
|
||||||
|
}
|
||||||
// read bytes from socket...
|
|
||||||
channel.Receive(buffer);
|
// message id
|
||||||
|
msg.MessageId = (System.UInt16)((buffer[index++] << 8) & 0xFF00);
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1)
|
msg.MessageId |= buffer[index++];
|
||||||
{
|
|
||||||
// only 3.1.0
|
return msg;
|
||||||
|
}
|
||||||
// read QoS level from fixed header (would be QoS Level 1)
|
|
||||||
msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
|
public override System.String ToString() =>
|
||||||
// read DUP flag from fixed header
|
|
||||||
msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
|
|
||||||
}
|
|
||||||
|
|
||||||
// message id
|
|
||||||
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
|
|
||||||
msg.messageId |= (buffer[index++]);
|
|
||||||
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
#if TRACE
|
#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
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,146 +17,127 @@ 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>
|
||||||
|
/// Class for SUBACK message from broker to client
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgSuback : MqttMsgBase {
|
||||||
|
#region Properties...
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class for SUBACK message from broker to client
|
/// List of granted QOS Levels
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgSuback : MqttMsgBase
|
public Byte[] GrantedQoSLevels { get; set; }
|
||||||
{
|
|
||||||
#region Properties...
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
// granted QOS levels
|
||||||
/// List of granted QOS Levels
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
public byte[] GrantedQoSLevels
|
/// Constructor
|
||||||
{
|
/// </summary>
|
||||||
get { return this.grantedQosLevels; }
|
public MqttMsgSuback() => this.Type = MQTT_MSG_SUBACK_TYPE;
|
||||||
set { this.grantedQosLevels = value; }
|
|
||||||
}
|
/// <summary>
|
||||||
|
/// Parse bytes for a SUBACK message
|
||||||
#endregion
|
/// </summary>
|
||||||
|
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
||||||
// granted QOS levels
|
/// <param name="protocolVersion">Protocol Version</param>
|
||||||
byte[] grantedQosLevels;
|
/// <param name="channel">Channel connected to the broker</param>
|
||||||
|
/// <returns>SUBACK message instance</returns>
|
||||||
/// <summary>
|
public static MqttMsgSuback Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
|
||||||
/// Constructor
|
Byte[] buffer;
|
||||||
/// </summary>
|
Int32 index = 0;
|
||||||
public MqttMsgSuback()
|
MqttMsgSuback msg = new MqttMsgSuback();
|
||||||
{
|
|
||||||
this.type = MQTT_MSG_SUBACK_TYPE;
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
|
||||||
}
|
// [v3.1.1] check flag bits
|
||||||
|
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBACK_FLAG_BITS) {
|
||||||
/// <summary>
|
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
||||||
/// Parse bytes for a SUBACK message
|
}
|
||||||
/// </summary>
|
}
|
||||||
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
|
||||||
/// <param name="protocolVersion">Protocol Version</param>
|
// get remaining length and allocate buffer
|
||||||
/// <param name="channel">Channel connected to the broker</param>
|
Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
|
||||||
/// <returns>SUBACK message instance</returns>
|
buffer = new Byte[remainingLength];
|
||||||
public static MqttMsgSuback Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
|
|
||||||
{
|
// read bytes from socket...
|
||||||
byte[] buffer;
|
_ = channel.Receive(buffer);
|
||||||
int index = 0;
|
|
||||||
MqttMsgSuback msg = new MqttMsgSuback();
|
// message id
|
||||||
|
msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
msg.MessageId |= buffer[index++];
|
||||||
{
|
|
||||||
// [v3.1.1] check flag bits
|
// payload contains QoS levels granted
|
||||||
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBACK_FLAG_BITS)
|
msg.GrantedQoSLevels = new Byte[remainingLength - MESSAGE_ID_SIZE];
|
||||||
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
Int32 qosIdx = 0;
|
||||||
}
|
do {
|
||||||
|
msg.GrantedQoSLevels[qosIdx++] = buffer[index++];
|
||||||
// get remaining length and allocate buffer
|
} while (index < remainingLength);
|
||||||
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
|
|
||||||
buffer = new byte[remainingLength];
|
return msg;
|
||||||
|
}
|
||||||
// read bytes from socket...
|
|
||||||
channel.Receive(buffer);
|
public override Byte[] GetBytes(Byte protocolVersion) {
|
||||||
|
Int32 varHeaderSize = 0;
|
||||||
// message id
|
Int32 payloadSize = 0;
|
||||||
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
|
Int32 remainingLength = 0;
|
||||||
msg.messageId |= (buffer[index++]);
|
Byte[] buffer;
|
||||||
|
Int32 index = 0;
|
||||||
// payload contains QoS levels granted
|
|
||||||
msg.grantedQosLevels = new byte[remainingLength - MESSAGE_ID_SIZE];
|
// message identifier
|
||||||
int qosIdx = 0;
|
varHeaderSize += MESSAGE_ID_SIZE;
|
||||||
do
|
|
||||||
{
|
Int32 grantedQosIdx;
|
||||||
msg.grantedQosLevels[qosIdx++] = buffer[index++];
|
for (grantedQosIdx = 0; grantedQosIdx < this.GrantedQoSLevels.Length; grantedQosIdx++) {
|
||||||
} while (index < remainingLength);
|
payloadSize++;
|
||||||
|
}
|
||||||
return msg;
|
|
||||||
}
|
remainingLength += varHeaderSize + payloadSize;
|
||||||
|
|
||||||
public override byte[] GetBytes(byte protocolVersion)
|
// first byte of fixed header
|
||||||
{
|
Int32 fixedHeaderSize = 1;
|
||||||
int fixedHeaderSize = 0;
|
|
||||||
int varHeaderSize = 0;
|
Int32 temp = remainingLength;
|
||||||
int payloadSize = 0;
|
// increase fixed header size based on remaining length
|
||||||
int remainingLength = 0;
|
// (each remaining length byte can encode until 128)
|
||||||
byte[] buffer;
|
do {
|
||||||
int index = 0;
|
fixedHeaderSize++;
|
||||||
|
temp /= 128;
|
||||||
// message identifier
|
} while (temp > 0);
|
||||||
varHeaderSize += MESSAGE_ID_SIZE;
|
|
||||||
|
// allocate buffer for message
|
||||||
int grantedQosIdx = 0;
|
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
||||||
for (grantedQosIdx = 0; grantedQosIdx < this.grantedQosLevels.Length; grantedQosIdx++)
|
|
||||||
{
|
// first fixed header byte
|
||||||
payloadSize++;
|
buffer[index++] = protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
|
||||||
}
|
? (Byte)((MQTT_MSG_SUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_SUBACK_FLAG_BITS)
|
||||||
|
: (Byte)(MQTT_MSG_SUBACK_TYPE << MSG_TYPE_OFFSET);
|
||||||
remainingLength += (varHeaderSize + payloadSize);
|
|
||||||
|
// encode remaining length
|
||||||
// first byte of fixed header
|
index = this.EncodeRemainingLength(remainingLength, buffer, index);
|
||||||
fixedHeaderSize = 1;
|
|
||||||
|
// message id
|
||||||
int temp = remainingLength;
|
buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
|
||||||
// increase fixed header size based on remaining length
|
buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
|
||||||
// (each remaining length byte can encode until 128)
|
|
||||||
do
|
// payload contains QoS levels granted
|
||||||
{
|
for (grantedQosIdx = 0; grantedQosIdx < this.GrantedQoSLevels.Length; grantedQosIdx++) {
|
||||||
fixedHeaderSize++;
|
buffer[index++] = this.GrantedQoSLevels[grantedQosIdx];
|
||||||
temp = temp / 128;
|
}
|
||||||
} while (temp > 0);
|
|
||||||
|
return buffer;
|
||||||
// allocate buffer for message
|
}
|
||||||
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
|
||||||
|
public override String ToString() =>
|
||||||
// first fixed header byte
|
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
|
||||||
buffer[index++] = (MQTT_MSG_SUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_SUBACK_FLAG_BITS; // [v.3.1.1]
|
|
||||||
else
|
|
||||||
buffer[index++] = (byte)(MQTT_MSG_SUBACK_TYPE << MSG_TYPE_OFFSET);
|
|
||||||
|
|
||||||
// encode remaining length
|
|
||||||
index = this.encodeRemainingLength(remainingLength, buffer, index);
|
|
||||||
|
|
||||||
// message id
|
|
||||||
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB
|
|
||||||
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB
|
|
||||||
|
|
||||||
// payload contains QoS levels granted
|
|
||||||
for (grantedQosIdx = 0; grantedQosIdx < this.grantedQosLevels.Length; grantedQosIdx++)
|
|
||||||
{
|
|
||||||
buffer[index++] = this.grantedQosLevels[grantedQosIdx];
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
#if TRACE
|
#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
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,257 +16,234 @@ 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>
|
||||||
|
/// Class for SUBSCRIBE message from client to broker
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgSubscribe : MqttMsgBase {
|
||||||
|
#region Properties...
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class for SUBSCRIBE message from client to broker
|
/// List of topics to subscribe
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgSubscribe : MqttMsgBase
|
public String[] Topics { get; set; }
|
||||||
{
|
|
||||||
#region Properties...
|
/// <summary>
|
||||||
|
/// List of QOS Levels related to topics
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// List of topics to subscribe
|
public Byte[] QoSLevels { get; set; }
|
||||||
/// </summary>
|
|
||||||
public string[] Topics
|
#endregion
|
||||||
{
|
|
||||||
get { return this.topics; }
|
// topics to subscribe
|
||||||
set { this.topics = value; }
|
|
||||||
}
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// List of QOS Levels related to topics
|
public MqttMsgSubscribe() => this.Type = MQTT_MSG_SUBSCRIBE_TYPE;
|
||||||
/// </summary>
|
|
||||||
public byte[] QoSLevels
|
/// <summary>
|
||||||
{
|
/// Constructor
|
||||||
get { return this.qosLevels; }
|
/// </summary>
|
||||||
set { this.qosLevels = value; }
|
/// <param name="topics">List of topics to subscribe</param>
|
||||||
}
|
/// <param name="qosLevels">List of QOS Levels related to topics</param>
|
||||||
|
public MqttMsgSubscribe(String[] topics, Byte[] qosLevels) {
|
||||||
#endregion
|
this.Type = MQTT_MSG_SUBSCRIBE_TYPE;
|
||||||
|
|
||||||
// topics to subscribe
|
this.Topics = topics;
|
||||||
string[] topics;
|
this.QoSLevels = qosLevels;
|
||||||
// QOS levels related to topics
|
|
||||||
byte[] qosLevels;
|
// SUBSCRIBE message uses QoS Level 1 (not "officially" in 3.1.1)
|
||||||
|
this.QosLevel = QOS_LEVEL_AT_LEAST_ONCE;
|
||||||
/// <summary>
|
}
|
||||||
/// Constructor
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
public MqttMsgSubscribe()
|
/// Parse bytes for a SUBSCRIBE message
|
||||||
{
|
/// </summary>
|
||||||
this.type = MQTT_MSG_SUBSCRIBE_TYPE;
|
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
||||||
}
|
/// <param name="protocolVersion">Protocol Version</param>
|
||||||
|
/// <param name="channel">Channel connected to the broker</param>
|
||||||
/// <summary>
|
/// <returns>SUBSCRIBE message instance</returns>
|
||||||
/// Constructor
|
public static MqttMsgSubscribe Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
|
||||||
/// </summary>
|
Byte[] buffer;
|
||||||
/// <param name="topics">List of topics to subscribe</param>
|
Int32 index = 0;
|
||||||
/// <param name="qosLevels">List of QOS Levels related to topics</param>
|
Byte[] topicUtf8;
|
||||||
public MqttMsgSubscribe(string[] topics, byte[] qosLevels)
|
Int32 topicUtf8Length;
|
||||||
{
|
MqttMsgSubscribe msg = new MqttMsgSubscribe();
|
||||||
this.type = MQTT_MSG_SUBSCRIBE_TYPE;
|
|
||||||
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
|
||||||
this.topics = topics;
|
// [v3.1.1] check flag bits
|
||||||
this.qosLevels = qosLevels;
|
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBSCRIBE_FLAG_BITS) {
|
||||||
|
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
||||||
// SUBSCRIBE message uses QoS Level 1 (not "officially" in 3.1.1)
|
}
|
||||||
this.qosLevel = QOS_LEVEL_AT_LEAST_ONCE;
|
}
|
||||||
}
|
|
||||||
|
// get remaining length and allocate buffer
|
||||||
/// <summary>
|
Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
|
||||||
/// Parse bytes for a SUBSCRIBE message
|
buffer = new Byte[remainingLength];
|
||||||
/// </summary>
|
|
||||||
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
// read bytes from socket...
|
||||||
/// <param name="protocolVersion">Protocol Version</param>
|
Int32 received = channel.Receive(buffer);
|
||||||
/// <param name="channel">Channel connected to the broker</param>
|
|
||||||
/// <returns>SUBSCRIBE message instance</returns>
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1) {
|
||||||
public static MqttMsgSubscribe Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
|
// only 3.1.0
|
||||||
{
|
|
||||||
byte[] buffer;
|
// read QoS level from fixed header
|
||||||
int index = 0;
|
msg.QosLevel = (Byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
|
||||||
byte[] topicUtf8;
|
// read DUP flag from fixed header
|
||||||
int topicUtf8Length;
|
msg.DupFlag = (fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET == 0x01;
|
||||||
MqttMsgSubscribe msg = new MqttMsgSubscribe();
|
// retain flag not used
|
||||||
|
msg.Retain = false;
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
}
|
||||||
{
|
|
||||||
// [v3.1.1] check flag bits
|
// message id
|
||||||
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBSCRIBE_FLAG_BITS)
|
msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
|
||||||
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
msg.MessageId |= buffer[index++];
|
||||||
}
|
|
||||||
|
// payload contains topics and QoS levels
|
||||||
// get remaining length and allocate buffer
|
// NOTE : before, I don't know how many topics will be in the payload (so use List)
|
||||||
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
|
|
||||||
buffer = new byte[remainingLength];
|
// if .Net Micro Framework
|
||||||
|
#if MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
|
||||||
// read bytes from socket...
|
|
||||||
int received = channel.Receive(buffer);
|
|
||||||
|
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1)
|
|
||||||
{
|
|
||||||
// only 3.1.0
|
|
||||||
|
|
||||||
// read QoS level from fixed header
|
|
||||||
msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
|
|
||||||
// read DUP flag from fixed header
|
|
||||||
msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
|
|
||||||
// retain flag not used
|
|
||||||
msg.retain = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// message id
|
|
||||||
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
|
|
||||||
msg.messageId |= (buffer[index++]);
|
|
||||||
|
|
||||||
// payload contains topics and QoS levels
|
|
||||||
// NOTE : before, I don't know how many topics will be in the payload (so use List)
|
|
||||||
|
|
||||||
// if .Net Micro Framework
|
|
||||||
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
|
|
||||||
IList tmpTopics = new ArrayList();
|
IList 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)));
|
|
||||||
|
// QoS level
|
||||||
// QoS level
|
tmpQosLevels.Add(buffer[index++]);
|
||||||
tmpQosLevels.Add(buffer[index++]);
|
|
||||||
|
} 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 (Int32 i = 0; i < tmpTopics.Count; i++) {
|
||||||
for (int i = 0; i < tmpTopics.Count; i++)
|
msg.Topics[i] = (String)tmpTopics[i];
|
||||||
{
|
msg.QoSLevels[i] = (Byte)tmpQosLevels[i];
|
||||||
msg.topics[i] = (string)tmpTopics[i];
|
}
|
||||||
msg.qosLevels[i] = (byte)tmpQosLevels[i];
|
|
||||||
}
|
return msg;
|
||||||
|
}
|
||||||
return msg;
|
|
||||||
}
|
public override Byte[] GetBytes(Byte protocolVersion) {
|
||||||
|
Int32 varHeaderSize = 0;
|
||||||
public override byte[] GetBytes(byte protocolVersion)
|
Int32 payloadSize = 0;
|
||||||
{
|
Int32 remainingLength = 0;
|
||||||
int fixedHeaderSize = 0;
|
Byte[] buffer;
|
||||||
int varHeaderSize = 0;
|
Int32 index = 0;
|
||||||
int payloadSize = 0;
|
|
||||||
int remainingLength = 0;
|
// topics list empty
|
||||||
byte[] buffer;
|
if (this.Topics == null || this.Topics.Length == 0) {
|
||||||
int index = 0;
|
throw new MqttClientException(MqttClientErrorCode.TopicsEmpty);
|
||||||
|
}
|
||||||
// topics list empty
|
|
||||||
if ((this.topics == null) || (this.topics.Length == 0))
|
// qos levels list empty
|
||||||
throw new MqttClientException(MqttClientErrorCode.TopicsEmpty);
|
if (this.QoSLevels == null || this.QoSLevels.Length == 0) {
|
||||||
|
throw new MqttClientException(MqttClientErrorCode.QosLevelsEmpty);
|
||||||
// qos levels list empty
|
}
|
||||||
if ((this.qosLevels == null) || (this.qosLevels.Length == 0))
|
|
||||||
throw new MqttClientException(MqttClientErrorCode.QosLevelsEmpty);
|
// topics and qos levels lists length don't match
|
||||||
|
if (this.Topics.Length != this.QoSLevels.Length) {
|
||||||
// topics and qos levels lists length don't match
|
throw new MqttClientException(MqttClientErrorCode.TopicsQosLevelsNotMatch);
|
||||||
if (this.topics.Length != this.qosLevels.Length)
|
}
|
||||||
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][];
|
Int32 topicIdx;
|
||||||
|
for (topicIdx = 0; topicIdx < this.Topics.Length; topicIdx++) {
|
||||||
for (topicIdx = 0; topicIdx < this.topics.Length; topicIdx++)
|
// check topic length
|
||||||
{
|
if (this.Topics[topicIdx].Length < MIN_TOPIC_LENGTH || this.Topics[topicIdx].Length > MAX_TOPIC_LENGTH) {
|
||||||
// check topic length
|
throw new MqttClientException(MqttClientErrorCode.TopicLength);
|
||||||
if ((this.topics[topicIdx].Length < MIN_TOPIC_LENGTH) || (this.topics[topicIdx].Length > MAX_TOPIC_LENGTH))
|
}
|
||||||
throw new MqttClientException(MqttClientErrorCode.TopicLength);
|
|
||||||
|
topicsUtf8[topicIdx] = Encoding.UTF8.GetBytes(this.Topics[topicIdx]);
|
||||||
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
|
Int32 fixedHeaderSize = 1;
|
||||||
fixedHeaderSize = 1;
|
|
||||||
|
Int32 temp = remainingLength;
|
||||||
int 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++;
|
||||||
{
|
temp /= 128;
|
||||||
fixedHeaderSize++;
|
} while (temp > 0);
|
||||||
temp = temp / 128;
|
|
||||||
} while (temp > 0);
|
// allocate buffer for message
|
||||||
|
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
||||||
// allocate buffer for message
|
|
||||||
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
// first fixed header byte
|
||||||
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
|
||||||
// first fixed header byte
|
buffer[index++] = (MQTT_MSG_SUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_SUBSCRIBE_FLAG_BITS; // [v.3.1.1]
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
} else {
|
||||||
buffer[index++] = (MQTT_MSG_SUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_SUBSCRIBE_FLAG_BITS; // [v.3.1.1]
|
buffer[index] = (Byte)((MQTT_MSG_SUBSCRIBE_TYPE << MSG_TYPE_OFFSET) |
|
||||||
else
|
(this.QosLevel << QOS_LEVEL_OFFSET));
|
||||||
{
|
buffer[index] |= this.DupFlag ? (Byte)(1 << DUP_FLAG_OFFSET) : (Byte)0x00;
|
||||||
buffer[index] = (byte)((MQTT_MSG_SUBSCRIBE_TYPE << MSG_TYPE_OFFSET) |
|
index++;
|
||||||
(this.qosLevel << QOS_LEVEL_OFFSET));
|
}
|
||||||
buffer[index] |= this.dupFlag ? (byte)(1 << DUP_FLAG_OFFSET) : (byte)0x00;
|
|
||||||
index++;
|
// encode remaining length
|
||||||
}
|
index = this.EncodeRemainingLength(remainingLength, buffer, index);
|
||||||
|
|
||||||
// encode remaining length
|
// check message identifier assigned (SUBSCRIBE uses QoS Level 1, so message id is mandatory)
|
||||||
index = this.encodeRemainingLength(remainingLength, buffer, index);
|
if (this.MessageId == 0) {
|
||||||
|
throw new MqttClientException(MqttClientErrorCode.WrongMessageId);
|
||||||
// check message identifier assigned (SUBSCRIBE uses QoS Level 1, so message id is mandatory)
|
}
|
||||||
if (this.messageId == 0)
|
|
||||||
throw new MqttClientException(MqttClientErrorCode.WrongMessageId);
|
buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
|
||||||
buffer[index++] = (byte)((messageId >> 8) & 0x00FF); // MSB
|
buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
|
||||||
buffer[index++] = (byte)(messageId & 0x00FF); // LSB
|
|
||||||
|
for (topicIdx = 0; topicIdx < this.Topics.Length; topicIdx++) {
|
||||||
topicIdx = 0;
|
// topic name
|
||||||
for (topicIdx = 0; topicIdx < this.topics.Length; topicIdx++)
|
buffer[index++] = (Byte)((topicsUtf8[topicIdx].Length >> 8) & 0x00FF); // MSB
|
||||||
{
|
buffer[index++] = (Byte)(topicsUtf8[topicIdx].Length & 0x00FF); // LSB
|
||||||
// topic name
|
Array.Copy(topicsUtf8[topicIdx], 0, buffer, index, topicsUtf8[topicIdx].Length);
|
||||||
buffer[index++] = (byte)((topicsUtf8[topicIdx].Length >> 8) & 0x00FF); // MSB
|
index += topicsUtf8[topicIdx].Length;
|
||||||
buffer[index++] = (byte)(topicsUtf8[topicIdx].Length & 0x00FF); // LSB
|
|
||||||
Array.Copy(topicsUtf8[topicIdx], 0, buffer, index, topicsUtf8[topicIdx].Length);
|
// requested QoS
|
||||||
index += topicsUtf8[topicIdx].Length;
|
buffer[index++] = this.QoSLevels[topicIdx];
|
||||||
|
}
|
||||||
// requested QoS
|
|
||||||
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
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,68 +14,48 @@ 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>
|
||||||
|
/// Event Args class for subscribe request on topics
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgSubscribeEventArgs : EventArgs {
|
||||||
|
#region Properties...
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event Args class for subscribe request on topics
|
/// Message identifier
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgSubscribeEventArgs : EventArgs
|
public UInt16 MessageId { get; internal set; }
|
||||||
{
|
|
||||||
#region Properties...
|
/// <summary>
|
||||||
|
/// Topics requested to subscribe
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Message identifier
|
public String[] Topics { get; internal set; }
|
||||||
/// </summary>
|
|
||||||
public ushort MessageId
|
/// <summary>
|
||||||
{
|
/// List of QOS Levels requested
|
||||||
get { return this.messageId; }
|
/// </summary>
|
||||||
internal set { this.messageId = value; }
|
public Byte[] QoSLevels { get; internal set; }
|
||||||
}
|
|
||||||
|
#endregion
|
||||||
/// <summary>
|
|
||||||
/// Topics requested to subscribe
|
// message identifier
|
||||||
/// </summary>
|
|
||||||
public string[] Topics
|
/// <summary>
|
||||||
{
|
/// Constructor
|
||||||
get { return this.topics; }
|
/// </summary>
|
||||||
internal set { this.topics = value; }
|
/// <param name="messageId">Message identifier for subscribe topics request</param>
|
||||||
}
|
/// <param name="topics">Topics requested to subscribe</param>
|
||||||
|
/// <param name="qosLevels">List of QOS Levels requested</param>
|
||||||
/// <summary>
|
public MqttMsgSubscribeEventArgs(UInt16 messageId, String[] topics, Byte[] qosLevels) {
|
||||||
/// List of QOS Levels requested
|
this.MessageId = messageId;
|
||||||
/// </summary>
|
this.Topics = topics;
|
||||||
public byte[] QoSLevels
|
this.QoSLevels = qosLevels;
|
||||||
{
|
}
|
||||||
get { return this.qosLevels; }
|
}
|
||||||
internal set { this.qosLevels = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
// message identifier
|
|
||||||
ushort messageId;
|
|
||||||
// topics requested to subscribe
|
|
||||||
string[] topics;
|
|
||||||
// QoS levels requested
|
|
||||||
byte[] qosLevels;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageId">Message identifier for subscribe topics request</param>
|
|
||||||
/// <param name="topics">Topics requested to subscribe</param>
|
|
||||||
/// <param name="qosLevels">List of QOS Levels requested</param>
|
|
||||||
public MqttMsgSubscribeEventArgs(ushort messageId, string[] topics, byte[] qosLevels)
|
|
||||||
{
|
|
||||||
this.messageId = messageId;
|
|
||||||
this.topics = topics;
|
|
||||||
this.qosLevels = qosLevels;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
/// Event Args class for subscribed topics
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgSubscribedEventArgs : EventArgs {
|
||||||
|
#region Properties...
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event Args class for subscribed topics
|
/// Message identifier
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgSubscribedEventArgs : EventArgs
|
public UInt16 MessageId { get; internal set; }
|
||||||
{
|
|
||||||
#region Properties...
|
/// <summary>
|
||||||
|
/// List of granted QOS Levels
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Message identifier
|
public Byte[] GrantedQoSLevels { get; internal set; }
|
||||||
/// </summary>
|
|
||||||
public ushort MessageId
|
#endregion
|
||||||
{
|
|
||||||
get { return this.messageId; }
|
// message identifier
|
||||||
internal set { this.messageId = value; }
|
|
||||||
}
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// List of granted QOS Levels
|
/// <param name="messageId">Message identifier for subscribed topics</param>
|
||||||
/// </summary>
|
/// <param name="grantedQosLevels">List of granted QOS Levels</param>
|
||||||
public byte[] GrantedQoSLevels
|
public MqttMsgSubscribedEventArgs(UInt16 messageId, Byte[] grantedQosLevels) {
|
||||||
{
|
this.MessageId = messageId;
|
||||||
get { return this.grantedQosLevels; }
|
this.GrantedQoSLevels = grantedQosLevels;
|
||||||
internal set { this.grantedQosLevels = value; }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
// message identifier
|
|
||||||
ushort messageId;
|
|
||||||
// granted QOS levels
|
|
||||||
byte[] grantedQosLevels;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageId">Message identifier for subscribed topics</param>
|
|
||||||
/// <param name="grantedQosLevels">List of granted QOS Levels</param>
|
|
||||||
public MqttMsgSubscribedEventArgs(ushort messageId, byte[] grantedQosLevels)
|
|
||||||
{
|
|
||||||
this.messageId = messageId;
|
|
||||||
this.grantedQosLevels = grantedQosLevels;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,110 +17,99 @@ 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>
|
||||||
|
/// Class for UNSUBACK message from broker to client
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgUnsuback : MqttMsgBase {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class for UNSUBACK message from broker to client
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgUnsuback : MqttMsgBase
|
public MqttMsgUnsuback() => this.Type = MQTT_MSG_UNSUBACK_TYPE;
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor
|
/// Parse bytes for a UNSUBACK message
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public MqttMsgUnsuback()
|
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
||||||
{
|
/// <param name="protocolVersion">Protocol Version</param>
|
||||||
this.type = MQTT_MSG_UNSUBACK_TYPE;
|
/// <param name="channel">Channel connected to the broker</param>
|
||||||
}
|
/// <returns>UNSUBACK message instance</returns>
|
||||||
|
public static MqttMsgUnsuback Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
|
||||||
/// <summary>
|
Byte[] buffer;
|
||||||
/// Parse bytes for a UNSUBACK message
|
Int32 index = 0;
|
||||||
/// </summary>
|
MqttMsgUnsuback msg = new MqttMsgUnsuback();
|
||||||
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
|
||||||
/// <param name="protocolVersion">Protocol Version</param>
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
|
||||||
/// <param name="channel">Channel connected to the broker</param>
|
// [v3.1.1] check flag bits
|
||||||
/// <returns>UNSUBACK message instance</returns>
|
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBACK_FLAG_BITS) {
|
||||||
public static MqttMsgUnsuback Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
|
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
||||||
{
|
}
|
||||||
byte[] buffer;
|
}
|
||||||
int index = 0;
|
|
||||||
MqttMsgUnsuback msg = new MqttMsgUnsuback();
|
// get remaining length and allocate buffer
|
||||||
|
Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
buffer = new Byte[remainingLength];
|
||||||
{
|
|
||||||
// [v3.1.1] check flag bits
|
// read bytes from socket...
|
||||||
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBACK_FLAG_BITS)
|
_ = channel.Receive(buffer);
|
||||||
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
|
||||||
}
|
// message id
|
||||||
|
msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
|
||||||
// get remaining length and allocate buffer
|
msg.MessageId |= buffer[index++];
|
||||||
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
|
|
||||||
buffer = new byte[remainingLength];
|
return msg;
|
||||||
|
}
|
||||||
// read bytes from socket...
|
|
||||||
channel.Receive(buffer);
|
public override Byte[] GetBytes(Byte protocolVersion) {
|
||||||
|
Int32 varHeaderSize = 0;
|
||||||
// message id
|
Int32 payloadSize = 0;
|
||||||
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
|
Int32 remainingLength = 0;
|
||||||
msg.messageId |= (buffer[index++]);
|
Byte[] buffer;
|
||||||
|
Int32 index = 0;
|
||||||
return msg;
|
|
||||||
}
|
// message identifier
|
||||||
|
varHeaderSize += MESSAGE_ID_SIZE;
|
||||||
public override byte[] GetBytes(byte protocolVersion)
|
|
||||||
{
|
remainingLength += varHeaderSize + payloadSize;
|
||||||
int fixedHeaderSize = 0;
|
|
||||||
int varHeaderSize = 0;
|
// first byte of fixed header
|
||||||
int payloadSize = 0;
|
Int32 fixedHeaderSize = 1;
|
||||||
int remainingLength = 0;
|
|
||||||
byte[] buffer;
|
Int32 temp = remainingLength;
|
||||||
int index = 0;
|
// increase fixed header size based on remaining length
|
||||||
|
// (each remaining length byte can encode until 128)
|
||||||
// message identifier
|
do {
|
||||||
varHeaderSize += MESSAGE_ID_SIZE;
|
fixedHeaderSize++;
|
||||||
|
temp /= 128;
|
||||||
remainingLength += (varHeaderSize + payloadSize);
|
} while (temp > 0);
|
||||||
|
|
||||||
// first byte of fixed header
|
// allocate buffer for message
|
||||||
fixedHeaderSize = 1;
|
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
||||||
|
|
||||||
int temp = remainingLength;
|
// first fixed header byte
|
||||||
// increase fixed header size based on remaining length
|
buffer[index++] = protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
|
||||||
// (each remaining length byte can encode until 128)
|
? (Byte)((MQTT_MSG_UNSUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_UNSUBACK_FLAG_BITS)
|
||||||
do
|
: (Byte)(MQTT_MSG_UNSUBACK_TYPE << MSG_TYPE_OFFSET);
|
||||||
{
|
|
||||||
fixedHeaderSize++;
|
// encode remaining length
|
||||||
temp = temp / 128;
|
index = this.EncodeRemainingLength(remainingLength, buffer, index);
|
||||||
} while (temp > 0);
|
|
||||||
|
// message id
|
||||||
// allocate buffer for message
|
buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
|
||||||
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
|
||||||
|
|
||||||
// first fixed header byte
|
return buffer;
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
}
|
||||||
buffer[index++] = (MQTT_MSG_UNSUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_UNSUBACK_FLAG_BITS; // [v.3.1.1]
|
|
||||||
else
|
public override String ToString() =>
|
||||||
buffer[index++] = (byte)(MQTT_MSG_UNSUBACK_TYPE << MSG_TYPE_OFFSET);
|
|
||||||
|
|
||||||
// encode remaining length
|
|
||||||
index = this.encodeRemainingLength(remainingLength, buffer, index);
|
|
||||||
|
|
||||||
// message id
|
|
||||||
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB
|
|
||||||
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
#if TRACE
|
#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
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,224 +16,205 @@ 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>
|
||||||
|
/// Class for UNSUBSCRIBE message from client to broker
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgUnsubscribe : MqttMsgBase {
|
||||||
|
#region Properties...
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class for UNSUBSCRIBE message from client to broker
|
/// List of topics to unsubscribe
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgUnsubscribe : MqttMsgBase
|
public String[] Topics { get; set; }
|
||||||
{
|
|
||||||
#region Properties...
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
// topics to unsubscribe
|
||||||
/// List of topics to unsubscribe
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
public string[] Topics
|
/// Constructor
|
||||||
{
|
/// </summary>
|
||||||
get { return this.topics; }
|
public MqttMsgUnsubscribe() => this.Type = MQTT_MSG_UNSUBSCRIBE_TYPE;
|
||||||
set { this.topics = value; }
|
|
||||||
}
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
#endregion
|
/// </summary>
|
||||||
|
/// <param name="topics">List of topics to unsubscribe</param>
|
||||||
// topics to unsubscribe
|
public MqttMsgUnsubscribe(String[] topics) {
|
||||||
string[] topics;
|
this.Type = MQTT_MSG_UNSUBSCRIBE_TYPE;
|
||||||
|
|
||||||
/// <summary>
|
this.Topics = topics;
|
||||||
/// Constructor
|
|
||||||
/// </summary>
|
// UNSUBSCRIBE message uses QoS Level 1 (not "officially" in 3.1.1)
|
||||||
public MqttMsgUnsubscribe()
|
this.QosLevel = QOS_LEVEL_AT_LEAST_ONCE;
|
||||||
{
|
}
|
||||||
this.type = MQTT_MSG_UNSUBSCRIBE_TYPE;
|
|
||||||
}
|
/// <summary>
|
||||||
|
/// Parse bytes for a UNSUBSCRIBE message
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Constructor
|
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
||||||
/// </summary>
|
/// <param name="protocolVersion">Protocol Version</param>
|
||||||
/// <param name="topics">List of topics to unsubscribe</param>
|
/// <param name="channel">Channel connected to the broker</param>
|
||||||
public MqttMsgUnsubscribe(string[] topics)
|
/// <returns>UNSUBSCRIBE message instance</returns>
|
||||||
{
|
public static MqttMsgUnsubscribe Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
|
||||||
this.type = MQTT_MSG_UNSUBSCRIBE_TYPE;
|
Byte[] buffer;
|
||||||
|
Int32 index = 0;
|
||||||
this.topics = topics;
|
Byte[] topicUtf8;
|
||||||
|
Int32 topicUtf8Length;
|
||||||
// UNSUBSCRIBE message uses QoS Level 1 (not "officially" in 3.1.1)
|
MqttMsgUnsubscribe msg = new MqttMsgUnsubscribe();
|
||||||
this.qosLevel = QOS_LEVEL_AT_LEAST_ONCE;
|
|
||||||
}
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
|
||||||
|
// [v3.1.1] check flag bits
|
||||||
/// <summary>
|
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBSCRIBE_FLAG_BITS) {
|
||||||
/// Parse bytes for a UNSUBSCRIBE message
|
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
||||||
/// </summary>
|
}
|
||||||
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
|
}
|
||||||
/// <param name="protocolVersion">Protocol Version</param>
|
|
||||||
/// <param name="channel">Channel connected to the broker</param>
|
// get remaining length and allocate buffer
|
||||||
/// <returns>UNSUBSCRIBE message instance</returns>
|
Int32 remainingLength = DecodeRemainingLength(channel);
|
||||||
public static MqttMsgUnsubscribe Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
|
buffer = new Byte[remainingLength];
|
||||||
{
|
|
||||||
byte[] buffer;
|
// read bytes from socket...
|
||||||
int index = 0;
|
Int32 received = channel.Receive(buffer);
|
||||||
byte[] topicUtf8;
|
|
||||||
int topicUtf8Length;
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1) {
|
||||||
MqttMsgUnsubscribe msg = new MqttMsgUnsubscribe();
|
// only 3.1.0
|
||||||
|
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
// read QoS level from fixed header
|
||||||
{
|
msg.QosLevel = (Byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
|
||||||
// [v3.1.1] check flag bits
|
// read DUP flag from fixed header
|
||||||
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBSCRIBE_FLAG_BITS)
|
msg.DupFlag = (fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET == 0x01;
|
||||||
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
|
// retain flag not used
|
||||||
}
|
msg.Retain = false;
|
||||||
|
}
|
||||||
// get remaining length and allocate buffer
|
|
||||||
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
|
// message id
|
||||||
buffer = new byte[remainingLength];
|
msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
|
||||||
|
msg.MessageId |= buffer[index++];
|
||||||
// read bytes from socket...
|
|
||||||
int received = channel.Receive(buffer);
|
// payload contains topics
|
||||||
|
// NOTE : before, I don't know how many topics will be in the payload (so use List)
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1)
|
|
||||||
{
|
// if .Net Micro Framework
|
||||||
// only 3.1.0
|
#if MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
|
||||||
|
|
||||||
// read QoS level from fixed header
|
|
||||||
msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
|
|
||||||
// read DUP flag from fixed header
|
|
||||||
msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
|
|
||||||
// retain flag not used
|
|
||||||
msg.retain = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// message id
|
|
||||||
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
|
|
||||||
msg.messageId |= (buffer[index++]);
|
|
||||||
|
|
||||||
// payload contains topics
|
|
||||||
// NOTE : before, I don't know how many topics will be in the payload (so use List)
|
|
||||||
|
|
||||||
// if .Net Micro Framework
|
|
||||||
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
|
|
||||||
IList tmpTopics = new ArrayList();
|
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 (Int32 i = 0; i < tmpTopics.Count; i++) {
|
||||||
for (int 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) {
|
||||||
|
Int32 varHeaderSize = 0;
|
||||||
public override byte[] GetBytes(byte protocolVersion)
|
Int32 payloadSize = 0;
|
||||||
{
|
Int32 remainingLength = 0;
|
||||||
int fixedHeaderSize = 0;
|
Byte[] buffer;
|
||||||
int varHeaderSize = 0;
|
Int32 index = 0;
|
||||||
int payloadSize = 0;
|
|
||||||
int remainingLength = 0;
|
// topics list empty
|
||||||
byte[] buffer;
|
if (this.Topics == null || this.Topics.Length == 0) {
|
||||||
int index = 0;
|
throw new MqttClientException(MqttClientErrorCode.TopicsEmpty);
|
||||||
|
}
|
||||||
// topics list empty
|
|
||||||
if ((this.topics == null) || (this.topics.Length == 0))
|
// message identifier
|
||||||
throw new MqttClientException(MqttClientErrorCode.TopicsEmpty);
|
varHeaderSize += MESSAGE_ID_SIZE;
|
||||||
|
Byte[][] topicsUtf8 = new Byte[this.Topics.Length][];
|
||||||
// message identifier
|
|
||||||
varHeaderSize += MESSAGE_ID_SIZE;
|
|
||||||
|
Int32 topicIdx;
|
||||||
int topicIdx = 0;
|
for (topicIdx = 0; topicIdx < this.Topics.Length; topicIdx++) {
|
||||||
byte[][] topicsUtf8 = new byte[this.topics.Length][];
|
// check topic length
|
||||||
|
if (this.Topics[topicIdx].Length < MIN_TOPIC_LENGTH || this.Topics[topicIdx].Length > MAX_TOPIC_LENGTH) {
|
||||||
for (topicIdx = 0; topicIdx < this.topics.Length; topicIdx++)
|
throw new MqttClientException(MqttClientErrorCode.TopicLength);
|
||||||
{
|
}
|
||||||
// check topic length
|
|
||||||
if ((this.topics[topicIdx].Length < MIN_TOPIC_LENGTH) || (this.topics[topicIdx].Length > MAX_TOPIC_LENGTH))
|
topicsUtf8[topicIdx] = Encoding.UTF8.GetBytes(this.Topics[topicIdx]);
|
||||||
throw new MqttClientException(MqttClientErrorCode.TopicLength);
|
payloadSize += 2; // topic size (MSB, LSB)
|
||||||
|
payloadSize += topicsUtf8[topicIdx].Length;
|
||||||
topicsUtf8[topicIdx] = Encoding.UTF8.GetBytes(this.topics[topicIdx]);
|
}
|
||||||
payloadSize += 2; // topic size (MSB, LSB)
|
|
||||||
payloadSize += topicsUtf8[topicIdx].Length;
|
remainingLength += varHeaderSize + payloadSize;
|
||||||
}
|
|
||||||
|
// first byte of fixed header
|
||||||
remainingLength += (varHeaderSize + payloadSize);
|
Int32 fixedHeaderSize = 1;
|
||||||
|
|
||||||
// first byte of fixed header
|
Int32 temp = remainingLength;
|
||||||
fixedHeaderSize = 1;
|
// increase fixed header size based on remaining length
|
||||||
|
// (each remaining length byte can encode until 128)
|
||||||
int temp = remainingLength;
|
do {
|
||||||
// increase fixed header size based on remaining length
|
fixedHeaderSize++;
|
||||||
// (each remaining length byte can encode until 128)
|
temp /= 128;
|
||||||
do
|
} while (temp > 0);
|
||||||
{
|
|
||||||
fixedHeaderSize++;
|
// allocate buffer for message
|
||||||
temp = temp / 128;
|
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
||||||
} while (temp > 0);
|
|
||||||
|
// first fixed header byte
|
||||||
// allocate buffer for message
|
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
|
||||||
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
|
buffer[index++] = (MQTT_MSG_UNSUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_UNSUBSCRIBE_FLAG_BITS; // [v.3.1.1]
|
||||||
|
} else {
|
||||||
// first fixed header byte
|
buffer[index] = (Byte)((MQTT_MSG_UNSUBSCRIBE_TYPE << MSG_TYPE_OFFSET) |
|
||||||
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
|
(this.QosLevel << QOS_LEVEL_OFFSET));
|
||||||
buffer[index++] = (MQTT_MSG_UNSUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_UNSUBSCRIBE_FLAG_BITS; // [v.3.1.1]
|
buffer[index] |= this.DupFlag ? (Byte)(1 << DUP_FLAG_OFFSET) : (Byte)0x00;
|
||||||
else
|
index++;
|
||||||
{
|
}
|
||||||
buffer[index] = (byte)((MQTT_MSG_UNSUBSCRIBE_TYPE << MSG_TYPE_OFFSET) |
|
|
||||||
(this.qosLevel << QOS_LEVEL_OFFSET));
|
// encode remaining length
|
||||||
buffer[index] |= this.dupFlag ? (byte)(1 << DUP_FLAG_OFFSET) : (byte)0x00;
|
index = this.EncodeRemainingLength(remainingLength, buffer, index);
|
||||||
index++;
|
|
||||||
}
|
// check message identifier assigned
|
||||||
|
if (this.MessageId == 0) {
|
||||||
// encode remaining length
|
throw new MqttClientException(MqttClientErrorCode.WrongMessageId);
|
||||||
index = this.encodeRemainingLength(remainingLength, buffer, index);
|
}
|
||||||
|
|
||||||
// check message identifier assigned
|
buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
|
||||||
if (this.messageId == 0)
|
buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
|
||||||
throw new MqttClientException(MqttClientErrorCode.WrongMessageId);
|
|
||||||
buffer[index++] = (byte)((messageId >> 8) & 0x00FF); // MSB
|
for (topicIdx = 0; topicIdx < this.Topics.Length; topicIdx++) {
|
||||||
buffer[index++] = (byte)(messageId & 0x00FF); // LSB
|
// topic name
|
||||||
|
buffer[index++] = (Byte)((topicsUtf8[topicIdx].Length >> 8) & 0x00FF); // MSB
|
||||||
topicIdx = 0;
|
buffer[index++] = (Byte)(topicsUtf8[topicIdx].Length & 0x00FF); // LSB
|
||||||
for (topicIdx = 0; topicIdx < this.topics.Length; topicIdx++)
|
Array.Copy(topicsUtf8[topicIdx], 0, buffer, index, topicsUtf8[topicIdx].Length);
|
||||||
{
|
index += topicsUtf8[topicIdx].Length;
|
||||||
// topic name
|
}
|
||||||
buffer[index++] = (byte)((topicsUtf8[topicIdx].Length >> 8) & 0x00FF); // MSB
|
|
||||||
buffer[index++] = (byte)(topicsUtf8[topicIdx].Length & 0x00FF); // LSB
|
return buffer;
|
||||||
Array.Copy(topicsUtf8[topicIdx], 0, buffer, index, topicsUtf8[topicIdx].Length);
|
}
|
||||||
index += topicsUtf8[topicIdx].Length;
|
|
||||||
}
|
public override String ToString() =>
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
/// Event Args class for unsubscribe request on topics
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgUnsubscribeEventArgs : EventArgs {
|
||||||
|
#region Properties...
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event Args class for unsubscribe request on topics
|
/// Message identifier
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgUnsubscribeEventArgs : EventArgs
|
public UInt16 MessageId { get; internal set; }
|
||||||
{
|
|
||||||
#region Properties...
|
/// <summary>
|
||||||
|
/// Topics requested to subscribe
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Message identifier
|
public String[] Topics { get; internal set; }
|
||||||
/// </summary>
|
|
||||||
public ushort MessageId
|
#endregion
|
||||||
{
|
|
||||||
get { return this.messageId; }
|
// message identifier
|
||||||
internal set { this.messageId = value; }
|
|
||||||
}
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Topics requested to subscribe
|
/// <param name="messageId">Message identifier for subscribed topics</param>
|
||||||
/// </summary>
|
/// <param name="topics">Topics requested to subscribe</param>
|
||||||
public string[] Topics
|
public MqttMsgUnsubscribeEventArgs(UInt16 messageId, String[] topics) {
|
||||||
{
|
this.MessageId = messageId;
|
||||||
get { return this.topics; }
|
this.Topics = topics;
|
||||||
internal set { this.topics = value; }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
// message identifier
|
|
||||||
ushort messageId;
|
|
||||||
// topics requested to unsubscribe
|
|
||||||
string[] topics;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageId">Message identifier for subscribed topics</param>
|
|
||||||
/// <param name="topics">Topics requested to subscribe</param>
|
|
||||||
public MqttMsgUnsubscribeEventArgs(ushort messageId, string[] topics)
|
|
||||||
{
|
|
||||||
this.messageId = messageId;
|
|
||||||
this.topics = topics;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
/// Event Args class for unsubscribed topic
|
||||||
|
/// </summary>
|
||||||
|
public class MqttMsgUnsubscribedEventArgs : EventArgs {
|
||||||
|
#region Properties...
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event Args class for unsubscribed topic
|
/// Message identifier
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttMsgUnsubscribedEventArgs : EventArgs
|
public UInt16 MessageId { get; internal set; }
|
||||||
{
|
|
||||||
#region Properties...
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
// message identifier
|
||||||
/// Message identifier
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
public ushort MessageId
|
/// Constructor
|
||||||
{
|
/// </summary>
|
||||||
get { return this.messageId; }
|
/// <param name="messageId">Message identifier for unsubscribed topic</param>
|
||||||
internal set { this.messageId = value; }
|
public MqttMsgUnsubscribedEventArgs(UInt16 messageId) => this.MessageId = messageId;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
// message identifier
|
|
||||||
ushort messageId;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageId">Message identifier for unsubscribed topic</param>
|
|
||||||
public MqttMsgUnsubscribedEventArgs(ushort messageId)
|
|
||||||
{
|
|
||||||
this.messageId = messageId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
3642
M2Mqtt/MqttClient.cs
3642
M2Mqtt/MqttClient.cs
File diff suppressed because it is too large
Load Diff
@ -14,17 +14,15 @@ 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,
|
||||||
{
|
SSLv3,
|
||||||
None,
|
TLSv1_0,
|
||||||
SSLv3,
|
TLSv1_1,
|
||||||
TLSv1_0,
|
TLSv1_2
|
||||||
TLSv1_1,
|
}
|
||||||
TLSv1_2
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -14,91 +14,90 @@ 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>
|
||||||
|
/// Settings class for the MQTT broker
|
||||||
|
/// </summary>
|
||||||
|
public class MqttSettings {
|
||||||
|
// default port for MQTT protocol
|
||||||
|
public const Int32 MQTT_BROKER_DEFAULT_PORT = 1883;
|
||||||
|
public const Int32 MQTT_BROKER_DEFAULT_SSL_PORT = 8883;
|
||||||
|
// default timeout on receiving from client
|
||||||
|
public const Int32 MQTT_DEFAULT_TIMEOUT = 30000;
|
||||||
|
// max publish, subscribe and unsubscribe retry for QoS Level 1 or 2
|
||||||
|
public const Int32 MQTT_ATTEMPTS_RETRY = 3;
|
||||||
|
// delay for retry publish, subscribe and unsubscribe for QoS Level 1 or 2
|
||||||
|
public const Int32 MQTT_DELAY_RETRY = 10000;
|
||||||
|
// broker need to receive the first message (CONNECT)
|
||||||
|
// within a reasonable amount of time after TCP/IP connection
|
||||||
|
public const Int32 MQTT_CONNECT_TIMEOUT = 30000;
|
||||||
|
// default inflight queue size
|
||||||
|
public const Int32 MQTT_MAX_INFLIGHT_QUEUE_SIZE = Int32.MaxValue;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Settings class for the MQTT broker
|
/// Listening connection port
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttSettings
|
public Int32 Port { get; internal set; }
|
||||||
{
|
|
||||||
// default port for MQTT protocol
|
/// <summary>
|
||||||
public const int MQTT_BROKER_DEFAULT_PORT = 1883;
|
/// Listening connection SSL port
|
||||||
public const int MQTT_BROKER_DEFAULT_SSL_PORT = 8883;
|
/// </summary>
|
||||||
// default timeout on receiving from client
|
public Int32 SslPort { get; internal set; }
|
||||||
public const int MQTT_DEFAULT_TIMEOUT = 30000;
|
|
||||||
// max publish, subscribe and unsubscribe retry for QoS Level 1 or 2
|
/// <summary>
|
||||||
public const int MQTT_ATTEMPTS_RETRY = 3;
|
/// Timeout on client connection (before receiving CONNECT message)
|
||||||
// delay for retry publish, subscribe and unsubscribe for QoS Level 1 or 2
|
/// </summary>
|
||||||
public const int MQTT_DELAY_RETRY = 10000;
|
public Int32 TimeoutOnConnection { get; internal set; }
|
||||||
// broker need to receive the first message (CONNECT)
|
|
||||||
// within a reasonable amount of time after TCP/IP connection
|
/// <summary>
|
||||||
public const int MQTT_CONNECT_TIMEOUT = 30000;
|
/// Timeout on receiving
|
||||||
// default inflight queue size
|
/// </summary>
|
||||||
public const int MQTT_MAX_INFLIGHT_QUEUE_SIZE = int.MaxValue;
|
public Int32 TimeoutOnReceiving { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Listening connection port
|
/// Attempts on retry
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Port { get; internal set; }
|
public Int32 AttemptsOnRetry { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Listening connection SSL port
|
/// Delay on retry
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int SslPort { get; internal set; }
|
public Int32 DelayOnRetry { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Timeout on client connection (before receiving CONNECT message)
|
/// Inflight queue size
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int TimeoutOnConnection { get; internal set; }
|
public Int32 InflightQueueSize { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Timeout on receiving
|
/// Singleton instance of settings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int TimeoutOnReceiving { get; internal set; }
|
public static MqttSettings Instance {
|
||||||
|
get {
|
||||||
/// <summary>
|
if (instance == null) {
|
||||||
/// Attempts on retry
|
instance = new MqttSettings();
|
||||||
/// </summary>
|
}
|
||||||
public int AttemptsOnRetry { get; internal set; }
|
|
||||||
|
return instance;
|
||||||
/// <summary>
|
}
|
||||||
/// Delay on retry
|
}
|
||||||
/// </summary>
|
|
||||||
public int DelayOnRetry { get; internal set; }
|
// singleton instance
|
||||||
|
private static MqttSettings instance;
|
||||||
/// <summary>
|
|
||||||
/// Inflight queue size
|
/// <summary>
|
||||||
/// </summary>
|
/// Constructor
|
||||||
public int InflightQueueSize { get; set; }
|
/// </summary>
|
||||||
|
private MqttSettings() {
|
||||||
/// <summary>
|
this.Port = MQTT_BROKER_DEFAULT_PORT;
|
||||||
/// Singleton instance of settings
|
this.SslPort = MQTT_BROKER_DEFAULT_SSL_PORT;
|
||||||
/// </summary>
|
this.TimeoutOnReceiving = MQTT_DEFAULT_TIMEOUT;
|
||||||
public static MqttSettings Instance
|
this.AttemptsOnRetry = MQTT_ATTEMPTS_RETRY;
|
||||||
{
|
this.DelayOnRetry = MQTT_DELAY_RETRY;
|
||||||
get
|
this.TimeoutOnConnection = MQTT_CONNECT_TIMEOUT;
|
||||||
{
|
this.InflightQueueSize = MQTT_MAX_INFLIGHT_QUEUE_SIZE;
|
||||||
if (instance == null)
|
}
|
||||||
instance = new MqttSettings();
|
}
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// singleton instance
|
|
||||||
private static MqttSettings instance;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor
|
|
||||||
/// </summary>
|
|
||||||
private MqttSettings()
|
|
||||||
{
|
|
||||||
this.Port = MQTT_BROKER_DEFAULT_PORT;
|
|
||||||
this.SslPort = MQTT_BROKER_DEFAULT_SSL_PORT;
|
|
||||||
this.TimeoutOnReceiving = MQTT_DEFAULT_TIMEOUT;
|
|
||||||
this.AttemptsOnRetry = MQTT_ATTEMPTS_RETRY;
|
|
||||||
this.DelayOnRetry = MQTT_DELAY_RETRY;
|
|
||||||
this.TimeoutOnConnection = MQTT_CONNECT_TIMEOUT;
|
|
||||||
this.InflightQueueSize = MQTT_MAX_INFLIGHT_QUEUE_SIZE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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)
|
public static void SleepThread(Int32 millisecondsTimeout) => Thread.Sleep(millisecondsTimeout);
|
||||||
{
|
}
|
||||||
new Thread(threadStart).Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SleepThread(int millisecondsTimeout)
|
|
||||||
{
|
|
||||||
Thread.Sleep(millisecondsTimeout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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,90 +33,74 @@ 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)
|
||||||
|
private readonly X509Certificate caCert;
|
||||||
|
#endif
|
||||||
|
// Server certificate (on broker)
|
||||||
|
private readonly X509Certificate serverCert;
|
||||||
|
// client certificate (on client)
|
||||||
|
private readonly X509Certificate clientCert;
|
||||||
|
|
||||||
// CA certificate (on client)
|
// SSL/TLS protocol version
|
||||||
private X509Certificate caCert;
|
private readonly MqttSslProtocols sslProtocol;
|
||||||
// Server certificate (on broker)
|
|
||||||
private X509Certificate serverCert;
|
|
||||||
// client certificate (on client)
|
|
||||||
private X509Certificate clientCert;
|
|
||||||
|
|
||||||
// SSL/TLS protocol version
|
/// <summary>
|
||||||
private MqttSslProtocols sslProtocol;
|
/// Remote host name
|
||||||
|
/// </summary>
|
||||||
|
public String RemoteHostName { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Remote host name
|
/// Remote IP address
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string RemoteHostName { get { return this.remoteHostName; } }
|
public IPAddress RemoteIpAddress { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Remote IP address
|
/// Remote port
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IPAddress RemoteIpAddress { get { return this.remoteIpAddress; } }
|
public Int32 RemotePort { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Remote port
|
|
||||||
/// </summary>
|
|
||||||
public int RemotePort { get { return this.remotePort; } }
|
|
||||||
|
|
||||||
#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
|
||||||
|
|
||||||
/// <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
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="socket">Socket opened with the client</param>
|
/// <param name="socket">Socket opened with the client</param>
|
||||||
public MqttNetworkChannel(Socket socket)
|
public MqttNetworkChannel(Socket socket)
|
||||||
#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(socket, false, null, MqttSslProtocols.None, null, null)
|
: this(socket, false, null, MqttSslProtocols.None, null, null)
|
||||||
#else
|
#else
|
||||||
@ -120,212 +108,205 @@ namespace uPLibrary.Networking.M2Mqtt
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="socket">Socket opened with the client</param>
|
/// <param name="socket">Socket opened with the client</param>
|
||||||
/// <param name="secure">Secure connection (SSL/TLS)</param>
|
/// <param name="secure">Secure connection (SSL/TLS)</param>
|
||||||
/// <param name="serverCert">Server X509 certificate for secure connection</param>
|
/// <param name="serverCert">Server X509 certificate for secure connection</param>
|
||||||
/// <param name="sslProtocol">SSL/TLS protocol version</param>
|
/// <param name="sslProtocol">SSL/TLS protocol version</param>
|
||||||
#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
|
||||||
public MqttNetworkChannel(Socket socket, bool secure, X509Certificate serverCert, MqttSslProtocols sslProtocol)
|
public MqttNetworkChannel(Socket socket, bool secure, X509Certificate serverCert, MqttSslProtocols sslProtocol)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
this.secure = secure;
|
this.secure = secure;
|
||||||
this.serverCert = serverCert;
|
this.serverCert = serverCert;
|
||||||
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)
|
||||||
this.userCertificateValidationCallback = userCertificateValidationCallback;
|
this.userCertificateValidationCallback = userCertificateValidationCallback;
|
||||||
this.userCertificateSelectionCallback = userCertificateSelectionCallback;
|
this.userCertificateSelectionCallback = userCertificateSelectionCallback;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// </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
|
||||||
: this(remoteHostName, remotePort, false, null, null, MqttSslProtocols.None)
|
: this(remoteHostName, remotePort, false, null, null, MqttSslProtocols.None)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// </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>
|
||||||
/// <param name="secure">Using SSL</param>
|
/// <param name="secure">Using SSL</param>
|
||||||
/// <param name="caCert">CA certificate</param>
|
/// <param name="caCert">CA certificate</param>
|
||||||
/// <param name="clientCert">Client certificate</param>
|
/// <param name="clientCert">Client certificate</param>
|
||||||
/// <param name="sslProtocol">SSL/TLS protocol version</param>
|
/// <param name="sslProtocol">SSL/TLS protocol version</param>
|
||||||
#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
|
||||||
public MqttNetworkChannel(string remoteHostName, int remotePort, bool secure, X509Certificate caCert, X509Certificate clientCert, MqttSslProtocols sslProtocol)
|
public MqttNetworkChannel(string remoteHostName, int remotePort, bool secure, X509Certificate caCert, X509Certificate clientCert, MqttSslProtocols sslProtocol)
|
||||||
#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
|
||||||
{
|
// it seems that with .Net Micro Framework, the IPV6 addresses aren't supported and return "null"
|
||||||
// check for the first address not null
|
Int32 i = 0;
|
||||||
// it seems that with .Net Micro Framework, the IPV6 addresses aren't supported and return "null"
|
while (hostEntry.AddressList[i] == null) {
|
||||||
int i = 0;
|
i++;
|
||||||
while (hostEntry.AddressList[i] == null) i++;
|
}
|
||||||
remoteIpAddress = hostEntry.AddressList[i];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception("No address found for the remote host name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.remoteHostName = remoteHostName;
|
remoteIpAddress = hostEntry.AddressList[i];
|
||||||
this.remoteIpAddress = remoteIpAddress;
|
} else {
|
||||||
this.remotePort = remotePort;
|
throw new Exception("No address found for the remote host name");
|
||||||
this.secure = secure;
|
|
||||||
this.caCert = caCert;
|
|
||||||
this.clientCert = clientCert;
|
|
||||||
this.sslProtocol = sslProtocol;
|
|
||||||
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
|
|
||||||
this.userCertificateValidationCallback = userCertificateValidationCallback;
|
|
||||||
this.userCertificateSelectionCallback = userCertificateSelectionCallback;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
this.RemoteHostName = remoteHostName;
|
||||||
/// Connect to remote server
|
this.RemoteIpAddress = remoteIpAddress;
|
||||||
/// </summary>
|
this.RemotePort = remotePort;
|
||||||
public void Connect()
|
this.secure = secure;
|
||||||
{
|
#if MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
|
||||||
this.socket = new Socket(IPAddressUtility.GetAddressFamily(this.remoteIpAddress), SocketType.Stream, ProtocolType.Tcp);
|
this.caCert = caCert;
|
||||||
// try connection to the broker
|
#endif
|
||||||
this.socket.Connect(new IPEndPoint(this.remoteIpAddress, this.remotePort));
|
this.clientCert = clientCert;
|
||||||
|
this.sslProtocol = sslProtocol;
|
||||||
|
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
|
||||||
|
this.userCertificateValidationCallback = userCertificateValidationCallback;
|
||||||
|
this.userCertificateSelectionCallback = userCertificateSelectionCallback;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Connect to remote server
|
||||||
|
/// </summary>
|
||||||
|
public void Connect() {
|
||||||
|
this.socket = new Socket(IPAddressUtility.GetAddressFamily(this.RemoteIpAddress), SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
// try connection to the broker
|
||||||
|
this.socket.Connect(new IPEndPoint(this.RemoteIpAddress, this.RemotePort));
|
||||||
|
|
||||||
#if SSL
|
#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);
|
||||||
this.sslStream = new SslStream(this.netStream, false, this.userCertificateValidationCallback, this.userCertificateSelectionCallback);
|
this.sslStream = new SslStream(this.netStream, false, this.userCertificateValidationCallback, this.userCertificateSelectionCallback);
|
||||||
#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 },
|
||||||
SslVerification.CertificateRequired,
|
SslVerification.CertificateRequired,
|
||||||
MqttSslUtility.ToSslPlatformEnum(this.sslProtocol));
|
MqttSslUtility.ToSslPlatformEnum(this.sslProtocol));
|
||||||
#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,
|
|
||||||
clientCertificates,
|
|
||||||
MqttSslUtility.ToSslPlatformEnum(this.sslProtocol),
|
|
||||||
false);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
this.sslStream.AuthenticateAsClient(this.RemoteHostName,
|
||||||
/// Send data on the network channel
|
clientCertificates,
|
||||||
/// </summary>
|
MqttSslUtility.ToSslPlatformEnum(this.sslProtocol),
|
||||||
/// <param name="buffer">Data buffer to send</param>
|
false);
|
||||||
/// <returns>Number of byte sent</returns>
|
|
||||||
public int Send(byte[] buffer)
|
#endif
|
||||||
{
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send data on the network channel
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">Data buffer to send</param>
|
||||||
|
/// <returns>Number of byte sent</returns>
|
||||||
|
public 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 {
|
||||||
}
|
return this.socket.Send(buffer, 0, buffer.Length, SocketFlags.None);
|
||||||
else
|
}
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Receive data from the network
|
/// Receive data from the network
|
||||||
/// </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)
|
Int32 idx = 0, read = 0;
|
||||||
int idx = 0, read = 0;
|
while (idx < buffer.Length) {
|
||||||
while (idx < buffer.Length)
|
// fixed scenario with socket closed gracefully by peer/broker and
|
||||||
{
|
// Read return 0. Avoid infinite loop.
|
||||||
// fixed scenario with socket closed gracefully by peer/broker and
|
read = this.sslStream.Read(buffer, idx, buffer.Length - idx);
|
||||||
// Read return 0. Avoid infinite loop.
|
if (read == 0) {
|
||||||
read = this.sslStream.Read(buffer, idx, buffer.Length - idx);
|
return 0;
|
||||||
if (read == 0)
|
}
|
||||||
return 0;
|
|
||||||
idx += read;
|
idx += read;
|
||||||
}
|
}
|
||||||
return buffer.Length;
|
return buffer.Length;
|
||||||
}
|
} else {
|
||||||
else
|
// read all data needed (until fill buffer)
|
||||||
{
|
Int32 idx = 0, read = 0;
|
||||||
// read all data needed (until fill buffer)
|
while (idx < buffer.Length) {
|
||||||
int idx = 0, read = 0;
|
// fixed scenario with socket closed gracefully by peer/broker and
|
||||||
while (idx < buffer.Length)
|
// Read return 0. Avoid infinite loop.
|
||||||
{
|
read = this.socket.Receive(buffer, idx, buffer.Length - idx, SocketFlags.None);
|
||||||
// fixed scenario with socket closed gracefully by peer/broker and
|
if (read == 0) {
|
||||||
// Read return 0. Avoid infinite loop.
|
return 0;
|
||||||
read = this.socket.Receive(buffer, idx, buffer.Length - idx, SocketFlags.None);
|
}
|
||||||
if (read == 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;
|
int idx = 0, read = 0;
|
||||||
@ -340,118 +321,94 @@ namespace uPLibrary.Networking.M2Mqtt
|
|||||||
}
|
}
|
||||||
return buffer.Length;
|
return buffer.Length;
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Receive data from the network channel with a specified timeout
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="buffer">Data buffer for receiving data</param>
|
|
||||||
/// <param name="timeout">Timeout on receiving (in milliseconds)</param>
|
|
||||||
/// <returns>Number of bytes received</returns>
|
|
||||||
public int Receive(byte[] buffer, int timeout)
|
|
||||||
{
|
|
||||||
// check data availability (timeout is in microseconds)
|
|
||||||
if (this.socket.Poll(timeout * 1000, SelectMode.SelectRead))
|
|
||||||
{
|
|
||||||
return this.Receive(buffer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Close the network channel
|
|
||||||
/// </summary>
|
|
||||||
public void Close()
|
|
||||||
{
|
|
||||||
#if SSL
|
|
||||||
if (this.secure)
|
|
||||||
{
|
|
||||||
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
|
|
||||||
this.netStream.Close();
|
|
||||||
#endif
|
|
||||||
this.sslStream.Close();
|
|
||||||
}
|
|
||||||
this.socket.Close();
|
|
||||||
#else
|
|
||||||
this.socket.Close();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Accept connection from a remote client
|
|
||||||
/// </summary>
|
|
||||||
public void Accept()
|
|
||||||
{
|
|
||||||
#if SSL
|
|
||||||
// secure channel requested
|
|
||||||
if (secure)
|
|
||||||
{
|
|
||||||
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
|
|
||||||
|
|
||||||
this.netStream = new NetworkStream(this.socket);
|
|
||||||
this.sslStream = new SslStream(this.netStream, false, this.userCertificateValidationCallback, this.userCertificateSelectionCallback);
|
|
||||||
|
|
||||||
this.sslStream.AuthenticateAsServer(this.serverCert, false, MqttSslUtility.ToSslPlatformEnum(this.sslProtocol), false);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
#else
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// IPAddress Utility class
|
/// Receive data from the network channel with a specified timeout
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class IPAddressUtility
|
/// <param name="buffer">Data buffer for receiving data</param>
|
||||||
{
|
/// <param name="timeout">Timeout on receiving (in milliseconds)</param>
|
||||||
/// <summary>
|
/// <returns>Number of bytes received</returns>
|
||||||
/// Return AddressFamily for the IP address
|
public Int32 Receive(Byte[] buffer, Int32 timeout) =>
|
||||||
/// </summary>
|
// check data availability (timeout is in microseconds)
|
||||||
/// <param name="ipAddress">IP address to check</param>
|
this.socket.Poll(timeout * 1000, SelectMode.SelectRead) ? this.Receive(buffer) : 0;
|
||||||
/// <returns>Address family</returns>
|
|
||||||
public static AddressFamily GetAddressFamily(IPAddress ipAddress)
|
/// <summary>
|
||||||
{
|
/// Close the network channel
|
||||||
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
|
/// </summary>
|
||||||
return ipAddress.AddressFamily;
|
public void Close() {
|
||||||
|
#if SSL
|
||||||
|
if (this.secure) {
|
||||||
|
#if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
|
||||||
|
this.netStream.Close();
|
||||||
|
#endif
|
||||||
|
this.sslStream.Close();
|
||||||
|
}
|
||||||
|
this.socket.Close();
|
||||||
|
#else
|
||||||
|
this.socket.Close();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Accept connection from a remote client
|
||||||
|
/// </summary>
|
||||||
|
public void Accept() {
|
||||||
|
#if SSL
|
||||||
|
// secure channel requested
|
||||||
|
if (this.secure) {
|
||||||
|
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
|
||||||
|
|
||||||
|
this.netStream = new NetworkStream(this.socket);
|
||||||
|
this.sslStream = new SslStream(this.netStream, false, this.userCertificateValidationCallback, this.userCertificateSelectionCallback);
|
||||||
|
|
||||||
|
this.sslStream.AuthenticateAsServer(this.serverCert, false, MqttSslUtility.ToSslPlatformEnum(this.sslProtocol), false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
#else
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IPAddress Utility class
|
||||||
|
/// </summary>
|
||||||
|
public static class IPAddressUtility {
|
||||||
|
/// <summary>
|
||||||
|
/// Return AddressFamily for the IP address
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ipAddress">IP address to check</param>
|
||||||
|
/// <returns>Address family</returns>
|
||||||
|
public static AddressFamily GetAddressFamily(IPAddress ipAddress) =>
|
||||||
|
#if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
|
||||||
|
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>
|
}
|
||||||
/// MQTT SSL utility class
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
public static class MqttSslUtility
|
/// MQTT SSL utility class
|
||||||
|
/// </summary>
|
||||||
|
public static class MqttSslUtility {
|
||||||
|
#if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3 && !COMPACT_FRAMEWORK
|
||||||
|
|
||||||
|
public static SslProtocols ToSslPlatformEnum(MqttSslProtocols mqttSslProtocol) => 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;
|
public static SslProtocols ToSslPlatformEnum(MqttSslProtocols mqttSslProtocol)
|
||||||
case MqttSslProtocols.TLSv1_0:
|
|
||||||
return SslProtocols.Tls;
|
|
||||||
/*case MqttSslProtocols.TLSv1_1:
|
|
||||||
return SslProtocols.Tls11;
|
|
||||||
case MqttSslProtocols.TLSv1_2:
|
|
||||||
return SslProtocols.Tls12;*/
|
|
||||||
default:
|
|
||||||
throw new ArgumentException("SSL/TLS protocol version not supported");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#elif (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
|
|
||||||
public static SslProtocols ToSslPlatformEnum(MqttSslProtocols mqttSslProtocol)
|
|
||||||
{
|
{
|
||||||
switch (mqttSslProtocol)
|
switch (mqttSslProtocol)
|
||||||
{
|
{
|
||||||
@ -468,5 +425,5 @@ namespace uPLibrary.Networking.M2Mqtt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
@ -41,4 +41,5 @@ using System.Runtime.InteropServices;
|
|||||||
// to avoid compilation error (AssemblyFileVersionAttribute doesn't exist) under .Net CF 3.5
|
// to avoid compilation error (AssemblyFileVersionAttribute doesn't exist) under .Net CF 3.5
|
||||||
#if !WindowsCE
|
#if !WindowsCE
|
||||||
[assembly: AssemblyFileVersion("4.3.0.0")]
|
[assembly: AssemblyFileVersion("4.3.0.0")]
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
@ -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>
|
||||||
|
/// MQTT Client Session
|
||||||
|
/// </summary>
|
||||||
|
public class MqttClientSession : MqttSession {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// MQTT Client Session
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MqttClientSession : MqttSession
|
/// <param name="clientId">Client Id to create session</param>
|
||||||
{
|
public MqttClientSession(String clientId) : base(clientId) {
|
||||||
/// <summary>
|
}
|
||||||
/// Constructor
|
}
|
||||||
/// </summary>
|
|
||||||
/// <param name="clientId">Client Id to create session</param>
|
|
||||||
public MqttClientSession(string clientId)
|
|
||||||
: base(clientId)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -14,50 +14,46 @@ 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>
|
||||||
|
/// MQTT Session base class
|
||||||
|
/// </summary>
|
||||||
|
public abstract class MqttSession {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// MQTT Session base class
|
/// Client Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class MqttSession
|
public String ClientId { get; set; }
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Client Id
|
/// Messages inflight during session
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ClientId { get; set; }
|
public Hashtable InflightMessages { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Messages inflight during session
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Hashtable InflightMessages { get; set; }
|
public MqttSession()
|
||||||
|
: this(null) {
|
||||||
/// <summary>
|
}
|
||||||
/// Constructor
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
public MqttSession()
|
/// Constructor
|
||||||
: this(null)
|
/// </summary>
|
||||||
{
|
/// <param name="clientId">Client Id to create session</param>
|
||||||
}
|
public MqttSession(String clientId) {
|
||||||
|
this.ClientId = clientId;
|
||||||
/// <summary>
|
this.InflightMessages = new Hashtable();
|
||||||
/// Constructor
|
}
|
||||||
/// </summary>
|
|
||||||
/// <param name="clientId">Client Id to create session</param>
|
/// <summary>
|
||||||
public MqttSession(string clientId)
|
/// Clean session
|
||||||
{
|
/// </summary>
|
||||||
this.ClientId = clientId;
|
public virtual void Clear() {
|
||||||
this.InflightMessages = new Hashtable();
|
this.ClientId = null;
|
||||||
}
|
this.InflightMessages.Clear();
|
||||||
|
}
|
||||||
/// <summary>
|
}
|
||||||
/// Clean session
|
}
|
||||||
/// </summary>
|
|
||||||
public virtual void Clear()
|
|
||||||
{
|
|
||||||
this.ClientId = null;
|
|
||||||
this.InflightMessages.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -17,34 +17,31 @@ Contributors:
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
|
||||||
namespace uPLibrary.Networking.M2Mqtt.Utility
|
namespace uPLibrary.Networking.M2Mqtt.Utility {
|
||||||
{
|
/// <summary>
|
||||||
|
/// Extension class for a Queue
|
||||||
|
/// </summary>
|
||||||
|
internal static class QueueExtension {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extension class for a Queue
|
/// Predicate for searching inside a queue
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static class QueueExtension
|
/// <param name="item">Item of the queue</param>
|
||||||
{
|
/// <returns>Result of predicate</returns>
|
||||||
/// <summary>
|
internal delegate Boolean QueuePredicate(Object item);
|
||||||
/// Predicate for searching inside a queue
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
/// <param name="item">Item of the queue</param>
|
/// Get (without removing) an item from queue based on predicate
|
||||||
/// <returns>Result of predicate</returns>
|
/// </summary>
|
||||||
internal delegate bool QueuePredicate(object item);
|
/// <param name="queue">Queue in which to search</param>
|
||||||
|
/// <param name="predicate">Predicate to verify to get item</param>
|
||||||
/// <summary>
|
/// <returns>Item matches the predicate</returns>
|
||||||
/// Get (without removing) an item from queue based on predicate
|
internal static Object Get(Queue queue, QueuePredicate predicate) {
|
||||||
/// </summary>
|
foreach (Object item in queue) {
|
||||||
/// <param name="queue">Queue in which to search</param>
|
if (predicate(item)) {
|
||||||
/// <param name="predicate">Predicate to verify to get item</param>
|
return item;
|
||||||
/// <returns>Item matches the predicate</returns>
|
}
|
||||||
internal static object Get(Queue queue, QueuePredicate predicate)
|
}
|
||||||
{
|
return null;
|
||||||
foreach (var item in queue)
|
}
|
||||||
{
|
}
|
||||||
if (predicate(item))
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -14,73 +14,57 @@ 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,
|
||||||
{
|
Warning = 0x02,
|
||||||
Error = 0x01,
|
Information = 0x04,
|
||||||
Warning = 0x02,
|
Verbose = 0x0F,
|
||||||
Information = 0x04,
|
Frame = 0x10,
|
||||||
Verbose = 0x0F,
|
Queuing = 0x20
|
||||||
Frame = 0x10,
|
}
|
||||||
Queuing = 0x20
|
|
||||||
}
|
// delegate for writing trace
|
||||||
|
public delegate void WriteTrace(String format, params Object[] args);
|
||||||
// delegate for writing trace
|
|
||||||
public delegate void WriteTrace(string format, params object[] args);
|
/// <summary>
|
||||||
|
/// Tracing class
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Tracing class
|
public static class Trace {
|
||||||
/// </summary>
|
public static TraceLevel TraceLevel;
|
||||||
public static class Trace
|
public static WriteTrace TraceListener;
|
||||||
{
|
|
||||||
public static TraceLevel TraceLevel;
|
[Conditional("DEBUG")]
|
||||||
public static WriteTrace TraceListener;
|
public static void Debug(String format, params Object[] args) => TraceListener?.Invoke(format, args);
|
||||||
|
|
||||||
[Conditional("DEBUG")]
|
public static void WriteLine(TraceLevel level, String format) {
|
||||||
public static void Debug(string format, params object[] args)
|
if ((level & TraceLevel) > 0) {
|
||||||
{
|
TraceListener.Invoke(format);
|
||||||
if (TraceListener != null)
|
}
|
||||||
{
|
}
|
||||||
TraceListener(format, args);
|
|
||||||
}
|
public static void WriteLine(TraceLevel level, String format, Object arg1) {
|
||||||
}
|
if ( (level & TraceLevel) > 0) {
|
||||||
|
TraceListener.Invoke(format, arg1);
|
||||||
public static void WriteLine(TraceLevel level, string format)
|
}
|
||||||
{
|
}
|
||||||
if (TraceListener != null && (level & TraceLevel) > 0)
|
|
||||||
{
|
public static void WriteLine(TraceLevel level, String format, Object arg1, Object arg2) {
|
||||||
TraceListener(format);
|
if ((level & TraceLevel) > 0) {
|
||||||
}
|
TraceListener.Invoke(format, arg1, arg2);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public static void WriteLine(TraceLevel level, string format, object arg1)
|
|
||||||
{
|
public static void WriteLine(TraceLevel level, String format, Object arg1, Object arg2, Object arg3) {
|
||||||
if (TraceListener != null && (level & TraceLevel) > 0)
|
if ((level & TraceLevel) > 0) {
|
||||||
{
|
TraceListener.Invoke(format, arg1, arg2, arg3);
|
||||||
TraceListener(format, arg1);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void WriteLine(TraceLevel level, string format, object arg1, object arg2)
|
|
||||||
{
|
|
||||||
if (TraceListener != null && (level & TraceLevel) > 0)
|
|
||||||
{
|
|
||||||
TraceListener(format, arg1, arg2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void WriteLine(TraceLevel level, string format, object arg1, object arg2, object arg3)
|
|
||||||
{
|
|
||||||
if (TraceListener != null && (level & TraceLevel) > 0)
|
|
||||||
{
|
|
||||||
TraceListener(format, arg1, arg2, arg3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -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;
|
||||||
|
|
||||||
@ -33,4 +33,5 @@ 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
|
@ -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
|
@ -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
|
@ -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
|
Loading…
Reference in New Issue
Block a user