Mqttnet: NullReferenceException in ConnectAsync

Created on 31 Jul 2020  路  4Comments  路  Source: chkr1011/MQTTnet

Describe the bug

When connecting to a localhost mosquitto, with appearantly a bad certificate, the LowLevelMqttClient throws a nullreference exception instead of providing a meaningfull response.

EDIT: it seems to be related to any early disconnect by the broker. Without TLS on the wrong port throws also a NullReference

Which project is your bug related to?

  • Client (LowLevelMqttClient)

To Reproduce

Connect to a TCP server, with TLS.
But have the server disconnect the socket early.

Expected behavior

A more meaningfull error to troubleshoot the problem would be nice.
Now I only discovered the reason because I looked into the brokers logs (mosquitto.exe -v)

Screenshots

Additional context / logging

Broker:

1596177119: New connection from ::1 on port 8883.
1596177119: OpenSSL Error: error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate
1596177119: Socket error on client <unknown>, disconnecting.

Client: (not much to see)

[2020-07-31T06:35:55.6685854Z] [] [1] [LowLevelMqttClient] [Verbose]: Trying to connect with server 'localhost:8883' (Timeout=00:00:10).

Code example

            var client = new MqttFactory().CreateLowLevelMqttClient();
            var options = new MqttClientOptionsBuilder()
                .WithClientId("testClient") 
                .WithTcpServer("localhost", 8883)
                .WithProtocolVersion(MqttProtocolVersion.V311)
                .WithTls() 
                .Build();


            await client.ConnectAsync(options, CancellationToken.None);

When using the MqttClient instead of the LowLevelMqttClient, there seems to be no nullreference exception:

[2020-07-31T06:41:30.9712424Z] [] [1] [MqttClient] [Verbose]: Trying to connect with server 'localhost:8883' (Timeout=00:00:10).
[2020-07-31T06:41:31.6311033Z] [] [4] [MqttClient] [Error]: Error while connecting with server.
MQTTnet.Exceptions.MqttCommunicationException: The remote certificate is invalid according to the validation procedure.
 ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
   at System.Net.Security.SslStream.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)
   at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Security.SslStream.ThrowIfExceptional()
   at System.Net.Security.SslStream.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.Security.SslStream.EndProcessAuthentication(IAsyncResult result)
   at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
   at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__64_2(IAsyncResult iar)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
   at MQTTnet.Implementations.MqttTcpChannel.ConnectAsync(CancellationToken cancellationToken)
   at MQTTnet.Implementations.MqttTcpChannel.ConnectAsync(CancellationToken cancellationToken)
   at MQTTnet.Internal.MqttTaskTimeout.WaitAsync(Func`2 action, TimeSpan timeout, CancellationToken cancellationToken)
   at MQTTnet.Adapter.MqttChannelAdapter.ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at MQTTnet.Adapter.MqttChannelAdapter.WrapException(Exception exception)
   at MQTTnet.Adapter.MqttChannelAdapter.ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
   at MQTTnet.Client.MqttClient.ConnectAsync(IMqttClientOptions options, CancellationToken cancellationToken)
[2020-07-31T06:41:31.8173713Z] [] [4] [MqttClient] [Verbose]: Disconnecting [Timeout=00:00:10]
[2020-07-31T06:41:31.8285225Z] [] [4] [MqttClient] [Verbose]: Disconnected from adapter.
[2020-07-31T06:41:31.8420452Z] [] [4] [MqttClient] [Info]: Disconnected.
bug

Most helpful comment

It turns out that the only thing which is not covered in a Unit Test has failed 馃槃
@SGStino Yes that is the fix. I added this and a Unit Tests. Thanks for pointing to the right direction 馃憤

All 4 comments

Please share the stack trace of the null ref exception. Then I can see where it exactly fails.

I'll verify again later, but if i recall correctly, it was reset due to async/await. So it didn't contain that many Mqttnet calls that were any help to me. It also didn't make it into the logging like the MqttCommunicationException did in the high level client.

So i'm guessing it would be something along the lines of await null.

I have diverged a bit from the LowLevelClient and directly used the adapter factory itself (because I wanted to make use of the formatters, which wasn't exposed in the client, why reinvent the wheel, when you just need a faster wheel)

I'll see if I can pinpoint something again by going back in my commit history.

   at MQTTnet.LowLevelClient.LowLevelMqttClient.<ConnectAsync>d__7.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at MqttNetLowLevelExperiment.Program.<Main>d__0.MoveNext() in MqttNetLowLevelExperiment\Program.cs:line 45

Not much usefull information here, but minimal code to replicate:

           var client = new MqttFactory().CreateLowLevelMqttClient();
            var options = new MqttClientOptionsBuilder() 
                .WithTcpServer("localhost", 3881) 
                .Build();

            await client.ConnectAsync(options, CancellationToken.None);

So i'm guessing it fails to do the initial connection, creates a null channel, and then tries to call something on the channel?

EDIT: somewhere around here I guess:
https://github.com/chkr1011/MQTTnet/blob/4f51a238b34d7bc8a2f704b4c960a2ce2fa40c29/Source/MQTTnet/LowLevelClient/LowLevelMqttClient.cs#L51
_adapter is not set, but already disposed. Adding a ? (_adapter?.Dispose()) should fix it?

It turns out that the only thing which is not covered in a Unit Test has failed 馃槃
@SGStino Yes that is the fix. I added this and a Unit Tests. Thanks for pointing to the right direction 馃憤

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pournasserian picture pournasserian  路  7Comments

StefanOssendorf picture StefanOssendorf  路  9Comments

kwende picture kwende  路  6Comments

bilalmalik777 picture bilalmalik777  路  7Comments

snice1981 picture snice1981  路  7Comments