@@ -12,6 +12,10 @@ namespace MQTTnet.Implementations | |||
{ | |||
public sealed class MqttTcpChannel : IMqttCommunicationChannel, IDisposable | |||
{ | |||
// ReSharper disable once MemberCanBePrivate.Global | |||
// ReSharper disable once AutoPropertyCanBeMadeGetOnly.Global | |||
public static int BufferSize { get; set; } = 4096 * 20; // Can be changed for fine tuning by library user. | |||
private Socket _socket; | |||
private SslStream _sslStream; | |||
@@ -34,9 +38,9 @@ namespace MQTTnet.Implementations | |||
CreateStreams(socket, sslStream); | |||
} | |||
public Stream RawStream { get; private set; } | |||
public Stream SendStream { get; private set; } | |||
public Stream ReceiveStream { get; private set; } | |||
public Stream RawReceiveStream { get; private set; } | |||
public async Task ConnectAsync(MqttClientOptions options) | |||
{ | |||
@@ -67,8 +71,8 @@ namespace MQTTnet.Implementations | |||
public void Dispose() | |||
{ | |||
RawStream?.Dispose(); | |||
RawStream = null; | |||
RawReceiveStream?.Dispose(); | |||
RawReceiveStream = null; | |||
ReceiveStream?.Dispose(); | |||
ReceiveStream = null; | |||
@@ -85,12 +89,12 @@ namespace MQTTnet.Implementations | |||
private void CreateStreams(Socket socket, Stream sslStream) | |||
{ | |||
RawStream = sslStream ?? new NetworkStream(socket); | |||
RawReceiveStream = sslStream ?? new NetworkStream(socket); | |||
//cannot use this as default buffering prevents from receiving the first connect message | |||
//need two streams otherwise read and write have to be synchronized | |||
SendStream = new BufferedStream(RawStream, BufferConstants.Size); | |||
ReceiveStream = new BufferedStream(RawStream, BufferConstants.Size); | |||
SendStream = new BufferedStream(RawReceiveStream, BufferSize); | |||
ReceiveStream = new BufferedStream(RawReceiveStream, BufferSize); | |||
} | |||
private static X509CertificateCollection LoadCertificates(MqttClientOptions options) | |||
@@ -12,20 +12,32 @@ namespace MQTTnet.Implementations | |||
{ | |||
private ClientWebSocket _webSocket; | |||
public Stream RawStream { get; private set; } | |||
public Stream SendStream => RawStream; | |||
public Stream ReceiveStream => RawStream; | |||
public Stream RawReceiveStream { get; private set; } | |||
public Stream SendStream => RawReceiveStream; | |||
public Stream ReceiveStream => RawReceiveStream; | |||
public async Task ConnectAsync(MqttClientOptions options) | |||
{ | |||
var uri = options.Server; | |||
if (!uri.StartsWith("ws://", StringComparison.OrdinalIgnoreCase)) | |||
{ | |||
uri = "ws://" + uri; | |||
} | |||
if (options.Port.HasValue) | |||
{ | |||
uri += ":" + options.Port; | |||
} | |||
_webSocket = new ClientWebSocket(); | |||
await _webSocket.ConnectAsync(new Uri(options.Server), CancellationToken.None).ConfigureAwait(false); | |||
RawStream = new WebSocketStream(_webSocket); | |||
_webSocket.Options.KeepAliveInterval = options.KeepAlivePeriod; | |||
await _webSocket.ConnectAsync(new Uri(uri), CancellationToken.None).ConfigureAwait(false); | |||
RawReceiveStream = new WebSocketStream(_webSocket); | |||
} | |||
public async Task DisconnectAsync() | |||
{ | |||
RawStream = null; | |||
RawReceiveStream = null; | |||
if (_webSocket == null) | |||
{ | |||
@@ -21,11 +21,9 @@ namespace MQTTnet | |||
switch (options.ConnectionType) | |||
{ | |||
case MqttConnectionType.Tcp: | |||
case MqttConnectionType.Tls: | |||
return new MqttTcpChannel(); | |||
return new MqttTcpChannel(); | |||
case MqttConnectionType.Ws: | |||
case MqttConnectionType.Wss: | |||
return new MqttWebSocketChannel(); | |||
return new MqttWebSocketChannel(); | |||
default: | |||
throw new NotSupportedException(); | |||
@@ -33,10 +33,10 @@ namespace MQTTnet.Implementations | |||
ReceiveStream = (Stream)sslStream ?? new NetworkStream(socket); | |||
} | |||
public Stream ReceiveStream { get; private set; } | |||
public Stream RawStream => ReceiveStream; | |||
public Stream SendStream => ReceiveStream; | |||
public Stream ReceiveStream { get; private set; } | |||
public Stream RawReceiveStream => ReceiveStream; | |||
public async Task ConnectAsync(MqttClientOptions options) | |||
{ | |||
if (options == null) throw new ArgumentNullException(nameof(options)); | |||
@@ -12,20 +12,32 @@ namespace MQTTnet.Implementations | |||
{ | |||
private ClientWebSocket _webSocket; | |||
public Stream SendStream => RawStream; | |||
public Stream ReceiveStream => RawStream; | |||
public Stream RawStream { get; private set; } | |||
public Stream SendStream => RawReceiveStream; | |||
public Stream ReceiveStream => RawReceiveStream; | |||
public Stream RawReceiveStream { get; private set; } | |||
public async Task ConnectAsync(MqttClientOptions options) | |||
{ | |||
var uri = options.Server; | |||
if (!uri.StartsWith("ws://", StringComparison.OrdinalIgnoreCase)) | |||
{ | |||
uri = "ws://" + uri; | |||
} | |||
if (options.Port.HasValue) | |||
{ | |||
uri += ":" + options.Port; | |||
} | |||
_webSocket = new ClientWebSocket(); | |||
await _webSocket.ConnectAsync(new Uri(options.Server), CancellationToken.None); | |||
RawStream = new WebSocketStream(_webSocket); | |||
_webSocket.Options.KeepAliveInterval = options.KeepAlivePeriod; | |||
await _webSocket.ConnectAsync(new Uri(uri), CancellationToken.None); | |||
RawReceiveStream = new WebSocketStream(_webSocket); | |||
} | |||
public async Task DisconnectAsync() | |||
{ | |||
RawStream = null; | |||
RawReceiveStream = null; | |||
if (_webSocket == null) | |||
{ | |||
@@ -21,10 +21,8 @@ namespace MQTTnet | |||
switch (options.ConnectionType) | |||
{ | |||
case MqttConnectionType.Tcp: | |||
case MqttConnectionType.Tls: | |||
return new MqttTcpChannel(); | |||
case MqttConnectionType.Ws: | |||
case MqttConnectionType.Wss: | |||
return new MqttWebSocketChannel(); | |||
default: | |||
@@ -26,7 +26,7 @@ namespace MQTTnet.Implementations | |||
public Stream SendStream { get; private set; } | |||
public Stream ReceiveStream { get; private set; } | |||
public Stream RawStream { get; private set; } | |||
public Stream RawReceiveStream { get; private set; } | |||
public async Task ConnectAsync(MqttClientOptions options) | |||
{ | |||
@@ -56,7 +56,7 @@ namespace MQTTnet.Implementations | |||
ReceiveStream = _socket.InputStream.AsStreamForRead(); | |||
SendStream = _socket.OutputStream.AsStreamForWrite(); | |||
RawStream = ReceiveStream; | |||
RawReceiveStream = ReceiveStream; | |||
} | |||
public Task DisconnectAsync() | |||
@@ -67,8 +67,8 @@ namespace MQTTnet.Implementations | |||
public void Dispose() | |||
{ | |||
RawStream?.Dispose(); | |||
RawStream = null; | |||
RawReceiveStream?.Dispose(); | |||
RawReceiveStream = null; | |||
SendStream?.Dispose(); | |||
SendStream = null; | |||
@@ -12,20 +12,32 @@ namespace MQTTnet.Implementations | |||
{ | |||
private ClientWebSocket _webSocket = new ClientWebSocket(); | |||
public Stream RawStream { get; private set; } | |||
public Stream SendStream => RawStream; | |||
public Stream ReceiveStream => RawStream; | |||
public Stream RawReceiveStream { get; private set; } | |||
public Stream SendStream => RawReceiveStream; | |||
public Stream ReceiveStream => RawReceiveStream; | |||
public async Task ConnectAsync(MqttClientOptions options) | |||
{ | |||
var uri = options.Server; | |||
if (!uri.StartsWith("ws://", StringComparison.OrdinalIgnoreCase)) | |||
{ | |||
uri = "ws://" + uri; | |||
} | |||
if (options.Port.HasValue) | |||
{ | |||
uri += ":" + options.Port; | |||
} | |||
_webSocket = new ClientWebSocket(); | |||
await _webSocket.ConnectAsync(new Uri(options.Server), CancellationToken.None).ConfigureAwait(false); | |||
RawStream = new WebSocketStream(_webSocket); | |||
_webSocket.Options.KeepAliveInterval = options.KeepAlivePeriod; | |||
await _webSocket.ConnectAsync(new Uri(uri), CancellationToken.None).ConfigureAwait(false); | |||
RawReceiveStream = new WebSocketStream(_webSocket); | |||
} | |||
public async Task DisconnectAsync() | |||
{ | |||
RawStream = null; | |||
RawReceiveStream = null; | |||
if (_webSocket == null) | |||
{ | |||
@@ -21,10 +21,8 @@ namespace MQTTnet | |||
switch (options.ConnectionType) | |||
{ | |||
case MqttConnectionType.Tcp: | |||
case MqttConnectionType.Tls: | |||
return new MqttTcpChannel(); | |||
case MqttConnectionType.Ws: | |||
case MqttConnectionType.Wss: | |||
return new MqttWebSocketChannel(); | |||
default: | |||
@@ -9,14 +9,14 @@ namespace MQTTnet.Core.Adapter | |||
{ | |||
public interface IMqttCommunicationAdapter | |||
{ | |||
Task ConnectAsync(MqttClientOptions options, TimeSpan timeout); | |||
IMqttPacketSerializer PacketSerializer { get; } | |||
Task ConnectAsync(TimeSpan timeout, MqttClientOptions options); | |||
Task DisconnectAsync(); | |||
Task DisconnectAsync(TimeSpan timeout); | |||
Task SendPacketsAsync(TimeSpan timeout, IEnumerable<MqttBasePacket> packets); | |||
Task<MqttBasePacket> ReceivePacketAsync(TimeSpan timeout); | |||
IMqttPacketSerializer PacketSerializer { get; } | |||
} | |||
} |
@@ -26,11 +26,11 @@ namespace MQTTnet.Core.Adapter | |||
public IMqttPacketSerializer PacketSerializer { get; } | |||
public async Task ConnectAsync(MqttClientOptions options, TimeSpan timeout) | |||
public async Task ConnectAsync(TimeSpan timeout, MqttClientOptions options) | |||
{ | |||
try | |||
{ | |||
await _channel.ConnectAsync(options).TimeoutAfter(timeout).ConfigureAwait(false); | |||
await _channel.ConnectAsync(options).TimeoutAfter(timeout); | |||
} | |||
catch (MqttCommunicationTimedOutException) | |||
{ | |||
@@ -46,11 +46,11 @@ namespace MQTTnet.Core.Adapter | |||
} | |||
} | |||
public async Task DisconnectAsync() | |||
public async Task DisconnectAsync(TimeSpan timeout) | |||
{ | |||
try | |||
{ | |||
await _channel.DisconnectAsync().ConfigureAwait(false); | |||
await _channel.DisconnectAsync().TimeoutAfter(timeout).ConfigureAwait(false); | |||
} | |||
catch (MqttCommunicationTimedOutException) | |||
{ | |||
@@ -113,7 +113,7 @@ namespace MQTTnet.Core.Adapter | |||
ReceivedMqttPacket receivedMqttPacket; | |||
if (timeout > TimeSpan.Zero) | |||
{ | |||
receivedMqttPacket = await ReceiveAsync(_channel.RawStream).TimeoutAfter(timeout).ConfigureAwait(false); | |||
receivedMqttPacket = await ReceiveAsync(_channel.RawReceiveStream).TimeoutAfter(timeout).ConfigureAwait(false); | |||
} | |||
else | |||
{ | |||
@@ -1,7 +0,0 @@ | |||
namespace MQTTnet.Core.Channel | |||
{ | |||
public static class BufferConstants | |||
{ | |||
public const int Size = 4096 * 20; | |||
} | |||
} |
@@ -6,14 +6,11 @@ namespace MQTTnet.Core.Channel | |||
{ | |||
public interface IMqttCommunicationChannel | |||
{ | |||
Task ConnectAsync(MqttClientOptions options); | |||
Task DisconnectAsync(); | |||
Stream SendStream { get; } | |||
Stream ReceiveStream { get; } | |||
Stream RawReceiveStream { get; } | |||
Stream RawStream { get; } | |||
Task ConnectAsync(MqttClientOptions options); | |||
Task DisconnectAsync(); | |||
} | |||
} |
@@ -53,7 +53,7 @@ namespace MQTTnet.Core.Client | |||
{ | |||
_disconnectedEventSuspended = false; | |||
await _adapter.ConnectAsync(_options, _options.DefaultCommunicationTimeout).ConfigureAwait(false); | |||
await _adapter.ConnectAsync(_options.DefaultCommunicationTimeout, _options).ConfigureAwait(false); | |||
MqttTrace.Verbose(nameof(MqttClient), "Connection with server established."); | |||
@@ -220,7 +220,7 @@ namespace MQTTnet.Core.Client | |||
{ | |||
try | |||
{ | |||
await _adapter.DisconnectAsync(); | |||
await _adapter.DisconnectAsync(_options.DefaultCommunicationTimeout).ConfigureAwait(false); | |||
} | |||
catch (Exception exception) | |||
{ | |||
@@ -3,8 +3,6 @@ | |||
public enum MqttConnectionType | |||
{ | |||
Tcp, | |||
Tls, | |||
Ws, | |||
Wss | |||
Ws | |||
} | |||
} |
@@ -56,7 +56,7 @@ namespace MQTTnet.Core.Server | |||
{ | |||
if (_pendingPublishPackets.Count == 0) | |||
{ | |||
await Task.Delay(TimeSpan.FromMilliseconds(5)).ConfigureAwait(false); | |||
await Task.Delay(TimeSpan.FromMilliseconds(5), cancellationToken).ConfigureAwait(false); | |||
continue; | |||
} | |||
@@ -71,7 +71,7 @@ namespace MQTTnet.Core.Server | |||
foreach (var publishPacket in packets) | |||
{ | |||
publishPacket.Dup = true; | |||
_pendingPublishPackets.Add(publishPacket); | |||
_pendingPublishPackets.Add(publishPacket, cancellationToken); | |||
} | |||
} | |||
catch (Exception exception) | |||
@@ -80,7 +80,7 @@ namespace MQTTnet.Core.Server | |||
foreach (var publishPacket in packets) | |||
{ | |||
publishPacket.Dup = true; | |||
_pendingPublishPackets.Add(publishPacket); | |||
_pendingPublishPackets.Add(publishPacket, cancellationToken); | |||
} | |||
} | |||
} | |||
@@ -64,7 +64,7 @@ namespace MQTTnet.Core.Server | |||
} | |||
finally | |||
{ | |||
await eventArgs.ClientAdapter.DisconnectAsync().ConfigureAwait(false); | |||
await eventArgs.ClientAdapter.DisconnectAsync(_options.DefaultCommunicationTimeout).ConfigureAwait(false); | |||
} | |||
} | |||
@@ -394,7 +394,7 @@ namespace MQTTnet.Core.Tests | |||
public Stream ReceiveStream => _stream; | |||
public Stream RawStream => _stream; | |||
public Stream RawReceiveStream => _stream; | |||
public Stream SendStream => _stream; | |||
@@ -18,12 +18,12 @@ namespace MQTTnet.Core.Tests | |||
public IMqttPacketSerializer PacketSerializer { get; } = new MqttPacketSerializer(); | |||
public Task ConnectAsync(MqttClientOptions options, TimeSpan timeout) | |||
public Task ConnectAsync(TimeSpan timeout, MqttClientOptions options) | |||
{ | |||
return Task.FromResult(0); | |||
} | |||
public Task DisconnectAsync() | |||
public Task DisconnectAsync(TimeSpan timeout) | |||
{ | |||
return Task.FromResult(0); | |||
} | |||
@@ -47,7 +47,7 @@ namespace MQTTnet.Core.Tests | |||
return Task.Run(() => _incomingPackets.Take()); | |||
} | |||
public IEnumerable<MqttBasePacket> ReceivePackets( CancellationToken cancellationToken ) | |||
public IEnumerable<MqttBasePacket> ReceivePackets(CancellationToken cancellationToken) | |||
{ | |||
return _incomingPackets.GetConsumingEnumerable(); | |||
} | |||
@@ -113,16 +113,16 @@ namespace MQTTnet.TestApp.NetFramework | |||
.Select(i => CreateMessage()) | |||
.ToList(); | |||
if (false) | |||
{ | |||
//send concurrent (test for raceconditions) | |||
var sendTasks = msgs | |||
.Select(msg => PublishSingleMessage(client, msg, ref msgCount)) | |||
.ToList(); | |||
await Task.WhenAll(sendTasks); | |||
} | |||
else | |||
////if (false) | |||
////{ | |||
//// //send concurrent (test for raceconditions) | |||
//// var sendTasks = msgs | |||
//// .Select(msg => PublishSingleMessage(client, msg, ref msgCount)) | |||
//// .ToList(); | |||
//// await Task.WhenAll(sendTasks); | |||
////} | |||
////else | |||
{ | |||
await client.PublishAsync(msgs); | |||
msgCount += msgs.Count; | |||
@@ -18,7 +18,7 @@ | |||
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> | |||
<WindowsXamlEnableOverview>true</WindowsXamlEnableOverview> | |||
<PackageCertificateKeyFile>MQTTnet.TestApp.UniversalWindows_TemporaryKey.pfx</PackageCertificateKeyFile> | |||
<PackageCertificateThumbprint>C5051872F588878B167FB976FDF249518AA2DDF0</PackageCertificateThumbprint> | |||
<PackageCertificateThumbprint>13E377A693C923EE9E88EE84B32A4B9881657362</PackageCertificateThumbprint> | |||
<RuntimeIdentifiers>win10;win10-arm;win10-arm-aot;win10-x86;win10-x86-aot;win10-x64;win10-x64-aot</RuntimeIdentifiers> | |||
</PropertyGroup> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> | |||
@@ -24,6 +24,11 @@ | |||
<TextBlock>ClientId:</TextBlock> | |||
<TextBox x:Name="ClientId"></TextBox> | |||
<StackPanel Orientation="Horizontal"> | |||
<RadioButton x:Name="UseTcp" IsChecked="True">TCP</RadioButton> | |||
<RadioButton x:Name="UseWs" >WS</RadioButton> | |||
</StackPanel> | |||
<CheckBox x:Name="UseTls">Use TLS</CheckBox> | |||
<Button Click="Connect">Connect</Button> | |||
<TextBlock>Trace:</TextBlock> | |||
@@ -1,4 +1,5 @@ | |||
using System; | |||
using System.Threading.Tasks; | |||
using Windows.UI.Core; | |||
using Windows.UI.Xaml; | |||
using MQTTnet.Core.Client; | |||
@@ -40,7 +41,7 @@ namespace MQTTnet.TestApp.UniversalWindows | |||
Password = Password.Text, | |||
ClientId = ClientId.Text, | |||
TlsOptions = { UseTls = UseTls.IsChecked == true }, | |||
ConnectionType = MqttConnectionType.Ws | |||
ConnectionType = UseTcp.IsChecked == true ? MqttConnectionType.Tcp : MqttConnectionType.Ws | |||
}; | |||
try | |||
@@ -1,5 +1,5 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp"> | |||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3" IgnorableNamespaces="uap mp uap3"> | |||
<Identity Name="4fa21172-9128-4e84-8a6d-74b9acde4d58" Publisher="CN=Christian" Version="1.0.0.0" /> | |||
<mp:PhoneIdentity PhoneProductId="4fa21172-9128-4e84-8a6d-74b9acde4d58" PhonePublisherId="00000000-0000-0000-0000-000000000000" /> | |||
<Properties> | |||
@@ -24,5 +24,7 @@ | |||
</Applications> | |||
<Capabilities> | |||
<Capability Name="internetClient" /> | |||
<Capability Name="internetClientServer" /> | |||
<Capability Name="privateNetworkClientServer" /> | |||
</Capabilities> | |||
</Package> |