Giter VIP home page Giter VIP logo

gnatmq's Introduction

GnatMQ

GnatMQ - MQTT Broker for .NET and WinRT

Alternatives

This repository is not well maintained, and the code is a bit dated. MQTTnet is the direct alternative, and better maintained. dotNetty is a Microsoft-supported generic messaging server that supports MQTT transport. That's a good option is you want to use the protocol to talk to a server, rather than to use it as a broker.

Description

A broker (server) for the MQTT protocol, an M2M Internet-of-Things communication protocol based on .Net Framework.

MQTT, short for Message Queue Telemetry Transport, is a light weight messaging protocol that enables embedded devices with limited resources to perform asynchronous communication on a constrained network.

Developed by IBM and Eurotech, the MQTT protocol is released as an open standard and being standardized by OASIS (Organization for the Advancement of Structured Information Standard), a non-profit consortium that drives the development, convergence and adoption of open standards for the global information society.

In general, the MQTT environment consists of multiple clients and a server, called broker.

This project is created to develop an MQTT broker. While there are other MQTT broker project, this project is created to provide additional resources to learn and engage in developing useful resources for the MQTT protocol, in conjunction with the M2Mqtt project, a .NET client library for MQTT that supports .NET Framework, .NET Compact Framework and .NET Micro Framework.

How to use:

Install-Package GnatMQ_Broker -Version 1.2.0

Starting the server is simple:

using uPLibrary.Networking.M2Mqtt;

static void Main(string[] args)
{
    // create and start broker
    MqttBroker broker = new MqttBroker();
    broker.Start();
	//Once the broker is started, you applciaiton is free to do whatever it wants. 
    Console.ReadLine();
	
	///Stop broker
    broker.Stop();
}

The broker can also be embedded in an applicaiton, be that a cloud server, desktop app or even a UWP applicaiton.

Supported Platforms:

  • .Net Framework (up to 4.5)
  • .Net Compact Framework 3.5 & 3.9 (for Windows Embedded Compact 7 / 2013)
  • .Net Micro Framework 4.2 & 4.3
  • Mono (for Linux O.S.)
  • Windows 8.1
  • Windows Phone 8.1
  • Windows 10 (Through .Net Standard 2)
  • .Net Core (Through .Net Standard 2)

Features

Main features included in the current release:

  • All three Quality of Service (QoS) Levels (at most once, at least once, exactly once);
  • Clean session;
  • Retained messages;
  • Will message (QoS, topic and message);
  • Username/Password via a User Access Control;
  • Subscription to topics with wildcards;
  • Publish and subscribe handle using inflight queue;
  • Security connection with SSL/TLS;

Features not included in the current release:

  • Broker configuration using a simple config file;
  • Bridge configuration (broker to broker);
  • Sessions, retained and will messages persisted at broker shutdown (ex. database);

Contributing

Contributions are welcome. Please submit a PR against the Dev branch. Because the software supprots so many platforms, testing it is a little involved. Because GnatMQ supports .Net Compact Framework 3.9, building nuget packages requires VS2015 Pro or Enterprise and
Applicaiton Builder for Compact Framework, download here.

More Information

gnatmq's People

Contributors

dennissc avatar dtflx01 avatar gioviq avatar marcelstoer avatar ppatierno avatar uhsl-marcus avatar vladimirakopyan avatar weshouman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gnatmq's Issues

CPU Leak if you specify Username/password

Hi,

Im using M2MQTT from https://www.nuget.org/packages/M2Mqtt/
IF i create a client and specify a user name the CPU usgae goes up by 25% and stays there even if the connection fails due to wrong credentials. And next call to connect will increment the CPU usage by 25%

So if you have multiple thread connecting to MQTT server, after a couple of calls the CPU reached 100% and crashes.
Following code can reproduce the issue, add it to a Console application .Net 4.5 or greater:

            Console.WriteLine("start?");
            Console.Read();
            Console.WriteLine("starting, please monitor the CPU usage.");
            List < MqttClient > l = new List<MqttClient>();
            for (int i = 0; i < 10; i++)
            {
                var client = new MqttClient(
                "test.mosquitto.org"
                , 1883
                , false
                , null
                , null
                , new MqttSslProtocols());
                client.MqttMsgPublishReceived += Client_MqttMsgPublishReceived;
                try
                {
                    client.Connect(Guid.NewGuid().ToString(), "ss", null);//intentionally making it fail with wrong credentials
                }
                catch(Exception ex) { Console.WriteLine("Error");  }
                l.Add(client);
            }            

            Console.WriteLine("Exit?");
            Console.Read();```

www.m2mqtt.net forbidden error

Forbidden

You don't have permission to access / on this server.

Additionally, a 403 Forbidden error was encountered while trying to use an ErrorDocument to handle the request.

Integration API for the broker

It is clearly a common use-case to embed the broker in a larger application (Issue #41, #33, #21, #38) that has some functionality, and attempt to talk back to the clients. People keep re-writing the same thing again and again.

Instead of trying to use client and server library withing one application, or using loopback (which is impossible in UWP) we can design an API into the broker that would enable it to create a "virtual" client and talk to other clients on the network.

It would be trivial to implement an event-based API to notify the parent application of new messages, and with a bit of through we can put together an API to "talk back" to the clients.

Integration API

  • Presense - See how many clients are connected
  • Management Events - Client Joined / Client left events
  • Observe - see messages that are being exchanged
  • Publish - let the broker send messages. Mosquitto does that on the topic $SYS/, but that's just a convention
  • Subscription Permissions - Not all clients can be trusted entirely. We must have a way to reject a client subscribing to messages they are not entitled to. Here is how Mosquitto implements an Access Control File. In this case we must return 0x80.
  • Publish Permissions - Again, not all clients should be allowed to publish anywhere they feel like. However MQTT protocol is not great at dealing with this. As per official spec

If a Server implementation does not authorize a PUBLISH to be performed by a Client; it has no way of informing that Client. It MUST either make a positive acknowledgement, according to the normal QoS rules,or closethe Network Connection [MQTT-3.3.5-2]

Exception raised when client disconnects while messages are still published

Hi all,
If you publish a lot of messages while a client is receiving these messages via the Broker, if the client disconnects at this time and exception is sometimes raised.
The exception is raised in the method PublishThread() file MqttPublisherManager.cs, always when processing this request :
var query = from p in this.retainedMessages where (new Regex(subscriptionTopic)).IsMatch(p.Key) // check for topics based also on wildcard with regex select p.Value;
Indeed, subscriptionTopic becomes sometimes null processing this request.
This is happening, because client.Close() is called in method CloseClient(MqttClient client) while PublishThread() is processing messages on this client.

Regards

Client already exist

During some tests with PLC ( eg . Siemens , Wago ) I noticed that the name of the client , is always the same for every request sent CONN .
The broker , on line 303 of MqttBroker.cs occurs if there is already a client of the same name and destroys the channel .

In fact , the PLC opens n - client , at different times, very quickly, and the broker closes the socket . The PLC tries to reopen the connection , but the broker closes again because there is already a client of the same name .
From the PLC connections exits, with the same name, with the same IP address but with different local ports each time .

You might think of doing verification if the customer already exists with the same but with the same IP address and the same port ?

What do you think ?

Thanks
Alberto

SSL Self signed certificate

Hello,

I actually try to implements a broker and one client with SSL communication.
I've follow this tutorial who explain how to create self signed certificate and use it into the broker.
After that, i've created a client : new MqttClient(IP,8883,true,new X509Certificate2("MyCARoot.cer"),new X509Certificate2("Client1.cer"),MqttSslProtocols.TLSv1_2); and used the method connect().

But after a lot of try, i always have this exceptions :

The remote certificate is invalid according to the validation procedure

The certificates are installed into : Trusted root certification authorities in the local machine.

I've implemented also private static bool UserCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) on my client class and get a

System.Net.Security.SslPolicyErrors.RemoteCertificateNameMismatch

and private static bool UserCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) on my broker class and get a

System.Net.Security.SslPolicyErrors.RemoteCertificateNotAvailable

Did i miss something ?
There is something wrong with my reflection or my implementation ?

Thanks by advance

Client implementation in the GnatMQ nuget package does not work

When using the client uPLibrary.Networking.M2Mqtt.MqttClient from the GnatMQ nuget package, the Connect method always throws the following exception. Using the same code with the M2Mqtt nuget package works flawlessly.

Exception of type 'uPLibrary.Networking.M2Mqtt.Exceptions.MqttCommunicationException' was thrown.
   at uPLibrary.Networking.M2Mqtt.MqttClient.SendReceive(Byte[] msgBytes, Int32 timeout) in c:\Users\ppatierno\Source\Repos\gnatmq\GnatMQ\MqttClient.cs:line 1089
   at uPLibrary.Networking.M2Mqtt.MqttClient.SendReceive(MqttMsgBase msg, Int32 timeout) in c:\Users\ppatierno\Source\Repos\gnatmq\GnatMQ\MqttClient.cs:line 1114
   at uPLibrary.Networking.M2Mqtt.MqttClient.SendReceive(MqttMsgBase msg) in c:\Users\ppatierno\Source\Repos\gnatmq\GnatMQ\MqttClient.cs:line 1100
   at uPLibrary.Networking.M2Mqtt.MqttClient.Connect(String clientId, String username, String password, Boolean willRetain, Byte willQosLevel, Boolean willFlag, String willTopic, String willMessage, Boolean cleanSession, UInt16 keepAlivePeriod) in c:\Users\ppatierno\Source\Repos\gnatmq\GnatMQ\MqttClient.cs:line 564
   at uPLibrary.Networking.M2Mqtt.MqttClient.Connect(String clientId) in c:\Users\ppatierno\Source\Repos\gnatmq\GnatMQ\MqttClient.cs:line 475

Exception thrown in method PublishThread in file MqttPublisherManager

var query = from s in session.Subscriptions
    where (new Regex(s.Topic)).IsMatch(outgoingMsg.Topic) select s;

    MqttSubscription subscription = query.First();
    if (subscription != null)
    {

The above code snippet will every once in a while throw a exception. This in turn will crash the PublishTread which in turn for all intents and purpouses halt the broker.

The code needs to be query.FirstOrDefault();

While loop in Publish Thread should probably also have a try catch block..

Relation with gNatt

I found this project https://github.com/jklemmack/gNatt and a lot of the code seems similar to GnatMQ. The problem is that the two projects have really different licenses so I need to know if the other project infringes on GnatMQ copyright and can't be used.

Thanks.

MqttBroker hangs when client disconnects

Hi,

I'm facing a major problem with GnatMQ.

I'm using it to add a MQTT broker on my app. When a client disconnects, the broker hangs. No publication or connection works after the client disconnection.

I've done a simple console program as this
static void Main(string[] args)
{
// create and start broker
MqttBroker broker = new MqttBroker();
broker.Start();
//Once the broker is started, you applciaiton is free to do whatever it wants.
Console.ReadLine();

        ///Stop broker
        broker.Stop();
    }

Using MQTTBox or a test program using M2MQTT after a disconnection, broker is dead !!!

Bug in subscription matching

Hi,
I've encountered an issue with GnatMQ where a client receives messages that he hasn't subscribed to.

The issue is that the client subscribes to "some/topic" only (no wildcard), but as result also receives "some/topic/sub" messages. This is very unlucky if the client uses several subtopics for different tasks...
With other brokers (and the same, proven and working MQTT clients), everything works fine.
When replacing mosquitto with GnatMQ as the broker (in a running configuration of various clients), the issue has been observed, but you can also reproduce it in an isolated environment (tested on both Win10 IoT Core and Win10 x64).

Steps to reproduce:

  • start "vanilla" GnatMQ broker, in either UAP or win32 console application
  • using the "mosquitto_sub" tool, subscribe to "some/topic":
    mosquitto_sub -h 192.168.1.111 -t "some/topic" -v
  • then publish using "mosquitto_pub":
    mosquitto_pub -h 192.168..1.111 -t "some/topic/bla" -d -l 0`

expected behavior: message isn't sent to client, since he didnt' subscribe to any wildcard and has no exactly matching subscription.

observed behavior: message is sent to client nevertheless:
some/topic/bla 0

(also reproducible with M2Mqtt client)

I suspect "this regex stuff" in MqttSubscriberManager.cs to be responsible, but have no clue what to do to fix it. When I should test something just let me know.

regards

EDIT:
wow I'm learning regex in c# ... :)

I've probably found the cause. I tried the following:
`

        string string1 = "some/topic";
        string PLUS_WILDCARD = "+";
        string SHARP_WILDCARD = "#";

        string PLUS_WILDCARD_REPLACE = @"[^/]+";
        string SHARP_WILDCARD_REPLACE = @".*";


        string string2 = string1.Replace(PLUS_WILDCARD, PLUS_WILDCARD_REPLACE).Replace(SHARP_WILDCARD, SHARP_WILDCARD_REPLACE);
        Console.WriteLine("replaced topic: {0}", string2);

        bool result = (new Regex(string2)).IsMatch("some/topic/bla");
        Console.WriteLine("Result: {0}", result.ToString());

        bool result2 = (new Regex("^"+string2+"$")).IsMatch("some/topic/bla");
        Console.WriteLine("Result2: {0}", result2.ToString());

        Console.ReadKey();`

`

Mr Patierno: could you please adjust the regex matching in MqttSUbscriberManager.cs to use exact matching, as shown in above example with "bool result2"? I think this is a serious bug in GnatMQ.

In my tests with ^$ around the regex, the wildcard replacement regexes still work as expected (just try with "string1" in the example ending in /+ or /# and you'll see) , so I think this is safe to apply this fix without breaking things. What do you think?

EDIT2 - I forked GnatMQ and tried with above modification, looks good, see #43

and, last edit, kudos to https://stackoverflow.com/questions/4581412/how-to-make-regexs-only-match-on-exact-matches for helping me finding a solution

Best regards

Performance

Hello,
what are the QNATMQ performances? I mean number of concurrent connections, latency, etc.

Thank you

$ Caracter in Topic not recognized

Hi, if in topic use a $ charatecter there is error in recognize of subscription because the $ is a special char for the regex.
To resolve:

MqttSubscriberManager.cs

Add:
private const string DOLLAR_WILDCARD = "$";
private const string DOLLAR_WILDCARD_REPLACE = @"\x24";

and add the new replace to the current replace.

  string topicReplaced = topic.Replace(PLUS_WILDCARD, PLUS_WILDCARD_REPLACE)
                              .Replace(SHARP_WILDCARD, SHARP_WILDCARD_REPLACE)
                              .Replace(DOLLAR_WILDCARD, DOLLAR_WILDCARD_REPLACE);

Enjoy !

UWP Broker and UWP Client cannot running on same device

Hello,

I have develop a UWP mqtt broker using GnatMQ and a UWP mqtt client using M2Mqtt. My problem is when the broker starts and client trying to connect with this broker, I get a connection exception (both broker and client are running on Windows IoT 10 core).
Otherwise, when I start the UWP broker on another device located on same local network (eg my laptop) the UWP client is connected and exchanges messages with broker.
My question is if UWP broker and UWP client can run on same device (Windows IoT 10 core).

Thank you,
Niki

MqttClient.cs: An socket exception causes exception loop in ReceiveThread()

Issue
In some conditions when calling this.channel.Receive(), to read the first byte/header, throws socket exception (typically "An existing connection was forcibly closed by the remote host") the ReceiveThread() never exists. It remains in a tight loop consuming cpu and throwing socket exceptions (isRunning is never set to False).

I was unable to manually reproduce the exception loop.

Solution suggestion
Change mqtt the code in general and the catch{} block, so that any exception causes the connection to broker/client to close and abort.

My workaround
I have set isRunning to false in the catch{} block to exit the receive tread.

Note: This is for m2mqtt.net (client side of mqtt library).

Broker and Client on same device not connecting

When I start an Broker (BackgroundApplication Windows 10 IoT) and want to connect to it with localhost from an UWP app, there occurs an timeout.

I have an Pi3 with the latest Windows 10 IoT installed.

Can't able to Reconnect once MQTT Client Forcibly closed

Hi,
I am using GnatMq Broker if some of the connected clients whenever forcibly disconnect and trying to reconnect that time the client reconnect is not happening. how can I handle this issue, it could be better if someone suggests the way or give me some sample code to achieve this.

Broker is freezing after calling boker.stop()

       MqttUserAuthenticationDelegate userDel = new MqttUserAuthenticationDelegate(
            delegate(string username, string pass)
            {
                if (username == "user" && pass == "pass")
                    return true;
                else
                    return false;
            }
        );
        MqttBroker broker = new MqttBroker();
        broker.UserAuth = userDel;
        broker.ClientConnected += Broker_ClientConnected;
        broker.ClientDisconnected += Broker_ClientDisconnected;
        broker.Start();

        Console.WriteLine("Press <Enter> to Close Server");
        Console.ReadLine();
        broker.Stop();

if any client requests comes with no authentication/wrong credentials, then application is freezing.
i made a windows service before and it never stops. then in console application I encountered this.

Problems with Xamarin Studio

I have a problem with the connection MqttClient:

public void Connect(string server)
{
try
{
client = new MqttClient(server);
string clientId = Guid.NewGuid().ToString();
client.Connect(clientId);
Broker = server;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}

Error CS0012: The type System.Net.IPAddress' is defined in an assembly that is not referenced. Consider adding a reference to assembly System, Version=3.9.0.0, Culture=neutral, PublicKeyToken=969db8053d3322ac, Retargetable=Yes' (CS0012)

Can You help me, please?

Toni

Community Ownership

I think by now it is clear that @ppatierno is not watching the project any more, however there is clearly a need for .Net to have an MQTT broker that work anywhere, from ancient .Net framework deployments to embedding in a UWP application. People are actively working on the project and making changes, such as bug fixes, dramatic performance improvements. We clearly want to benefit from those improvements, but they are not happening in a central location.

Something has to be done. Let's organise ourselves, and declare one specific repository the official successor of the current item. How about we create an organisation on Github, and add all the active developers / maintainers ?

I personally don't care about performance, but want a reliably working MQTT broker that I can deploy inside my UWP app, which I am working on as a side project and intend to publish on the store.

Other issues need to be discussed - for example, can we drop windows 8.1? How about restricting our target run-times for the broker to:

  • Net Framework 4.5.2 or greater
  • Net Core 1.1 or greater
  • UWP

Mind you, there is Emitter.io, another MQTT broker written in .Net, but they are dropping .net and switching to GoLang because they want to use clustering and distributed stuff - and that's great but It also is moving into a different territory.
I believe there is a case for cross-platform, single, simple MQTT broker for .Net.
In case where scalability is needed one can combine it with Kafka or something.

bug in GnatMQ\Managers\MqttSubscriberManager.cs

The problem seems to be in the last line of GetSubscription:

return query.Distinct(comparer).First();

If the query.Distinct(comparer) comes back empty, the .First() throws an error.

Perhaps

return query.Distinct(comparer).FirstOrDefault();

would be the fix?

Collection has been modified while accessing it

When subscribing to several messages while publishing default values to these messages from the main thread, I get exceptions in MqttSubscriberManager.cs and MqttSubscriberManager.cs saying that the collection has been modified while accessing it.
The correction I applied is, the subscribers and retainedMessages collection have to be sourrounded by lock statements with the collections implied.
Regards

When several client connect to the Broker, an exception is raised InflightQueueFull

I've both a GnatMQ Broker and a client M2Mqtt running on the same application on a Windows embedded compact 2013 device.
Another device run only the client M2Mqtt which is connected to tha first device on the Broker.
Then a third client M2Mqtt is connecting from an application running on a Windows 7 to the Broker. At this time an exception is raised very often on the Broker : MqttClientErrorCode.InflightQueueFull.
This appears in the file MqttClient.cs in the following method public ushort Publish(string topic, byte[] message, byte qosLevel, bool retain).

`public ushort Publish(string topic, byte[] message, byte qosLevel, bool retain)
{
MqttMsgPublish publish =
new MqttMsgPublish(topic, message, false, qosLevel, retain);
publish.MessageId = this.GetMessageId();

        // enqueue message to publish into the inflight queue
        bool enqueue = this.EnqueueInflight(publish, MqttMsgFlow.ToPublish);

        // message enqueued
        if (enqueue)
            return publish.MessageId;
        // infligh queue full, message not enqueued
        else
            throw new MqttClientException(MqttClientErrorCode.InflightQueueFull);
    }`

This exception is raised because this.EnqueueInflight(publish, MqttMsgFlow.ToPublish) returns false.

Any clue please ?
Regards

NullReferenceException in MqttClient - MQTT broker to MQTT client communication

Hi,
I use the Broker on my Raspberry Pi running Windows 10 IoT Core. Due to the network isolation, it is not possible to run the broker and the client at the same machine connecting via a loopback connection. So I decided to implement the communication layer and build an in-memory connection which allows connecting regular clients via TCP and inside my application via RAM. The broker runs without a problem but the MqttClient is not usable.

The ctor I use is: public MqttClient(IMqttNetworkChannel channel)

Whenever I call Connect("MyClient") I get a NullReferenceException. StackTrace:

   at uPLibrary.Networking.M2Mqtt.MqttClient.SendReceive(Byte[] msgBytes, Int32 timeout)
   at uPLibrary.Networking.M2Mqtt.MqttClient.SendReceive(MqttMsgBase msg, Int32 timeout)
   at uPLibrary.Networking.M2Mqtt.MqttClient.SendReceive(MqttMsgBase msg)
   at uPLibrary.Networking.M2Mqtt.MqttClient.Connect(String clientId, String username, String password, Boolean willRetain, Byte willQosLevel, Boolean willFlag, String willTopic, String willMessage, Boolean cleanSession, UInt16 keepAlivePeriod)
   at uPLibrary.Networking.M2Mqtt.MqttClient.Connect(String clientId)
   at HA4IoT.Hardware.Mqtt.MqttService.Startup()
   at HA4IoT.Core.ContainerExtensions.StartupServices(Container container)

Whithout calling Connect("MyClient") I can still send messages without problems.

I forked this project and saw that the object which is null is: this.syncEndReceiving.Reset(); // at line 1053

I tried to solve the problem on my own via adding this following line to the contructor: this.syncEndReceiving = new AutoResetEvent(false);

Then I get no NullReferenceException anymore but after a certain time (a few seconds) I always get a MqttCommunicationException. It seems that the timeout of the AutoResetEvent is not Set() properly to the WaitOne() method returns false.

My implementations of the communication channel are (maybe these are causing the issue):

public class MqttBrokerChannel : IMqttCommunicationLayer
    {
        private readonly StreamSocketListener _socket = new StreamSocketListener();

        public event MqttClientConnectedEventHandler ClientConnected;

        public void Start()
        {
            _socket.ConnectionReceived += ProcessConnection;
            _socket.BindServiceNameAsync(MqttSettings.Instance.Port.ToString()).AsTask().Wait();

            Log.Info($"Started MQTT broker with port {MqttSettings.Instance.Port}.");
        }

        public void Stop()
        {
            _socket.Dispose();
        }

        public void Attach(MqttClient mqttClient)
        {
            if (mqttClient == null) throw new ArgumentNullException(nameof(mqttClient));

            Log.Verbose("Attached internal client to MQTT broker.");
            ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(mqttClient));
        }

        private void ProcessConnection(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
        {
            Log.Verbose($"External client ({args.Socket.Information.RemoteAddress}) connected to MQTT broker.");
            var mqttClient = new MqttClient(new MqttNetworkChannel(args.Socket));
            ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(mqttClient));
        }
    }

    public class MqttLoopbackClientChannel : IMqttNetworkChannel
    {
        private readonly object _syncRoot = new object();
        private readonly ManualResetEvent _memoryGate = new ManualResetEvent(false);
        private readonly MemoryStream _memory = new MemoryStream();

        public bool DataAvailable
        {
            get
            {
                lock (_syncRoot)
                {
                    return _memory.Length > 0;
                }
            }
        }

        public int Receive(byte[] buffer)
        {
            return Receive(buffer, Timeout.Infinite);
        }

        public int Receive(byte[] buffer, int timeout)
        {
            if (!_memoryGate.WaitOne(timeout))
            {
                return 0;
            }

            lock (_syncRoot)
            {
                var length = _memory.Read(buffer, 0, buffer.Length);

                if (_memory.Position == _memory.Length)
                {
                    _memory.SetLength(0);
                    _memoryGate.Reset();
                }

                return length;
            }
        }

        public int Send(byte[] buffer)
        {
            lock (_syncRoot)
            {
                _memory.Write(buffer, 0, buffer.Length);
                _memory.Position -= buffer.Length;

                _memoryGate.Set();
                return buffer.Length;
            }
        }

        public void Close() { }

        public void Connect() { }

        public void Accept() { }
    }

Best regards,
Christian Kratky

Retain LastWill

Using M2Mqtt as a client that connects with willRetain flag ON, does not retain the message.

//ID, User, Pass, WillRetain, WillQoS, WillFlag, WillTopic, WillMessage, Clean, KeepAlive
client.Connect(clientID, null, null, true, MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, true, "State/lastWill", "online", true, 3);

Brokers Logs Record Into MS SQL

is there any way to store sessions from Brokers into database and keep logs of records and time of event.

how to include listening of brokers into MS SQL (2005+) is there any way

Dead?

Is this project dead? No commits since Dec 2015.

Problems With SSL and Windows 10 IoT Core

Hello!

I actually left this as a reply to Paolos Article.. regarding using M2Mqtt for Windows 10 IoT Core. but I thought maybe this could be interesting for more people so I will ask this question here also..

Im currently building a "Local Agent" for an Central IoT Solution using Raspberry and Windows 10 IoT Core. We already have a Mqtt Broker set up and it works great for several different clients including, iOS, Windows and ESP8266. To handle basic security we use SSL (TLS1.2 Protocol) with a bought certificate from a trusted certificate authority.

Now Im trying to use M2Mqtt for Mqtt Client and it looks like it connects ok, but I cant get it to publish or notify me on any subscribed topics… No exceptions... no nothing.. just cant get any events to fire or publish anything to my topics…:/

Right now I’m using the version from NuGet, but I think I need to get the code to debug this further…

What do you think? have you tested this client on IoT Core using SSL?

Best regards
Torbjörn Nilsson

GetSubscription(string topic, string clientId) throws if no topics found

MqttSubscriberManager.cs:214: query.Distinct(comparer).First(); // First() throws exception if enumerator is 'empty'

My fix:

        public MqttSubscription GetSubscription(string topic, string clientId)
        {
            var query = from ss in this.subscribers
                        where (new Regex(ss.Key)).IsMatch(topic)    // check for topics based also on wildcard with regex
                        from s in this.subscribers[ss.Key]
                        where s.ClientId == clientId                // check for subscriber only with a specified Client Id
                        select s;

            // use comparer for multiple subscriptions that overlap (e.g. /test/# and  /test/+/foo)
            // If a client is subscribed to multiple subscriptions with topics that overlap
            // it has more entries into subscriptions list but broker sends only one message
            this.comparer.Type = MqttSubscriptionComparer.MqttSubscriptionComparerType.OnClientId;

            // pinky: if sequence has no items, First() throws exception
            var item = query.Distinct(comparer).GetEnumerator();
            if (!item.MoveNext())
                return null;
            return item.Current;
        }

Steps to reproduce:

  1. Start broker
  2. Connect and subscribe to topic "$SYS/broker/subscriptions/count" (i have used MQTT.fx 1.0.1)
  3. First() throws exception with message: "Sequence contains no elements"

GnatMQ version: v1.1.0.0

Race between protocol Disconnect message and socket closing

Handling a protocol disconnect (MqttMsgDisconnect.MQTT_MSG_DISCONNECT_TYPE in DispatchEventThread()) will result in OnMqttMsgDisconnected() which will call the MqttMsgDisconnected callback(s) and eventually close the client.

Handling a socket close will call OnConnectionClosing() which will call the ConnectionClosed callback(s) and also close the client.

These 2 events can race each other, and in some cases you may get both callbacks called. Both callbacks by default call MqttClient.Close(), which does not protect against being called more than once.
(It sets IsConnected to false at its end, but it doesn't check it at its beginning. Moreover users are allowed to add their own callbacks, which results in varying levels of weirdness)

This is especially evident if OnMqttMsgDisconnected() takes a bit longer to execute and in the meantime the socket has (gracefully) dropped, so when it exits, it also executes the final part of DispatchEventThread() and re-calls MqttClient.Close().

TL;DR or how i personally solve this:

  1. i added protection against MqttClient.Close() being called twice
  2. the race might be resolved by adding a lock on MqttClient.isConnectionClosing, but i just partitioned the isConnectionClosing part of DiscpatchEventThread into its own block which re-checks isRunning.

If anyone's interested or Paolo requests it, i can create pull requests for these, but for now here's a simple patch.

Performance issue

Steps to reproduce the issue:
use MQTT.fx 0.0.16 as client and run the following script to stress the broker

var Thread = Java.type("java.lang.Thread");

function execute(action) {
out("Test Script: " + action.getName());
for (;;) {
//for (var i = 0; i < 10; i++) {
switchON();
Thread.sleep(0);
switchOFF();
Thread.sleep(1);
}
action.setExitCode(0);
action.setResultText("done.");
out("Test Script: Done");
return action;
}

function switchON() {
out("fountain ON");
mqttManager.publish("home/garden/fountain", "ON");
}

function switchOFF() {
out("fountain OFF");
mqttManager.publish("home/garden/fountain", "OFF");
}

function out(message){
output.print(message);
}

The eventQueue keeps raising in size so memory consumption.

$SYS

Ciao Paolo, come stai?

Angelo from brazil here, I´m using your gnatmq on our solution with no problems at all. I don´t know if I´m wrong but I didn´t see any implementation of $SYS topic. When I connect using MQTT.fx I can subscribe $SYS but do not receive any counters. It´s that correct?

Show Projects where you use GnatMQ

I'd like to list project that use GnatMQ. This would help us understand what others are doing with the library, what platforms we have to support, etc.
The projects don't need to be open-source, we just need a description of what it's doing, and a link would be great.

I use it in a UWP application which acts as a local MQTT broker and dashboard for Arduinos and other sensors. You can get it in Windows Store.

@GioviQ @DennisSc @dtflx01 @dkkriste it would be good to get descriptions from you.

We could then start making plans on further support of the library. I think we are loosing many potential contributions because it's hard to understand code with all these compiler directives.

I don't think anyone uses Windows 8 and now that we have .Net Standard 2 on Xamarin and Windows10 Apps we could get rid of all the WinRT APIs.

Websockets

Hello,
do you ever implement websocket into GnatMQ?

Embeddable MQTT broker

We are modifying Gnatmq to embed it inside a larger application. Inside the mqttBroker class
We made the
void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
Raise an an event to the external application, and we made the method
public void PublishData(string topic, byte[] data, bool retain = true, byte qos = MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE)
public.
Will this cause issues with threading?

Broker Example

Hi,

Would you be able to have an extended broker example. I would like to count the clients, log when a message arrived etc.
Currently I can only start and stop the Broker. Would be nice if you have some examples.

MqttBroker hangs

Twice after running for about a week, I've had MqttBroker not respond when a client attempts to connect. Once this has happened, if I try to call _mqttBroker.Stop(), to gracefully shutdown, it hangs. I end up having to kill the process to restart. Does anyone have any ideas what might be causing this? I'm happy to try to help fix it, but don't know where to start. If there's any more info I can provide, please let me know

MqttClient thows exception

I'm at the very beginning mit MQTT.

In a very simple excample I use mosquitto to play with mqtt on my raspberry.
When I do connect using the MqttClient from M2Mqtt library all works well. But I also would try to deploy the broker and since there is also a MqttClient in the GantMQ library, I'm executing the same code. When I do cliet.Connect("clientId") there are 4 exceptions thown "uPLibrary.Networking.M2Mqtt.Exceptions.MqttClientException" in GnatMQ.WinRT.dll"

I didn't have the time yet to download the source code and debug more deep into. The first question I have, since there are no samples how to use the broker, can I use the client in this library the same way as in the M2Mqtt? Or is this a real bug?

[question] session.InflightMessages: hashTable vs. hashSet

hi,
is there a reason that session.InflightMessages is a hashTable and not a hashSet?
I am asking because the key to the table is the MessageId, which can be shared between messages of flow ToPublish and ToAcknowledge. If you add both messages in the hashTable, the 2nd addition will cause an exception (key exists).

This happened to me during testing (once); if it is not expected/allowed to have both messages in flight at any time, then the root cause may be something else.
Otherwise making InflightMessages a hashSet and storing full msgContexts should resolve this issue.

Bridge feature

Hello,
do you have any intentions to provide this feature in the next future?
If not, may you give any suggestions, start points etc. so that I can try to implement it?

Thank you

Reconnecting a client

I'm running gnatmq on a raspberry and two clients (console application) on my laptop, one publishing massages the other is subscribed to receive them)
When I establish the first connection with both clients, all works well and I receive the messaged.
Then I cancel the message sending client. I configured a "last will" topic and message, but do not receive this message (only once in all my trying).
When I then start the sender again, i cannot connect to the broker. After some timeout a get an exception like "An existing connection was forcibly closed by the remote host".
I've set a breakpoint on the broker on receiving the TCP connection. What I figured out yet ist, I run into that breakpoint (in case of the second connection) only, when the exception on the client is thrown. That means, the thy try of the client to connect is not recognized by the broker.
And also in the client list of the broker there are still two clients, thus the broker didn't recognize one client getting away.

MQTT Broker customization

Where can be found some samples about the customization possibilities of the MQTT broker ?
Does the MQTT broker offer interfaces to add "custom" add-ons/plugins (for example for persisting messages in the cloud) ?

Exception raised when two MQTT client subscribes whith the same ClientID

I found an Exception raised when two MQTT client subscribes whith the same ClientID.
The exception is raised in MqttPublisherManager.cs in method PublishThread() in the following line

var query = from p in this.retainedMessages where (new Regex(subscription.Topic)).IsMatch(p.Key)
// check for topics based also on wildcard with regex
select p.Value;
Exception is raised because subscription.Topic is null.
Each ClientID must be unique, but if it happens, this issue appears.

Regards

Broker MqttClient not closing TCP connection after connection refused.

Pretty sure this is not intended as the comments suggests otherwise
When Connack function receives a returnCode that is not CONN_ACCEPTED, it does not set the IsConnected flag to true and calls the Close method were there is a if (this.IsConnected) condition before closing the channel and never actually closing it.

Previous versions of this lib did not had that check on MqttClient.Close();

In Connack:

            if (connack.ReturnCode == MqttMsgConnack.CONN_ACCEPTED)
            {
                // [v3.1.1] if client id isn't null, the CONNECT message has a cliend id with zero bytes length
                //          and broker assigned a unique identifier to the client
                this.ClientId = (clientId == null) ? connect.ClientId : clientId;
                this.CleanSession = connect.CleanSession;
                this.WillFlag = connect.WillFlag;
                this.WillTopic = connect.WillTopic;
                this.WillMessage = connect.WillMessage;
                this.WillQosLevel = connect.WillQosLevel;

                this.keepAlivePeriod = connect.KeepAlivePeriod * 1000; // convert in ms
                // broker has a tolerance of 1.5 specified keep alive period
                this.keepAlivePeriod += (this.keepAlivePeriod / 2);

                // start thread for checking keep alive period timeout
                Fx.StartThread(this.KeepAliveThread);

                this.isConnectionClosing = false;
                this.IsConnected = true;
            }
            // connection refused, close TCP/IP channel
            else
            {
                this.Close(); //BUG HERE
            }

On this.Close:

        public void Close()
#else
        private void Close()
#endif
        {
			if (this.IsConnected)
			{
				...
				...
				// close network channel
				this.channel.Close();

				this.IsConnected = false;
			}
        }

Client Message Received Event Triggered Multiple Times

I'm using the raw GnatMQ library as a broker and raw MqttDotNet lib as the client. Whenever a message is received in the client with QOS 2, the client's PublishArrived event gets triggered exactly 3 times. When I test the client MqttDotNet library with the sample HiveMQ broker, there is no problem and the event only fires once.

NOTE: This issue ironically ONLY happens with QOS 2!

Additionally, it might be worth mentioning that when a message is sent as retained from a different client such as M2MQTT, and received as retained (not directly) by the MqttDotNet client, the PublishArrived event always triggers twice (and not 3 times).

Here's a topic about this on SO too.

Can anybody help with this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.