Skip to content

Commit 0c2008c

Browse files
authored
Improved Disconnect Error Handling (#176)
1 parent 22d23eb commit 0c2008c

File tree

6 files changed

+134
-114
lines changed

6 files changed

+134
-114
lines changed

Source/HiveMQtt/Client/HiveMQClient.cs

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,8 @@ public async Task<bool> DisconnectAsync(DisconnectOptions? options = null)
197197
}
198198

199199
/// <inheritdoc />
200-
public async Task<PublishResult> PublishAsync(MQTT5PublishMessage message)
200+
public async Task<PublishResult> PublishAsync(MQTT5PublishMessage message, CancellationToken cancellationToken = default)
201201
{
202-
if (!this.IsConnected())
203-
{
204-
throw new HiveMQttClientException("PublishAsync: Client is not connected. Check client.IsConnected() before calling PublishAsync.");
205-
}
206-
207202
message.Validate();
208203

209204
var packetIdentifier = this.GeneratePacketIdentifier();
@@ -227,17 +222,12 @@ public async Task<PublishResult> PublishAsync(MQTT5PublishMessage message)
227222
{
228223
// Wait on the QoS 1 handshake
229224
pubAckPacket = await publishPacket.OnPublishQoS1CompleteTCS.Task
230-
.WaitAsync(TimeSpan.FromMilliseconds(this.Options.ResponseTimeoutInMs))
225+
.WaitAsync(cancellationToken)
231226
.ConfigureAwait(false);
232227
}
233-
catch (TimeoutException)
228+
catch (OperationCanceledException)
234229
{
235-
Logger.Error("PublishAsync: QoS 1 timeout. No PUBACK response received in time.");
236-
var disconnectOptions = new DisconnectOptions
237-
{
238-
ReasonCode = DisconnectReasonCode.UnspecifiedError,
239-
};
240-
await this.DisconnectAsync(disconnectOptions).ConfigureAwait(false);
230+
Logger.Debug("PublishAsync: Operation cancelled by user.");
241231
throw;
242232
}
243233

@@ -255,18 +245,12 @@ public async Task<PublishResult> PublishAsync(MQTT5PublishMessage message)
255245
{
256246
// Wait on the QoS 2 handshake
257247
packetList = await publishPacket.OnPublishQoS2CompleteTCS.Task
258-
.WaitAsync(TimeSpan.FromMilliseconds(this.Options.ResponseTimeoutInMs))
248+
.WaitAsync(cancellationToken)
259249
.ConfigureAwait(false);
260250
}
261-
catch (TimeoutException)
251+
catch (OperationCanceledException)
262252
{
263-
Logger.Error("PublishAsync: QoS 2 timeout. No response received in time.");
264-
265-
var disconnectOptions = new DisconnectOptions
266-
{
267-
ReasonCode = DisconnectReasonCode.UnspecifiedError,
268-
};
269-
await this.DisconnectAsync(disconnectOptions).ConfigureAwait(false);
253+
Logger.Debug("PublishAsync: Operation cancelled by user.");
270254
throw;
271255
}
272256

@@ -278,11 +262,6 @@ public async Task<PublishResult> PublishAsync(MQTT5PublishMessage message)
278262
}
279263
}
280264

281-
if (publishResult is null)
282-
{
283-
throw new HiveMQttClientException("PublishAsync: QoS 2 complete but no PubRec packet received.");
284-
}
285-
286265
return publishResult;
287266
}
288267

@@ -330,11 +309,6 @@ public async Task<SubscribeResult> SubscribeAsync(string topic, QualityOfService
330309
/// <inheritdoc />
331310
public async Task<SubscribeResult> SubscribeAsync(SubscribeOptions options)
332311
{
333-
if (!this.IsConnected())
334-
{
335-
throw new HiveMQttClientException("SubscribeAsync: Client is not connected. Check client.IsConnected() before calling SubscribeAsync.");
336-
}
337-
338312
// Fire the corresponding event
339313
this.BeforeSubscribeEventLauncher(options);
340314

@@ -445,11 +419,6 @@ public async Task<UnsubscribeResult> UnsubscribeAsync(List<Subscription> subscri
445419

446420
public async Task<UnsubscribeResult> UnsubscribeAsync(UnsubscribeOptions unsubOptions)
447421
{
448-
if (!this.IsConnected())
449-
{
450-
throw new HiveMQttClientException("UnsubscribeAsync: Client is not connected. Check client.IsConnected() before calling UnsubscribeAsync.");
451-
}
452-
453422
// Fire the corresponding event
454423
this.BeforeUnsubscribeEventLauncher(unsubOptions.Subscriptions);
455424

@@ -513,6 +482,12 @@ public async Task<UnsubscribeResult> UnsubscribeAsync(UnsubscribeOptions unsubOp
513482
/// <param name="clean">Indicates whether the disconnect was intended or not.</param>
514483
private async Task<bool> HandleDisconnectionAsync(bool clean = true)
515484
{
485+
if (this.ConnectState == ConnectState.Disconnected)
486+
{
487+
Logger.Trace("HandleDisconnection: Already disconnected.");
488+
return false;
489+
}
490+
516491
Logger.Debug($"HandleDisconnection: Handling disconnection. clean={clean}.");
517492

518493
// Cancel all background tasks and close the socket
@@ -537,6 +512,9 @@ private async Task<bool> HandleDisconnectionAsync(bool clean = true)
537512
this.OutgoingPublishQueue.Clear();
538513
}
539514

515+
// Delay for 1 seconds before launching the AfterDisconnect event
516+
await Task.Delay(1000).ConfigureAwait(false);
517+
540518
// Fire the corresponding after event
541519
this.AfterDisconnectEventLauncher(clean);
542520
return true;

Source/HiveMQtt/Client/HiveMQClientSocket.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ private async Task<bool> CreateTLSConnectionAsync(Stream stream)
213213
}
214214
else
215215
{
216-
tlsOptions.RemoteCertificateValidationCallback = HiveMQClient.ValidateServerCertificate;
216+
tlsOptions.RemoteCertificateValidationCallback = ValidateServerCertificate;
217217
}
218218

219219
try

0 commit comments

Comments
 (0)