private async Task AcceptTlsEndpointConnectionsAsync(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { try { #if NET452 || NET461 var clientSocket = await Task.Factory.FromAsync(_tlsEndpointSocket.BeginAccept, _tlsEndpointSocket.EndAccept, null).ConfigureAwait(false); #else var clientSocket = await _tlsEndpointSocket.AcceptAsync().ConfigureAwait(false); #endif var sslStream = new SslStream(new NetworkStream(clientSocket)); await sslStream.AuthenticateAsServerAsync(_tlsCertificate, false, SslProtocols.Tls12, false).ConfigureAwait(false); var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(clientSocket, sslStream), new MqttPacketSerializer(), _logger); ClientAccepted?.Invoke(this, new MqttServerAdapterClientAcceptedEventArgs(clientAdapter)); } catch (Exception exception) { _logger.Error <MqttServerAdapter>(exception, "Error while accepting connection at TLS endpoint."); //excessive CPU consumed if in endless loop of socket errors await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false); } } }
private async Task AcceptTlsEndpointConnectionsAsync(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { try { #if NET452 || NET461 var clientSocket = await Task.Factory.FromAsync(_tlsEndpointSocket.BeginAccept, _tlsEndpointSocket.EndAccept, null).ConfigureAwait(false); #else var clientSocket = await _tlsEndpointSocket.AcceptAsync().ConfigureAwait(false); #endif var sslStream = new SslStream(new NetworkStream(clientSocket)); await sslStream.AuthenticateAsServerAsync(_tlsCertificate, false, SslProtocols.Tls12, false).ConfigureAwait(false); var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(clientSocket, sslStream), new MqttPacketSerializer(), _logger); ClientAccepted?.Invoke(this, new MqttServerAdapterClientAcceptedEventArgs(clientAdapter)); } catch (ObjectDisposedException) { // It can happen that the listener socket is accessed after the cancellation token is already set and the listener socket is disposed. } catch (Exception exception) { if (exception is SocketException s && s.SocketErrorCode == SocketError.OperationAborted) { return; } _logger.Error <MqttServerAdapter>(exception, "Error while accepting connection at TLS endpoint."); await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false); } } }
private async void OnConnectionReceivedAsync(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args) { try { var clientHandler = ClientHandler; if (clientHandler != null) { using (var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(args.Socket, _options), new MqttPacketFormatterAdapter(), _logger)) { await clientHandler(clientAdapter).ConfigureAwait(false); } } } catch (Exception exception) { if (exception is ObjectDisposedException) { // It can happen that the listener socket is accessed after the cancellation token is already set and the listener socket is disposed. return; } _logger.Error(exception, "Error while handling client connection."); } finally { try { args.Socket.Dispose(); } catch (Exception exception) { _logger.Error(exception, "Error while cleaning up client connection"); } } }
private void _serverSokcet_OnAccepted(object obj) { Task.Run(() => { var ci = (ChannelInfo)obj; Stream stream = ci.Stream; string remoteEndPoint = ci.ID; X509Certificate2 clientCertificate = null; if (_tlsCertificate != null) { SslStream sslStream = (SslStream)stream; clientCertificate = sslStream.RemoteCertificate as X509Certificate2; if (clientCertificate == null && sslStream.RemoteCertificate != null) { clientCertificate = new X509Certificate2(sslStream.RemoteCertificate.Export(X509ContentType.Cert)); } } var clientHandler = ClientHandler; if (clientHandler != null) { using (var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(stream, remoteEndPoint, clientCertificate), new MqttPacketFormatterAdapter(new MqttPacketWriter()), _rootLogger)) { clientHandler(clientAdapter).ConfigureAwait(false).GetAwaiter().GetResult(); } } }); }
private async Task AcceptDefaultEndpointConnectionsAsync(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { try { //todo: else branch can be used with min dependency NET46 #if NET452 || NET461 var clientSocket = await Task.Factory.FromAsync(_defaultEndpointSocket.BeginAccept, _defaultEndpointSocket.EndAccept, null).ConfigureAwait(false); #else var clientSocket = await _defaultEndpointSocket.AcceptAsync().ConfigureAwait(false); #endif var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(clientSocket, null), new MqttPacketSerializer(), _logger); ClientAccepted?.Invoke(this, new MqttServerAdapterClientAcceptedEventArgs(clientAdapter)); } catch (ObjectDisposedException) { // It can happen that the listener socket is accessed after the cancellation token is already set and the listener socket is disposed. } catch (Exception exception) { if (exception is SocketException s && s.SocketErrorCode == SocketError.OperationAborted) { return; } _logger.Error <MqttServerAdapter>(exception, "Error while accepting connection at default endpoint."); await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false); } } }
public void Setup() { var message = new MqttApplicationMessageBuilder() .WithTopic("A") .Build(); _packet = message.ToPublishPacket(); var serializer = new MqttPacketSerializer(); var serializedPacket = Join(serializer.Serialize(_packet)); _iterations = 10000; _stream = new MemoryStream(_iterations * serializedPacket.Length); for (var i = 0; i < _iterations; i++) { _stream.Write(serializedPacket, 0, serializedPacket.Length); } _stream.Position = 0; var channel = new TestMqttChannel(_stream); _channelAdapter = new MqttChannelAdapter(channel, serializer, new MqttNetLogger().CreateChildLogger(nameof(MqttChannelAdapter))); }
TPacket Roundtrip <TPacket>(TPacket packet, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311) where TPacket : MqttBasePacket { var writer = WriterFactory(); var serializer = MqttPacketFormatterAdapter.GetMqttPacketFormatter(protocolVersion, writer); var buffer = serializer.Encode(packet); var channel = new TestMqttChannel(buffer.ToArray()); var adapter = new MqttChannelAdapter(channel, new MqttPacketFormatterAdapter(protocolVersion, writer), null, new MqttNetLogger()); return((TPacket)adapter.ReceivePacketAsync(CancellationToken.None).GetAwaiter().GetResult()); //using (var headerStream = new MemoryStream(buffer1.ToArray())) //{ // //var fixedHeader = new byte[2]; // //var header = new MqttPacketReader(channel).ReadFixedHeaderAsync(fixedHeader, CancellationToken.None).GetAwaiter().GetResult().FixedHeader; // //using (var bodyStream = new MemoryStream(Join(buffer1), (int)headerStream.Position, (int)header.RemainingLength)) // //{ // // var reader = ReaderFactory(bodyStream.ToArray()); // // return (T)serializer.Decode(new ReceivedMqttPacket(header.Flags, reader, 0)); // //} //} }
public async Task RunWebSocketConnectionAsync(WebSocket webSocket, HttpContext httpContext) { if (webSocket == null) { throw new ArgumentNullException(nameof(webSocket)); } var endpoint = $"{httpContext.Connection.RemoteIpAddress}:{httpContext.Connection.RemotePort}"; var clientCertificate = await httpContext.Connection.GetClientCertificateAsync().ConfigureAwait(false); var isSecureConnection = clientCertificate != null; clientCertificate?.Dispose(); var clientHandler = ClientHandler; if (clientHandler != null) { var writer = new SpanBasedMqttPacketWriter(); var formatter = new MqttPacketFormatterAdapter(writer); var channel = new MqttWebSocketChannel(webSocket, endpoint, isSecureConnection); using (var channelAdapter = new MqttChannelAdapter(channel, formatter, _logger.CreateChildLogger(nameof(MqttWebSocketServerAdapter)))) { await clientHandler(channelAdapter).ConfigureAwait(false); } } }
void DeserializeAndCompare(MqttPacket packet, string expectedBase64Value, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311) { var writer = WriterFactory(); var serializer = MqttPacketFormatterAdapter.GetMqttPacketFormatter(protocolVersion, writer); var buffer1 = serializer.Encode(packet); using (var headerStream = new MemoryStream(buffer1.Join().ToArray())) { using (var channel = new TestMqttChannel(headerStream)) { using (var adapter = new MqttChannelAdapter( channel, new MqttPacketFormatterAdapter(protocolVersion, new MqttBufferWriter(4096, 65535)), null, new MqttNetEventLogger())) { var receivedPacket = adapter.ReceivePacketAsync(CancellationToken.None).GetAwaiter().GetResult(); var buffer2 = serializer.Encode(receivedPacket); Assert.AreEqual(expectedBase64Value, Convert.ToBase64String(buffer2.Join().ToArray())); } } } }
MqttProtocolVersion DeserializeAndDetectVersion(MqttPacketFormatterAdapter packetFormatterAdapter, byte[] buffer) { var channel = new TestMqttChannel(buffer); var adapter = new MqttChannelAdapter(channel, packetFormatterAdapter, null, new MqttNetLogger()); adapter.ReceivePacketAsync(CancellationToken.None).GetAwaiter().GetResult(); return(packetFormatterAdapter.ProtocolVersion); //using (var headerStream = new MemoryStream(buffer)) //{ // //var fixedHeader = new byte[2]; // //var header = new MqttPacketReader(channel).ReadFixedHeaderAsync(fixedHeader, CancellationToken.None).GetAwaiter().GetResult().FixedHeader; // //using (var bodyStream = new MemoryStream(buffer, (int)headerStream.Position, (int)header.RemainingLength)) // //{ // // var reader = ReaderFactory(bodyStream.ToArray()); // // var packet = new ReceivedMqttPacket(header.Flags, reader, 0); // // packetFormatterAdapter.DetectProtocolVersion(packet); // // return adapter.ProtocolVersion; // //} //} }
void DeserializeAndCompare(MqttBasePacket packet, string expectedBase64Value, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311) { var writer = WriterFactory(); var serializer = MqttPacketFormatterAdapter.GetMqttPacketFormatter(protocolVersion, writer); var buffer1 = serializer.Encode(packet); using (var headerStream = new MemoryStream(buffer1.ToArray())) { var channel = new TestMqttChannel(headerStream); var adapter = new MqttChannelAdapter(channel, new MqttPacketFormatterAdapter(protocolVersion, writer), null, new MqttNetLogger()); var receivedPacket = adapter.ReceivePacketAsync(CancellationToken.None).GetAwaiter().GetResult(); var buffer2 = serializer.Encode(receivedPacket); Assert.AreEqual(expectedBase64Value, Convert.ToBase64String(buffer2.ToArray())); //adapter.ReceivePacketAsync(CancellationToken.None); //var fixedHeader = new byte[2]; //var header = new MqttPacketReader(channel).ReadFixedHeaderAsync(fixedHeader, CancellationToken.None).GetAwaiter().GetResult().FixedHeader; //using (var bodyStream = new MemoryStream(Join(buffer1), (int)headerStream.Position, header.RemainingLength)) //{ // var reader = ReaderFactory(bodyStream.ToArray()); // var deserializedPacket = serializer.Decode(new ReceivedMqttPacket(header.Flags, reader, 0)); // var buffer2 = serializer.Encode(deserializedPacket); // Assert.AreEqual(expectedBase64Value, Convert.ToBase64String(Join(buffer2))); //} } }
public void Setup() { _packet = new MqttPublishPacket { Topic = "A" }; var serializer = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311); var serializedPacket = Join(serializer.Encode(_packet)); _iterations = 10000; _stream = new MemoryStream(_iterations * serializedPacket.Length); for (var i = 0; i < _iterations; i++) { _stream.Write(serializedPacket, 0, serializedPacket.Length); } _stream.Position = 0; var channel = new TestMqttChannel(_stream); _channelAdapter = new MqttChannelAdapter(channel, serializer, new MqttNetLogger()); }
public async Task RunWebSocketConnectionAsync(WebSocket webSocket, HttpContext httpContext) { if (webSocket == null) { throw new ArgumentNullException(nameof(webSocket)); } var endpoint = $"{httpContext.Connection.RemoteIpAddress}:{httpContext.Connection.RemotePort}"; var clientCertificate = await httpContext.Connection.GetClientCertificateAsync().ConfigureAwait(false); try { var isSecureConnection = clientCertificate != null; var clientHandler = ClientHandler; if (clientHandler != null) { var formatter = new MqttPacketFormatterAdapter(new MqttBufferWriter(4096, 65535)); var channel = new MqttWebSocketChannel(webSocket, endpoint, isSecureConnection, clientCertificate); using (var channelAdapter = new MqttChannelAdapter(channel, formatter, null, _logger)) { await clientHandler(channelAdapter).ConfigureAwait(false); } } } finally { clientCertificate?.Dispose(); } }
MqttProtocolVersion DeserializeAndDetectVersion(MqttPacketFormatterAdapter packetFormatterAdapter, byte[] buffer) { var channel = new TestMqttChannel(buffer); var adapter = new MqttChannelAdapter(channel, packetFormatterAdapter, null, new MqttNetEventLogger()); adapter.ReceivePacketAsync(CancellationToken.None).GetAwaiter().GetResult(); return(packetFormatterAdapter.ProtocolVersion); }
public MqttPacket Decode(MqttPacketBuffer buffer) { using (var channel = new MemoryMqttChannel(buffer.ToArray())) { var formatterAdapter = new MqttPacketFormatterAdapter(_protocolVersion, new MqttBufferWriter(4096, 65535)); var adapter = new MqttChannelAdapter(channel, formatterAdapter, null, MqttNetNullLogger.Instance); return adapter.ReceivePacketAsync(CancellationToken.None).GetAwaiter().GetResult(); } }
public void Deserialize_10000_Messages() { var channel = new BenchmarkMqttChannel(_serializedPacket); var reader = new MqttChannelAdapter(channel, new MqttPacketFormatterAdapter(new MqttBufferWriter(4096, 65535)), null, new MqttNetEventLogger()); for (var i = 0; i < 10000; i++) { channel.Reset(); var header = reader.ReceivePacketAsync(CancellationToken.None).GetAwaiter().GetResult(); } }
TPacket Roundtrip <TPacket>(TPacket packet, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311, MqttBufferWriter bufferWriter = null) where TPacket : MqttPacket { var writer = bufferWriter ?? WriterFactory(); var serializer = MqttPacketFormatterAdapter.GetMqttPacketFormatter(protocolVersion, writer); var buffer = serializer.Encode(packet); using (var channel = new TestMqttChannel(buffer.Join().ToArray())) { var adapter = new MqttChannelAdapter(channel, new MqttPacketFormatterAdapter(protocolVersion, new MqttBufferWriter(4096, 65535)), null, new MqttNetEventLogger()); return((TPacket)adapter.ReceivePacketAsync(CancellationToken.None).GetAwaiter().GetResult()); } }
async void OnConnectionReceivedAsync(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args) { try { var clientHandler = ClientHandler; if (clientHandler != null) { X509Certificate2 clientCertificate = null; if (args.Socket.Control.ClientCertificate != null) { try { clientCertificate = new X509Certificate2(args.Socket.Control.ClientCertificate.GetCertificateBlob().ToArray()); } catch (Exception exception) { _logger.Warning(exception, "Unable to convert UWP certificate to X509Certificate2."); } } var bufferWriter = new MqttBufferWriter(4096, 65535); var packetFormatterAdapter = new MqttPacketFormatterAdapter(bufferWriter); var tcpChannel = new MqttTcpChannel(args.Socket, clientCertificate, _options); using (var clientAdapter = new MqttChannelAdapter(tcpChannel, packetFormatterAdapter, null, _rootLogger)) { await clientHandler(clientAdapter).ConfigureAwait(false); } } } catch (Exception exception) { if (exception is ObjectDisposedException) { // It can happen that the listener socket is accessed after the cancellation token is already set and the listener socket is disposed. return; } _logger.Error(exception, "Error while handling client connection."); } finally { try { args.Socket.Dispose(); } catch (Exception exception) { _logger.Error(exception, "Error while cleaning up client connection."); } } }
private void AcceptDefaultEndpointConnectionsAsync(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args) { try { var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(args.Socket), new MqttPacketSerializer(), _logger); ClientAccepted?.Invoke(this, new MqttServerAdapterClientAcceptedEventArgs(clientAdapter)); } catch (Exception exception) { _logger.Error <MqttServerAdapter>(exception, "Error while accepting connection at default endpoint."); } }
public Task AcceptWebSocketAsync(WebSocket webSocket) { if (webSocket == null) { throw new ArgumentNullException(nameof(webSocket)); } var channel = new MqttWebSocketServerChannel(webSocket); var clientAdapter = new MqttChannelAdapter(channel, new MqttPacketSerializer(), new MqttNetLogger()); var eventArgs = new MqttServerAdapterClientAcceptedEventArgs(clientAdapter); ClientAccepted?.Invoke(this, eventArgs); return(eventArgs.SessionTask); }
private async Task AcceptClientConnectionsAsync() { while (!_cancellationToken.IsCancellationRequested) { try { #if NET452 || NET461 var clientSocket = await Task.Factory.FromAsync(_socket.BeginAccept, _socket.EndAccept, null).ConfigureAwait(false); #else var clientSocket = await _socket.AcceptAsync().ConfigureAwait(false); #endif clientSocket.NoDelay = true; SslStream sslStream = null; if (_tlsCertificate != null) { sslStream = new SslStream(new NetworkStream(clientSocket), false); await sslStream.AuthenticateAsServerAsync(_tlsCertificate, false, _tlsOptions.SslProtocol, false).ConfigureAwait(false); } _logger.Verbose("Client '{0}' accepted by TCP listener '{1}, {2}'.", clientSocket.RemoteEndPoint, _socket.LocalEndPoint, _addressFamily == AddressFamily.InterNetwork ? "ipv4" : "ipv6"); var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(clientSocket, sslStream), new MqttPacketSerializer(), _logger); ClientAccepted?.Invoke(this, new MqttServerAdapterClientAcceptedEventArgs(clientAdapter)); } catch (ObjectDisposedException) { // It can happen that the listener socket is accessed after the cancellation token is already set and the listener socket is disposed. } catch (Exception exception) { if (exception is SocketException s && s.SocketErrorCode == SocketError.OperationAborted) { return; } _logger.Error(exception, $"Error while accepting connection at TCP listener {_socket.LocalEndPoint} TLS={_tlsCertificate != null}."); await Task.Delay(TimeSpan.FromSeconds(1), _cancellationToken).ConfigureAwait(false); } } }
public async Task RunWebSocketConnectionAsync(WebSocket webSocket, string endpoint) { if (webSocket == null) { throw new ArgumentNullException(nameof(webSocket)); } var clientAdapter = new MqttChannelAdapter(new MqttWebSocketChannel(webSocket, endpoint), new MqttPacketSerializer(), new MqttNetLogger().CreateChildLogger(nameof(MqttWebSocketServerAdapter))); var eventArgs = new MqttServerAdapterClientAcceptedEventArgs(clientAdapter); ClientAccepted?.Invoke(this, eventArgs); if (eventArgs.SessionTask != null) { await eventArgs.SessionTask.ConfigureAwait(false); } }
private async Task AcceptDefaultEndpointConnectionsAsync(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { try { //todo: else branch can be used with min dependency NET46 #if NET452 || NET461 var clientSocket = await Task.Factory.FromAsync(_defaultEndpointSocket.BeginAccept, _defaultEndpointSocket.EndAccept, null).ConfigureAwait(false); #else var clientSocket = await _defaultEndpointSocket.AcceptAsync().ConfigureAwait(false); #endif var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(clientSocket, null), new MqttPacketSerializer(), _logger); ClientAccepted?.Invoke(this, new MqttServerAdapterClientAcceptedEventArgs(clientAdapter)); } catch (Exception exception) { _logger.Error <MqttServerAdapter>(exception, "Error while accepting connection at default endpoint."); //excessive CPU consumed if in endless loop of socket errors await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false); } } }
async Task TryHandleClientConnectionAsync(CrossPlatformSocket clientSocket) { Stream stream = null; string remoteEndPoint = null; try { remoteEndPoint = clientSocket.RemoteEndPoint.ToString(); _logger.Verbose("Client '{0}' accepted by TCP listener '{1}, {2}'.", remoteEndPoint, _localEndPoint, _addressFamily == AddressFamily.InterNetwork ? "ipv4" : "ipv6"); clientSocket.NoDelay = _options.NoDelay; stream = clientSocket.GetStream(); X509Certificate2 clientCertificate = null; if (_tlsCertificate != null) { var sslStream = new SslStream(stream, false, _tlsOptions.RemoteCertificateValidationCallback); await sslStream.AuthenticateAsServerAsync( _tlsCertificate, _tlsOptions.ClientCertificateRequired, _tlsOptions.SslProtocol, _tlsOptions.CheckCertificateRevocation).ConfigureAwait(false); stream = sslStream; clientCertificate = sslStream.RemoteCertificate as X509Certificate2; if (clientCertificate == null && sslStream.RemoteCertificate != null) { clientCertificate = new X509Certificate2(sslStream.RemoteCertificate.Export(X509ContentType.Cert)); } } var clientHandler = ClientHandler; if (clientHandler != null) { using (var clientAdapter = new MqttChannelAdapter( new MqttTcpChannel(stream, remoteEndPoint, clientCertificate), new MqttPacketFormatterAdapter(new MqttPacketWriter()), null, _rootLogger)) { await clientHandler(clientAdapter).ConfigureAwait(false); } } } catch (Exception exception) { if (exception is ObjectDisposedException) { // It can happen that the listener socket is accessed after the cancellation token is already set and the listener socket is disposed. return; } if (exception is SocketException socketException && socketException.SocketErrorCode == SocketError.OperationAborted) { return; } _logger.Error(exception, "Error while handling client connection."); } finally { try { stream?.Dispose(); clientSocket?.Dispose(); } catch (Exception disposeException) { _logger.Error(disposeException, "Error while cleaning up client connection"); } } _logger.Verbose("Client '{0}' disconnected at TCP listener '{1}, {2}'.", remoteEndPoint, _localEndPoint, _addressFamily == AddressFamily.InterNetwork ? "ipv4" : "ipv6"); }
private async Task TryHandleClientConnectionAsync(Socket clientSocket) { Stream stream = null; string remoteEndPoint = null; try { remoteEndPoint = clientSocket.RemoteEndPoint.ToString(); _logger.Verbose("Client '{0}' accepted by TCP listener '{1}, {2}'.", remoteEndPoint, _socket.LocalEndPoint, _addressFamily == AddressFamily.InterNetwork ? "ipv4" : "ipv6"); clientSocket.NoDelay = _options.NoDelay; stream = new NetworkStream(clientSocket, true); if (_tlsCertificate != null) { var sslStream = new SslStream(stream, false); await sslStream.AuthenticateAsServerAsync(_tlsCertificate, false, _tlsOptions.SslProtocol, false).ConfigureAwait(false); stream = sslStream; } var clientHandler = ClientHandler; if (clientHandler != null) { using (var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(stream, remoteEndPoint), new MqttPacketFormatterAdapter(), _logger)) { await clientHandler(clientAdapter).ConfigureAwait(false); } } } catch (Exception exception) { if (exception is ObjectDisposedException) { // It can happen that the listener socket is accessed after the cancellation token is already set and the listener socket is disposed. return; } if (exception is SocketException socketException && socketException.SocketErrorCode == SocketError.OperationAborted) { return; } _logger.Error(exception, "Error while handling client connection."); } finally { try { stream?.Dispose(); clientSocket?.Dispose(); _logger.Verbose("Client '{0}' disconnected at TCP listener '{1}, {2}'.", remoteEndPoint, _socket.LocalEndPoint, _addressFamily == AddressFamily.InterNetwork ? "ipv4" : "ipv6"); } catch (Exception disposeException) { _logger.Error(disposeException, "Error while cleaning up client connection"); } } }
private async Task TryHandleClientConnectionAsync(Socket clientSocket) { var socketIndex = Interlocked.Increment(ref latestSocketIndex); string clientPrefix = null; string serverEndPont = null; SslStream sslStream = null; var stopwatch = new Stopwatch(); try { stopwatch.Start(); clientPrefix = $"Socket[{socketIndex}, {clientSocket.RemoteEndPoint}]"; serverEndPont = string.Format("{0}, {1}, {2}", _socket.LocalEndPoint, _addressFamily == AddressFamily.InterNetwork ? "ipv4" : "ipv6", _tlsCertificate == null ? "tcp" : "tls"); _logger.Verbose($"{clientPrefix} > Accepted by TCP listener '{serverEndPont}'. Time:{stopwatch.Elapsed.TotalMilliseconds}ms"); clientSocket.NoDelay = true; if (_tlsCertificate != null) {//如果不设置超时,AuthenticateAsServerAsync 可能会一直阻塞下去 clientSocket.ReceiveTimeout = (int)_communicationTimeout.TotalMilliseconds; clientSocket.SendTimeout = (int)_communicationTimeout.TotalMilliseconds; var stream = new NetworkStream(clientSocket, true); sslStream = new SslStream(stream, false); var cancellationTokenDisposeSslStream = new CancellationTokenSource(); var taskDisposeSslStream = Task.Delay(_communicationTimeout, cancellationTokenDisposeSslStream.Token) .ContinueWith((task) => { if (task.IsCanceled) { return; } if (cancellationTokenDisposeSslStream.IsCancellationRequested) { return; } //超时,则清理掉 Cleanup(clientSocket, sslStream); }); await sslStream.AuthenticateAsServerAsync(_tlsCertificate, false, _tlsOptions.SslProtocol, false).ConfigureAwait(false); cancellationTokenDisposeSslStream.Cancel(); _logger.Verbose($"{clientPrefix} > SslStream created. Time:{stopwatch.Elapsed.TotalMilliseconds}ms"); } _logger.Verbose($"{clientPrefix} > Processed. Time:{stopwatch.Elapsed.TotalMilliseconds}ms"); if (ClientAccepted != null) { using (var clientAdapter = new MqttChannelAdapter(new MqttTcpChannel(clientSocket, sslStream), new MqttPacketSerializer(), _logger)) { var args = new MqttServerAdapterClientAcceptedEventArgs(clientAdapter); ClientAccepted.Invoke(this, args); await args.SessionTask.ConfigureAwait(false); } } } catch (ObjectDisposedException exception) { // It can happen that the listener socket is accessed after the cancellation token is already set and the listener socket is disposed. _logger.Error(exception, $"{clientPrefix} > Error while handling client connection. Listener:'{serverEndPont}' Time:{stopwatch.Elapsed.TotalMilliseconds}ms Disposed"); } catch (Exception exception) { Cleanup(clientSocket, sslStream); if (exception is SocketException s && s.SocketErrorCode == SocketError.OperationAborted) { _logger.Error(exception, $"{clientPrefix} > Error while handling client connection. Listener:'{serverEndPont}' Time:{stopwatch.Elapsed.TotalMilliseconds}ms OperationAborted"); return; } if (exception is System.IO.IOException ioException) { _logger.Error(exception, $"{clientPrefix} > Error while handling client connection. Listener:'{serverEndPont}' Time:{stopwatch.Elapsed.TotalMilliseconds}ms IOException"); return; } _logger.Error(exception, $"{clientPrefix} > Error while handling client connection. Listener:'{serverEndPont}' Time:{stopwatch.Elapsed.TotalMilliseconds}ms Unknown"); } finally { try { Cleanup(clientSocket, sslStream); _logger.Verbose($"{clientPrefix} > Disconnected at TCP listener '{serverEndPont}'. Time:{stopwatch.Elapsed.TotalMilliseconds}ms"); } catch (Exception disposeException) { _logger.Error(disposeException, $"{clientPrefix} > Error while cleaning up client connection. Listener:'{serverEndPont}' Time:{stopwatch.Elapsed.TotalMilliseconds}ms"); } stopwatch.Stop(); } }
async Task TryHandleClientConnectionAsync(CrossPlatformSocket clientSocket) { Stream stream = null; string remoteEndPoint = null; try { remoteEndPoint = clientSocket.RemoteEndPoint.ToString(); _logger.Verbose("Client '{0}' accepted by TCP listener '{1}, {2}'.", remoteEndPoint, _localEndPoint, _addressFamily == AddressFamily.InterNetwork ? "ipv4" : "ipv6"); clientSocket.NoDelay = _options.NoDelay; stream = clientSocket.GetStream(); X509Certificate2 clientCertificate = null; if (_tlsCertificate != null) { var sslStream = new SslStream(stream, false, _tlsOptions.RemoteCertificateValidationCallback); #if NETCOREAPP3_1 || NET5_0_OR_GREATER await sslStream.AuthenticateAsServerAsync( new SslServerAuthenticationOptions() { ServerCertificate = _tlsCertificate, ClientCertificateRequired = _tlsOptions.ClientCertificateRequired, EnabledSslProtocols = _tlsOptions.SslProtocol, CertificateRevocationCheckMode = _tlsOptions.CheckCertificateRevocation ? X509RevocationMode.Online : X509RevocationMode.NoCheck, EncryptionPolicy = EncryptionPolicy.RequireEncryption, CipherSuitesPolicy = _tlsOptions.CipherSuitesPolicy }).ConfigureAwait(false); #else await sslStream.AuthenticateAsServerAsync( _tlsCertificate, _tlsOptions.ClientCertificateRequired, _tlsOptions.SslProtocol, _tlsOptions.CheckCertificateRevocation).ConfigureAwait(false); #endif stream = sslStream; clientCertificate = sslStream.RemoteCertificate as X509Certificate2; if (clientCertificate == null && sslStream.RemoteCertificate != null) { clientCertificate = new X509Certificate2(sslStream.RemoteCertificate.Export(X509ContentType.Cert)); } } var clientHandler = ClientHandler; if (clientHandler != null) { var tcpChannel = new MqttTcpChannel(stream, remoteEndPoint, clientCertificate); var bufferWriter = new MqttBufferWriter(_serverOptions.WriterBufferSize, _serverOptions.WriterBufferSizeMax); var packetFormatterAdapter = new MqttPacketFormatterAdapter(bufferWriter); using (var clientAdapter = new MqttChannelAdapter(tcpChannel, packetFormatterAdapter, null, _rootLogger)) { await clientHandler(clientAdapter).ConfigureAwait(false); } } } catch (Exception exception) { if (exception is ObjectDisposedException) { // It can happen that the listener socket is accessed after the cancellation token is already set and the listener socket is disposed. return; } if (exception is SocketException socketException && socketException.SocketErrorCode == SocketError.OperationAborted) { return; } _logger.Error(exception, "Error while handling client connection."); } finally { try { stream?.Dispose(); clientSocket?.Dispose(); } catch (Exception disposeException) { _logger.Error(disposeException, "Error while cleaning up client connection"); } } _logger.Verbose("Client '{0}' disconnected at TCP listener '{1}, {2}'.", remoteEndPoint, _localEndPoint, _addressFamily == AddressFamily.InterNetwork ? "ipv4" : "ipv6"); }