MQTTNet with MQTT.js are not working together - asp.net-core

I'm trying to use MQTTNet as service broker, that takes requests from webClients over MQTT.js. However, this method is notworking for unknown reasons.
when i test the Service Broker using the windows application "MQTT Explorer" as a client, it works fine.
When i test the MQTT.js Client to connect to an open Service Broker like broker.emqx.io it works also fine.
but the connection between my service Broker with the mqtt client has always a problem. The following error is thrown from the MQTTNet Server:
Client '[::1]:58434' accepted by TCP listener '[::]:8883, ipv6'.
Expected at least 21538 bytes but there are only 69 bytes
MQTTnet.Exceptions.MqttProtocolViolationException: Expected at least 21538 bytes but there are
only 69 bytes
at MQTTnet.Formatter.MqttBufferReader.ReadString()
at MQTTnet.Formatter.MqttPacketFormatterAdapter.ParseProtocolVersion(ReceivedMqttPacket
receivedMqttPacket)
at MQTTnet.Formatter.MqttPacketFormatterAdapter.DetectProtocolVersion(ReceivedMqttPacket
receivedMqttPacket)
at MQTTnet.Adapter.MqttChannelAdapter.ReceivePacketAsync(CancellationToken cancellationToken)
at MQTTnet.Server.MqttClientSessionsManager.ReceiveConnectPacket(IMqttChannelAdapter
channelAdapter, CancellationToken cancellationToken)
at MQTTnet.Server.MqttClientSessionsManager.HandleClientConnectionAsync(IMqttChannelAdapter
channelAdapter, CancellationToken cancellationToken)
Client '[::1]:58434' disconnected at TCP listener '[::]:8883, ipv6'.
configuration of my server are as following:
static async Task<MqttServer> StartMqttServer(bool isDevelopment, ConsoleLogger consoleLogger = null)
{
MqttFactory mqttFactory = new MqttFactory();
if (consoleLogger != null)
{
mqttFactory = new MqttFactory(consoleLogger);
}
// Due to security reasons the "default" endpoint (which is unencrypted) is not enabled by default!
var mqttServerOptions = mqttFactory.CreateServerOptionsBuilder()
.WithDefaultEndpoint()
.Build();
var server = mqttFactory.CreateMqttServer(mqttServerOptions);
await server.StartAsync();
return server;
}
does anybody know why is this happening? And perhaps have an idea how i can fix it?
Thanks in advaced.

Related

How to make gRPC client comunicate with a gRPC server in a different machine? Both in Aspnet Core 3.0. Possible SSL problem

So, by the title you know what I'm trying to build.
I already have one gRPC server and 3 clients talking together in the same machine. The server is accessible on http://localhot:5001. Everything runs smoothly but if I run the clients on another machine they cannot access the server. So I installed IIS and placed the server there for it to get served to outside with the domain beta.server.com. I altered the hosts file on the client machine to go to the computer ip(192.168.5.49) where the server is running on IIS.
When I try to access with the browser by http i get a message saying i can only connect with a gRPC client. By https says NET::ERR_CERT_COMMON_NAME_INVALID. Maybe this is the problem...(found out after writing the rest).
By trying to connect with a gRPC client to http(http://beta.server.com) I get an error saying http/1.1 is not supported, which is true, this service works only on http2.
When try to connect to the server ip with https(https://beta.server.com) I get the error that the ssl connection could not be established. As follows:
PS C:\Users\Farm\Desktop\GrpcSierConsole\Viewer> dotnet run
Entered task
Unhandled exception. System.AggregateException: One or more errors occurred. (Status(StatusCode=Internal, Detail="Error starting gRPC call: The SSL connection could not be established, see inner exception."))
---> Grpc.Core.RpcException: Status(StatusCode=Internal, Detail="Error starting gRPC call: The SSL connection could not be established, see inner exception.")
at Grpc.Net.Client.Internal.HttpContentClientStreamReader`2.MoveNextCore(CancellationToken cancellationToken)
at Grpc.Core.AsyncStreamReaderExtensions.ReadAllAsync[T](IAsyncStreamReader`1 streamReader, CancellationToken cancellationToken)+MoveNext()
at Grpc.Core.AsyncStreamReaderExtensions.ReadAllAsync[T](IAsyncStreamReader`1 streamReader, CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult()
at Viewer.Program.<>c.<<Main>b__0_0>d.MoveNext() in C:\Users\Farm\Desktop\GrpcSierConsole\viewer\Program.cs:line 24
--- End of stack trace from previous location where exception was thrown ---
at Viewer.Program.<>c.<<Main>b__0_0>d.MoveNext() in C:\Users\Farm\Desktop\GrpcSierConsole\viewer\Program.cs:line 24
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait()
at Viewer.Program.Main() in C:\Users\Farm\Desktop\GrpcSierConsole\viewer\Program.cs:line 29
The error is on line 29 on the program.cs in the server. The code I have there is the following:
Line 29 is webBuilder.UseStartup():
//Additional configuration is required to successfully run gRPC on macOS.
// For instructions on how to configure Kestrel and gRPC clients on macOS, visit https://go.microsoft.com/fwlink/?linkid=2099682
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
I've tried to use the Visual Studio localhost certificate and a self signed certificate within the IIS in both the client computer and the server computer running IIS.
Also I've used this line in the client to trust all certificates:
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
Which I got from: How to ignore the certificate check when ssl
I don't know what more to do. Anyone can help?
##################### UPDATE ######################
I've added this code to the client
var httpClientHandler = new HttpClientHandler();
// Return `true` to allow certificates that are untrusted/invalid
httpClientHandler.ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var httpClient = new HttpClient(httpClientHandler);
var channel = GrpcChannel.ForAddress("https://localhost:5001",
new GrpcChannelOptions { HttpClient = httpClient });
var client = new QueueManagement.QueueManagementClient(channel);
...
Now I don't have the SSL error but this one:
PS C:\Users\Farm\Desktop\GrpcSierConsole\Viewer> dotnet run
Entered task
Unhandled exception. System.AggregateException: One or more errors occurred. (Status(StatusCode=Internal, Detail="Error starting gRPC call: An error occurred while sending the request."))
---> Grpc.Core.RpcException: Status(StatusCode=Internal, Detail="Error starting gRPC call: An error occurred while sending the request.")
at Grpc.Net.Client.Internal.HttpContentClientStreamReader`2.MoveNextCore(CancellationToken cancellationToken)
at Grpc.Core.AsyncStreamReaderExtensions.ReadAllAsync[T](IAsyncStreamReader`1 streamReader, CancellationToken cancellationToken)+MoveNext()
at Grpc.Core.AsyncStreamReaderExtensions.ReadAllAsync[T](IAsyncStreamReader`1 streamReader, CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult()
at Viewer.Program.<>c.<<Main>b__0_0>d.MoveNext() in C:\Users\Farm\Desktop\GrpcSierConsole\Viewer\Program.cs:line 32
--- End of stack trace from previous location where exception was thrown ---
at Viewer.Program.<>c.<<Main>b__0_0>d.MoveNext() in C:\Users\Farm\Desktop\GrpcSierConsole\Viewer\Program.cs:line 32
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait()
at Viewer.Program.Main() in C:\Users\Farm\Desktop\GrpcSierConsole\Viewer\Program.cs:line 37
And at line 37 i have the task.wait() because this runs inside a task.
var channel = GrpcChannel.ForAddress("https://beta.server.com",
new GrpcChannelOptions { HttpClient = httpClient });
var client = new QueueManagement.QueueManagementClient(channel);
var request = client.QueueNumberChanged(new SendQueueId { QueueId = "2" });
await foreach (var response in request.ResponseStream.ReadAllAsync())
{
Console.WriteLine($"Senha {response.Number} -> fila 2");
}
});
t.Wait();
After a great research and many messages exchanged in Issues at Microsoft official GitHub Repository for .Net Core kestrel documentation i found it.
It can be done with this settings on appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http2"
},
"EndPoints": {
"Https": {
"Url": "https://*:5002",
"Certificate": {
"Path": "c:\\test.pfx",
"Password": "password1234"
}
}
}
},
}

IllegalArgumentException: "Auth scheme may not be null" in CloseableHttpAsyncClient

I'm running some asynchronous GET requests using a proxy with authentication. When doing HTTPS requests, I'm always running into an exception after 2 successful asyncronous requests:
java.lang.IllegalArgumentException: Auth scheme may not be null
When executing the GET requests without a proxy, or using http instead of https, the exception never occurred.
Example from Apache HttpAsyncClient Examples
HttpHost proxy = new HttpHost("proxyname", 3128);
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope(proxy), new UsernamePasswordCredentials("proxyuser", "proxypass"));
CloseableHttpAsyncClient httpClient = HttpAsyncClients.custom().setDefaultCredentialsProvider(credsProvider).build();
httpClient.start();
RequestConfig config = RequestConfig.custom().setProxy(proxy).build();
for (int i = 0; i < 3; i++) {
HttpGet httpGet = new HttpGet(url);
httpGet.setConfig(config);
httpClient.execute(httpGet, new FutureCallback<HttpResponse>() {
public void failed(Exception ex) {
ex.printStackTrace(); // Exception occures here afther 2nd iteration
}
public void completed(HttpResponse result) {
// works for the first and second iteration
}
public void cancelled() {
}
});
}
httpClient.close();
If I run the code above with 'http://httpbin.org/get', there is no exception, but if I run it with 'https://httpbin.org/get', I get the following exception after 2 successful requests:
java.lang.IllegalArgumentException: Auth scheme may not be null
at org.apache.http.util.Args.notNull(Args.java:54)
at org.apache.http.impl.client.AuthenticationStrategyImpl.authSucceeded(AuthenticationStrategyImpl.java:215)
at org.apache.http.impl.client.ProxyAuthenticationStrategy.authSucceeded(ProxyAuthenticationStrategy.java:44)
at org.apache.http.impl.auth.HttpAuthenticator.isAuthenticationRequested(HttpAuthenticator.java:88)
at org.apache.http.impl.nio.client.MainClientExec.needAuthentication(MainClientExec.java:629)
at org.apache.http.impl.nio.client.MainClientExec.handleResponse(MainClientExec.java:569)
at org.apache.http.impl.nio.client.MainClientExec.responseReceived(MainClientExec.java:309)
at org.apache.http.impl.nio.client.DefaultClientExchangeHandlerImpl.responseReceived(DefaultClientExchangeHandlerImpl.java:151)
at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.responseReceived(HttpAsyncRequestExecutor.java:315)
at org.apache.http.impl.nio.DefaultNHttpClientConnection.consumeInput(DefaultNHttpClientConnection.java:255)
at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:81)
at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:39)
at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:121)
at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:162)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:337)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:276)
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:591)
at java.lang.Thread.run(Thread.java:748)
Note: I'm using httpasyncclient 4.1.4
If this is the exact code you have been executing then the problem is quite apparent. Welcome to the world of even-driven programming.
Essentially what happens is the following:
The client initiates 3 message exchanges by submitting 3 requests to the client execution pipeline in a tight loop
3 message exchanges get queued up for execution
The loop exits
Client shutdown is initiated
Now the client is racing to execute 3 initiated message exchanges and to shut itself down at the same time
If one is lucky and the target server is fast enough one might get all 3 exchanges before the client shuts down its i/o event processing threads
If unlucky or when the request execution is relatively slow, for instance due, to the use of TLS transport security, some of message exchanges might get terminated in the middle of the process. This is the reason you are seeing the failure when using https scheme but not http.

WCF ClientFramingDuplexSessionChannel Opened and Faulted

I have a WCF Duplex net.tcp binding. I create a client DuplexClient to comuunicate with server. If, for some reason the service stop responding (app pool recycles for exemple) between the client creation and the method call, I get a weird behavior.
try
{
var result = await client.SomeMethod();
}
catch (Exception ex)
{
Console.WriteLine($"client.State = {client.State}");
Console.WriteLine($"Error : {ex.Message}");
}
I have this message in the console :
client.State = Opened
Error : The communication object,
System.ServiceModel.Channels.ClientFramingDuplexSessionChannel, cannot
be used for communication because it is in the Faulted state.
How can the channel be in the state Opened while the error says that it is in a Faulted state ? I strongly suspect the ClientFramingDuplexSessionChannel type because it probably keeps an open channel from server to client while the client to server channel is dead. Is it possible ? How can I check if client is realy opened and running both ways ?

Aut discovering of ip address

I have a server and a client that communicate with each other over an UDP socket. The server are opening port 10002 and are listening for incoming datagrams.
For the client to get the server ip it sends one broadcast datagram which the server responds to. The client code responsible for finding the ip address of the server looks like this:
private IPEndPoint GetServerEP(TimeSpan timeout, UdpClient udpclient)
{
IPEndpoint server = new IPEndPoint(IPAddress.Broadcast, 10002);
byte[] data = GetDiscoverDatagram();
_udpclient.EnableBroadcast = true;
udpclient.Send(data, data.Length, server);
try
{
udpclient.Client.ReceiveTimeout = (int)timeout.TotalMilliseconds;
udpclient.Receive(ref server);
}
catch (SocketException e)
{
string msg = string.Format("Server did not respond within {0} ms", timeout.TotalMilliseconds);
throw new TimeoutException(msg, e);
}
return server;
}
Upon running this, I can see that the server actually receives the broadcast datagram and responds with a packet bound for the same port as the client sends from. However, the client does not receive anything and timeouts.
What am I missing?
Stupid me (or; stupid firewall). The code worked, but the firewall blocked the response packet from the server. After disabling everything works like a charm.

A request to send or receive data was disallowed because the socket is not connected

I am trying to connect to a remote external server using TCP sockets in WCF code
My WCF service is the client which has code using sockets to connect to an external server.
This code sends a request to an external server and receives the server response
int byteCount = 0;
Socket m_socClient;
try
{
string query = "My Request String";
m_socClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
System.Net.IPAddress remoteIPAddress = System.Net.IPAddress.Parse("127:0:0:0");
System.Net.IPEndPoint remoteEndPoint = new System.Net.IPEndPoint(remoteIPAddress, 1234);
EVCommon.Log("COnnecting to" + IPSelected + Port);
m_socClient.Connect(remoteEndPoint);
try
{
if (m_socClient.Connected)
{
EVCommon.Log("Connected to" + IPSelected + Port);
var reQuestToSend = string.Format("POST /ZZZZZ HTTP/1.1\r\nContent-Length:{0}\r\n\r\n{1}", query.Length, query);
byte[] bytesToSend = Encoding.ASCII.GetBytes(reQuestToSend);
byteCount = m_socClient.Send(bytesToSend, SocketFlags.None);
byte[] bytesReceived = new byte[1024];
byteCount = m_socClient.Receive(bytesReceived, SocketFlags.None);
Response271 = Encoding.ASCII.GetString(bytesReceived);
m_socClient.Disconnect(false);
m_socClient.Close(5000);
}
}
catch(Exception ex)
{
EVCommon.Log(ex.Message);
}
}
If I make a windows application with the same client code to connect to the remote server, it is successful. I am able to connect, send and receive
This error occurs only when I bring WCF into the picture. The code fails at if(m_socket.Connected). So it is not able to connect successfully.
A request to send or receive data was disallowed because the socket
is not connected and (when sending on a datagram socket using a sendto call) no address was supplied.
Thank you
The difference is that the windows applications runs in the identity of the logged in user and the WCF service runs in the identity of the application pool.
What is probably happening is that the application pool is running as NETWORK SERVICE which does not have the right to open a port.
Try changing the identity of the app pool to your user to check if this is the problem.