diff --git a/Frameworks/MQTTnet.NetFramework/Implementations/MqttTcpChannel.cs b/Frameworks/MQTTnet.NetFramework/Implementations/MqttTcpChannel.cs index c9c080d2..a3b81470 100644 --- a/Frameworks/MQTTnet.NetFramework/Implementations/MqttTcpChannel.cs +++ b/Frameworks/MQTTnet.NetFramework/Implementations/MqttTcpChannel.cs @@ -7,22 +7,33 @@ using System.Threading.Tasks; using MQTTnet.Core.Channel; using MQTTnet.Core.Client; using MQTTnet.Core.Exceptions; +using System.IO; namespace MQTTnet.Implementations { public sealed class MqttTcpChannel : IMqttCommunicationChannel, IDisposable { + private Stream _dataStream; private Socket _socket; private SslStream _sslStream; + /// + /// called on client sockets are created in connect + /// public MqttTcpChannel() { + } + /// + /// called on server, sockets are passed in + /// connect will not be called + /// public MqttTcpChannel(Socket socket, SslStream sslStream) { _socket = socket ?? throw new ArgumentNullException(nameof(socket)); _sslStream = sslStream; + _dataStream = (Stream)sslStream ?? new NetworkStream(socket); } public async Task ConnectAsync(MqttClientOptions options) @@ -40,7 +51,13 @@ namespace MQTTnet.Implementations if (options.TlsOptions.UseTls) { _sslStream = new SslStream(new NetworkStream(_socket, true)); - await _sslStream.AuthenticateAsClientAsync(options.Server, LoadCertificates(options), SslProtocols.Tls12, options.TlsOptions.CheckCertificateRevocation); + + _dataStream = _sslStream; + await _sslStream.AuthenticateAsClientAsync(options.Server, LoadCertificates(options), SslProtocols.Tls12, options.TlsOptions.CheckCertificateRevocation).ConfigureAwait(false); + } + else + { + _dataStream = new NetworkStream(_socket); } } catch (SocketException exception) @@ -68,16 +85,7 @@ namespace MQTTnet.Implementations try { - if (_sslStream != null) - { - return _sslStream.WriteAsync(buffer, 0, buffer.Length); - } - - return Task.Factory.FromAsync( - // ReSharper disable once AssignNullToNotNullAttribute - _socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, null, null), - _socket.EndSend); - + return _dataStream.WriteAsync(buffer, 0, buffer.Length); } catch (SocketException exception) { @@ -85,21 +93,26 @@ namespace MQTTnet.Implementations } } - public Task ReadAsync(byte[] buffer) + public async Task ReadAsync(byte[] buffer) { if (buffer == null) throw new ArgumentNullException(nameof(buffer)); try { - if (_sslStream != null) - { - return _sslStream.ReadAsync(buffer, 0, buffer.Length); - } + int totalBytes = 0; - return Task.Factory.FromAsync( - // ReSharper disable once AssignNullToNotNullAttribute - _socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, null, null), - _socket.EndReceive); + do + { + var read = await _dataStream.ReadAsync(buffer, totalBytes, buffer.Length - totalBytes).ConfigureAwait(false); + + if (read == 0) + { + throw new MqttCommunicationException(new SocketException((int)SocketError.Disconnecting)); + } + + totalBytes += read; + } + while (totalBytes < buffer.Length); } catch (SocketException exception) { diff --git a/Frameworks/MQTTnet.NetStandard/Implementations/MqttTcpChannel.cs b/Frameworks/MQTTnet.NetStandard/Implementations/MqttTcpChannel.cs index a4247b09..8486ca18 100644 --- a/Frameworks/MQTTnet.NetStandard/Implementations/MqttTcpChannel.cs +++ b/Frameworks/MQTTnet.NetStandard/Implementations/MqttTcpChannel.cs @@ -7,22 +7,32 @@ using System.Threading.Tasks; using MQTTnet.Core.Channel; using MQTTnet.Core.Client; using MQTTnet.Core.Exceptions; +using System.IO; namespace MQTTnet.Implementations { public sealed class MqttTcpChannel : IMqttCommunicationChannel, IDisposable { + private Stream _dataStream; private Socket _socket; private SslStream _sslStream; + /// + /// called on client sockets are created in connect + /// public MqttTcpChannel() { } + /// + /// called on server, sockets are passed in + /// connect will not be called + /// public MqttTcpChannel(Socket socket, SslStream sslStream) { _socket = socket ?? throw new ArgumentNullException(nameof(socket)); _sslStream = sslStream; + _dataStream = (Stream)sslStream ?? new NetworkStream(socket); } public async Task ConnectAsync(MqttClientOptions options) @@ -35,12 +45,17 @@ namespace MQTTnet.Implementations _socket = new Socket(SocketType.Stream, ProtocolType.Tcp); } - await _socket.ConnectAsync(options.Server, options.GetPort()); - + await _socket.ConnectAsync(options.Server, options.GetPort()).ConfigureAwait(false); + if (options.TlsOptions.UseTls) { _sslStream = new SslStream(new NetworkStream(_socket, true)); - await _sslStream.AuthenticateAsClientAsync(options.Server, LoadCertificates(options), SslProtocols.Tls12, options.TlsOptions.CheckCertificateRevocation); + _dataStream = _sslStream; + await _sslStream.AuthenticateAsClientAsync(options.Server, LoadCertificates(options), SslProtocols.Tls12, options.TlsOptions.CheckCertificateRevocation).ConfigureAwait(false); + } + else + { + _dataStream = new NetworkStream(_socket); } } catch (SocketException exception) @@ -68,12 +83,7 @@ namespace MQTTnet.Implementations try { - if (_sslStream != null) - { - return _sslStream.WriteAsync(buffer, 0, buffer.Length); - } - - return _socket.SendAsync(new ArraySegment(buffer), SocketFlags.None); + return _dataStream.WriteAsync(buffer, 0, buffer.Length); } catch (SocketException exception) { @@ -81,18 +91,26 @@ namespace MQTTnet.Implementations } } - public Task ReadAsync(byte[] buffer) + public async Task ReadAsync(byte[] buffer) { if (buffer == null) throw new ArgumentNullException(nameof(buffer)); try { - if (_sslStream != null) - { - return _sslStream.ReadAsync(buffer, 0, buffer.Length); - } + int totalBytes = 0; - return _socket.ReceiveAsync(new ArraySegment(buffer), SocketFlags.None); + do + { + var read = await _dataStream.ReadAsync(buffer, totalBytes, buffer.Length - totalBytes).ConfigureAwait(false); + + if (read == 0) + { + throw new MqttCommunicationException(new SocketException((int)SocketError.Disconnecting)); + } + + totalBytes += read; + } + while (totalBytes < buffer.Length); } catch (SocketException exception) {