1212using MQTTnet . Packets ;
1313using System ;
1414using System . Buffers ;
15+ using System . IO ;
1516using System . IO . Pipelines ;
1617using System . Net ;
18+ using System . Net . Sockets ;
19+ using System . Runtime . InteropServices ;
1720using System . Security . Cryptography . X509Certificates ;
1821using System . Threading ;
1922using System . Threading . Tasks ;
@@ -106,8 +109,18 @@ private static bool IsTlsConnection(IHttpContextFeature? _httpContextFeature, IT
106109
107110 public async Task DisconnectAsync ( )
108111 {
109- await _input . CompleteAsync ( ) . ConfigureAwait ( false ) ;
110- await _output . CompleteAsync ( ) . ConfigureAwait ( false ) ;
112+ try
113+ {
114+ await _input . CompleteAsync ( ) . ConfigureAwait ( false ) ;
115+ await _output . CompleteAsync ( ) . ConfigureAwait ( false ) ;
116+ }
117+ catch ( Exception exception )
118+ {
119+ if ( ! WrapAndThrowException ( exception ) )
120+ {
121+ throw ;
122+ }
123+ }
111124 }
112125
113126 public virtual void Dispose ( )
@@ -116,6 +129,29 @@ public virtual void Dispose()
116129 }
117130
118131 public async Task < MqttPacket ? > ReceivePacketAsync ( CancellationToken cancellationToken )
132+ {
133+ try
134+ {
135+ return await ReceivePacketCoreAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
136+ }
137+ catch ( OperationCanceledException )
138+ {
139+ }
140+ catch ( ObjectDisposedException )
141+ {
142+ }
143+ catch ( Exception exception )
144+ {
145+ if ( ! WrapAndThrowException ( exception ) )
146+ {
147+ throw ;
148+ }
149+ }
150+
151+ return null ;
152+ }
153+
154+ private async Task < MqttPacket ? > ReceivePacketCoreAsync ( CancellationToken cancellationToken )
119155 {
120156 try
121157 {
@@ -143,7 +179,7 @@ public virtual void Dispose()
143179 {
144180 if ( ! buffer . IsEmpty )
145181 {
146- if ( PacketFormatterAdapter . TryDecode ( buffer , _packetInspector , out var packet , out consumed , out observed , out var received ) )
182+ if ( PacketFormatterAdapter . TryDecode ( buffer , _packetInspector , out var packet , out consumed , out observed , out var received ) )
147183 {
148184 BytesReceived += received ;
149185
@@ -168,11 +204,11 @@ public virtual void Dispose()
168204 }
169205 }
170206 }
171- catch ( Exception exception )
207+ catch ( Exception )
172208 {
173209 // completing the channel makes sure that there is no more data read after a protocol error
174- _input . Complete ( exception ) ;
175- _output . Complete ( exception ) ;
210+ await _input . CompleteAsync ( ) . ConfigureAwait ( false ) ;
211+ await _output . CompleteAsync ( ) . ConfigureAwait ( false ) ;
176212
177213 throw ;
178214 }
@@ -188,6 +224,21 @@ public void ResetStatistics()
188224 }
189225
190226 public async Task SendPacketAsync ( MqttPacket packet , CancellationToken cancellationToken )
227+ {
228+ try
229+ {
230+ await SendPacketCoreAsync ( packet , cancellationToken ) . ConfigureAwait ( false ) ;
231+ }
232+ catch ( Exception exception )
233+ {
234+ if ( ! WrapAndThrowException ( exception ) )
235+ {
236+ throw ;
237+ }
238+ }
239+ }
240+
241+ private async Task SendPacketCoreAsync ( MqttPacket packet , CancellationToken cancellationToken )
191242 {
192243 using ( await _writerLock . EnterAsync ( cancellationToken ) . ConfigureAwait ( false ) )
193244 {
@@ -241,4 +292,44 @@ static void WritePacketBuffer(PipeWriter output, MqttPacketBuffer buffer)
241292 buffer . Payload . CopyTo ( destination : span . Slice ( offset ) ) ;
242293 output . Advance ( buffer . Length ) ;
243294 }
295+
296+ public static bool WrapAndThrowException ( Exception exception )
297+ {
298+ if ( exception is OperationCanceledException ||
299+ exception is MqttCommunicationTimedOutException ||
300+ exception is MqttCommunicationException ||
301+ exception is MqttProtocolViolationException )
302+ {
303+ return false ;
304+ }
305+
306+ if ( exception is IOException && exception . InnerException is SocketException innerException )
307+ {
308+ exception = innerException ;
309+ }
310+
311+ if ( exception is SocketException socketException )
312+ {
313+ if ( socketException . SocketErrorCode == SocketError . OperationAborted )
314+ {
315+ throw new OperationCanceledException ( ) ;
316+ }
317+
318+ if ( socketException . SocketErrorCode == SocketError . ConnectionAborted )
319+ {
320+ throw new MqttCommunicationException ( socketException ) ;
321+ }
322+ }
323+
324+ if ( exception is COMException comException )
325+ {
326+ const uint ErrorOperationAborted = 0x800703E3 ;
327+ if ( ( uint ) comException . HResult == ErrorOperationAborted )
328+ {
329+ throw new OperationCanceledException ( ) ;
330+ }
331+ }
332+
333+ throw new MqttCommunicationException ( exception ) ;
334+ }
244335}
0 commit comments