* Set IsSessionPresent in CONNACK if client session exists * Set IsSessionPresent in CONNACK if client session exists; - restore white space differences to make comparison easierrelease/3.x.x
@@ -106,9 +106,11 @@ namespace MQTTnet.Server.Internal | |||||
return; | return; | ||||
} | } | ||||
clientConnection = await CreateClientConnection(connectPacket, channelAdapter, connectionValidatorContext.SessionItems).ConfigureAwait(false); | |||||
connAckPacket = channelAdapter.PacketFormatterAdapter.DataConverter.CreateConnAckPacket(connectionValidatorContext); | connAckPacket = channelAdapter.PacketFormatterAdapter.DataConverter.CreateConnAckPacket(connectionValidatorContext); | ||||
// Pass connAckPacket so that IsSessionPresent flag can be set if the client session already exists | |||||
clientConnection = await CreateClientConnection(connectPacket, connAckPacket, channelAdapter, connectionValidatorContext.SessionItems).ConfigureAwait(false); | |||||
await channelAdapter.SendPacketAsync(connAckPacket, cancellationToken).ConfigureAwait(false); | await channelAdapter.SendPacketAsync(connAckPacket, cancellationToken).ConfigureAwait(false); | ||||
await _eventDispatcher.SafeNotifyClientConnectedAsync(connectPacket, channelAdapter).ConfigureAwait(false); | await _eventDispatcher.SafeNotifyClientConnectedAsync(connectPacket, channelAdapter).ConfigureAwait(false); | ||||
@@ -450,7 +452,8 @@ namespace MQTTnet.Server.Internal | |||||
} | } | ||||
async Task<MqttClientConnection> CreateClientConnection( | async Task<MqttClientConnection> CreateClientConnection( | ||||
MqttConnectPacket connectPacket, | |||||
MqttConnectPacket connectPacket, | |||||
MqttConnAckPacket connAckPacket, | |||||
IMqttChannelAdapter channelAdapter, | IMqttChannelAdapter channelAdapter, | ||||
IDictionary<object, object> sessionItems) | IDictionary<object, object> sessionItems) | ||||
{ | { | ||||
@@ -476,6 +479,7 @@ namespace MQTTnet.Server.Internal | |||||
else | else | ||||
{ | { | ||||
_logger.Verbose("Reusing existing session of client '{0}'.", connectPacket.ClientId); | _logger.Verbose("Reusing existing session of client '{0}'.", connectPacket.ClientId); | ||||
connAckPacket.IsSessionPresent = true; | |||||
} | } | ||||
} | } | ||||
@@ -1,4 +1,4 @@ | |||||
using Microsoft.VisualStudio.TestTools.UnitTesting; | |||||
using Microsoft.VisualStudio.TestTools.UnitTesting; | |||||
using MQTTnet.Client; | using MQTTnet.Client; | ||||
using MQTTnet.Client.Options; | using MQTTnet.Client.Options; | ||||
using MQTTnet.Formatter; | using MQTTnet.Formatter; | ||||
@@ -38,5 +38,57 @@ namespace MQTTnet.Tests.MQTTv5 | |||||
Assert.AreEqual(1, receivedMessagesCount); | Assert.AreEqual(1, receivedMessagesCount); | ||||
} | } | ||||
} | } | ||||
[TestMethod] | |||||
public async Task Validate_IsSessionPresent() | |||||
{ | |||||
using (var testEnvironment = new TestEnvironment(TestContext)) | |||||
{ | |||||
// Create server with persistent sessions enabled | |||||
await testEnvironment.StartServer(o => o.WithPersistentSessions()); | |||||
const string ClientId = "Client1"; | |||||
// Create client without clean session and long session expiry interval | |||||
var client1 = await testEnvironment.ConnectClient(o => o | |||||
.WithProtocolVersion(MqttProtocolVersion.V500) | |||||
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort) | |||||
.WithSessionExpiryInterval(9999) | |||||
.WithCleanSession(false) | |||||
.WithClientId(ClientId) | |||||
.Build() | |||||
); | |||||
// Disconnect; empty session should remain on server | |||||
await client1.DisconnectAsync(); | |||||
// Simulate some time delay between connections | |||||
await Task.Delay(1000); | |||||
// Reconnect the same client ID to existing session | |||||
var client2 = testEnvironment.CreateClient(); | |||||
var options = testEnvironment.Factory.CreateClientOptionsBuilder() | |||||
.WithProtocolVersion(MqttProtocolVersion.V500) | |||||
.WithTcpServer("127.0.0.1", testEnvironment.ServerPort) | |||||
.WithSessionExpiryInterval(9999) | |||||
.WithCleanSession(false) | |||||
.WithClientId(ClientId) | |||||
.Build(); | |||||
var result = await client2.ConnectAsync(options).ConfigureAwait(false); | |||||
await client2.DisconnectAsync(); | |||||
// Session should be present | |||||
Assert.IsTrue(result.IsSessionPresent, "Session not present"); | |||||
} | |||||
} | |||||
} | } | ||||
} | } |