Skip to content

Commit 710500a

Browse files
committed
API Proposal: Check Disposed Socket #54
1 parent d35c2e4 commit 710500a

File tree

10 files changed

+249
-35
lines changed

10 files changed

+249
-35
lines changed

.appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Specify version format
2-
version: "3.0.7.{build}"
2+
version: "3.0.8.{build}"
33

44
# Image to use
55
image: Visual Studio 2019

source/NetCoreServer/NetCoreServer.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>netstandard2.1</TargetFramework>
5-
<Version>3.0.7</Version>
5+
<Version>3.0.8</Version>
66
<Authors>Ivan Shynkarenka</Authors>
77
<Copyright>Copyright (c) 2019-2020 Ivan Shynkarenka</Copyright>
88
<RepositoryUrl>https://github.com/chronoxor/NetCoreServer</RepositoryUrl>

source/NetCoreServer/SslClient.cs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.IO;
32
using System.Net;
43
using System.Net.Security;
54
using System.Net.Sockets;
@@ -200,12 +199,20 @@ public virtual bool Connect()
200199
}
201200
catch (SocketException ex)
202201
{
202+
// Close the client socket
203+
Socket.Close();
204+
// Dispose the client socket
205+
Socket.Dispose();
206+
203207
// Call the client disconnected handler
204208
SendError(ex.SocketErrorCode);
205209
OnDisconnected();
206210
return false;
207211
}
208212

213+
// Update the client socket disposed flag
214+
IsSocketDisposed = false;
215+
209216
// Apply the option: keep alive
210217
if (OptionKeepAlive)
211218
Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
@@ -310,6 +317,9 @@ public virtual bool Disconnect()
310317

311318
// Dispose the client socket
312319
Socket.Dispose();
320+
321+
// Update the client socket disposed flag
322+
IsSocketDisposed = true;
313323
}
314324
catch (ObjectDisposedException) {}
315325

@@ -978,8 +988,15 @@ private void SendError(SocketError error)
978988

979989
#region IDisposable implementation
980990

981-
// Disposed flag.
982-
private bool _disposed;
991+
/// <summary>
992+
/// Disposed flag
993+
/// </summary>
994+
public bool IsDisposed { get; private set; }
995+
996+
/// <summary>
997+
/// Client socket disposed flag
998+
/// </summary>
999+
public bool IsSocketDisposed { get; private set; } = true;
9831000

9841001
// Implement IDisposable.
9851002
public void Dispose()
@@ -1002,7 +1019,7 @@ protected virtual void Dispose(bool disposingManagedResources)
10021019
// refer to reference type fields because those objects may
10031020
// have already been finalized."
10041021

1005-
if (!_disposed)
1022+
if (!IsDisposed)
10061023
{
10071024
if (disposingManagedResources)
10081025
{
@@ -1015,7 +1032,7 @@ protected virtual void Dispose(bool disposingManagedResources)
10151032
// Set large fields to null here...
10161033

10171034
// Mark as disposed.
1018-
_disposed = true;
1035+
IsDisposed = true;
10191036
}
10201037
}
10211038

source/NetCoreServer/SslServer.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ public virtual bool Start()
145145
// Create a new acceptor socket
146146
_acceptorSocket = new Socket(Endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
147147

148+
// Update the acceptor socket disposed flag
149+
IsSocketDisposed = false;
150+
148151
// Apply the option: reuse address
149152
_acceptorSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, OptionReuseAddress);
150153
// Apply the option: exclusive address use
@@ -197,6 +200,9 @@ public virtual bool Stop()
197200
// Dispose the acceptor socket
198201
_acceptorSocket.Dispose();
199202

203+
// Update the acceptor socket disposed flag
204+
IsSocketDisposed = true;
205+
200206
// Disconnect all sessions
201207
DisconnectAll();
202208

@@ -442,8 +448,15 @@ private void SendError(SocketError error)
442448

443449
#region IDisposable implementation
444450

445-
// Disposed flag.
446-
private bool _disposed;
451+
/// <summary>
452+
/// Disposed flag
453+
/// </summary>
454+
public bool IsDisposed { get; private set; }
455+
456+
/// <summary>
457+
/// Acceptor socket disposed flag
458+
/// </summary>
459+
public bool IsSocketDisposed { get; private set; } = true;
447460

448461
// Implement IDisposable.
449462
public void Dispose()
@@ -466,7 +479,7 @@ protected virtual void Dispose(bool disposingManagedResources)
466479
// refer to reference type fields because those objects may
467480
// have already been finalized."
468481

469-
if (!_disposed)
482+
if (!IsDisposed)
470483
{
471484
if (disposingManagedResources)
472485
{
@@ -479,7 +492,7 @@ protected virtual void Dispose(bool disposingManagedResources)
479492
// Set large fields to null here...
480493

481494
// Mark as disposed.
482-
_disposed = true;
495+
IsDisposed = true;
483496
}
484497
}
485498

source/NetCoreServer/SslSession.cs

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.IO;
32
using System.Net.Security;
43
using System.Net.Sockets;
54
using System.Text;
@@ -12,7 +11,7 @@ namespace NetCoreServer
1211
/// SSL session is used to read and write data from the connected SSL client
1312
/// </summary>
1413
/// <remarks>Thread-safe</remarks>
15-
public class SslSession
14+
public class SslSession : IDisposable
1615
{
1716
/// <summary>
1817
/// Initialize the session with a given server
@@ -125,6 +124,9 @@ internal void Connect(Socket socket)
125124
{
126125
Socket = socket;
127126

127+
// Update the session socket disposed flag
128+
IsSocketDisposed = false;
129+
128130
// Setup buffers
129131
_receiveBuffer = new Buffer();
130132
_sendBufferMain = new Buffer();
@@ -213,6 +215,9 @@ public virtual bool Disconnect()
213215

214216
// Dispose the session socket
215217
Socket.Dispose();
218+
219+
// Update the session socket disposed flag
220+
IsSocketDisposed = true;
216221
}
217222
catch (ObjectDisposedException) {}
218223

@@ -751,5 +756,64 @@ private void SendError(SocketError error)
751756
}
752757

753758
#endregion
759+
760+
#region IDisposable implementation
761+
762+
/// <summary>
763+
/// Disposed flag
764+
/// </summary>
765+
public bool IsDisposed { get; private set; }
766+
767+
/// <summary>
768+
/// Session socket disposed flag
769+
/// </summary>
770+
public bool IsSocketDisposed { get; private set; } = true;
771+
772+
// Implement IDisposable.
773+
public void Dispose()
774+
{
775+
Dispose(true);
776+
GC.SuppressFinalize(this);
777+
}
778+
779+
protected virtual void Dispose(bool disposingManagedResources)
780+
{
781+
// The idea here is that Dispose(Boolean) knows whether it is
782+
// being called to do explicit cleanup (the Boolean is true)
783+
// versus being called due to a garbage collection (the Boolean
784+
// is false). This distinction is useful because, when being
785+
// disposed explicitly, the Dispose(Boolean) method can safely
786+
// execute code using reference type fields that refer to other
787+
// objects knowing for sure that these other objects have not been
788+
// finalized or disposed of yet. When the Boolean is false,
789+
// the Dispose(Boolean) method should not execute code that
790+
// refer to reference type fields because those objects may
791+
// have already been finalized."
792+
793+
if (!IsDisposed)
794+
{
795+
if (disposingManagedResources)
796+
{
797+
// Dispose managed resources here...
798+
Disconnect();
799+
}
800+
801+
// Dispose unmanaged resources here...
802+
803+
// Set large fields to null here...
804+
805+
// Mark as disposed.
806+
IsDisposed = true;
807+
}
808+
}
809+
810+
// Use C# destructor syntax for finalization code.
811+
~SslSession()
812+
{
813+
// Simply call Dispose(false).
814+
Dispose(false);
815+
}
816+
817+
#endregion
754818
}
755819
}

source/NetCoreServer/TcpClient.cs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,20 @@ public virtual bool Connect()
177177
}
178178
catch (SocketException ex)
179179
{
180+
// Close the client socket
181+
Socket.Close();
182+
// Dispose the client socket
183+
Socket.Dispose();
184+
180185
// Call the client disconnected handler
181186
SendError(ex.SocketErrorCode);
182187
OnDisconnected();
183188
return false;
184189
}
185190

191+
// Update the client socket disposed flag
192+
IsSocketDisposed = false;
193+
186194
// Apply the option: keep alive
187195
if (OptionKeepAlive)
188196
Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
@@ -246,6 +254,9 @@ public virtual bool Disconnect()
246254

247255
// Dispose the client socket
248256
Socket.Dispose();
257+
258+
// Update the client socket disposed flag
259+
IsSocketDisposed = true;
249260
}
250261
catch (ObjectDisposedException) {}
251262

@@ -858,8 +869,15 @@ private void SendError(SocketError error)
858869

859870
#region IDisposable implementation
860871

861-
// Disposed flag.
862-
private bool _disposed;
872+
/// <summary>
873+
/// Disposed flag
874+
/// </summary>
875+
public bool IsDisposed { get; private set; }
876+
877+
/// <summary>
878+
/// Client socket disposed flag
879+
/// </summary>
880+
public bool IsSocketDisposed { get; private set; } = true;
863881

864882
// Implement IDisposable.
865883
public void Dispose()
@@ -882,7 +900,7 @@ protected virtual void Dispose(bool disposingManagedResources)
882900
// refer to reference type fields because those objects may
883901
// have already been finalized."
884902

885-
if (!_disposed)
903+
if (!IsDisposed)
886904
{
887905
if (disposingManagedResources)
888906
{
@@ -895,7 +913,7 @@ protected virtual void Dispose(bool disposingManagedResources)
895913
// Set large fields to null here...
896914

897915
// Mark as disposed.
898-
_disposed = true;
916+
IsDisposed = true;
899917
}
900918
}
901919

source/NetCoreServer/TcpServer.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ public virtual bool Start()
136136
// Create a new acceptor socket
137137
_acceptorSocket = new Socket(Endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
138138

139+
// Update the acceptor socket disposed flag
140+
IsSocketDisposed = false;
141+
139142
// Apply the option: reuse address
140143
_acceptorSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, OptionReuseAddress);
141144
// Apply the option: exclusive address use
@@ -188,6 +191,9 @@ public virtual bool Stop()
188191
// Dispose the acceptor socket
189192
_acceptorSocket.Dispose();
190193

194+
// Update the acceptor socket disposed flag
195+
IsSocketDisposed = true;
196+
191197
// Disconnect all sessions
192198
DisconnectAll();
193199

@@ -427,8 +433,15 @@ private void SendError(SocketError error)
427433

428434
#region IDisposable implementation
429435

430-
// Disposed flag.
431-
private bool _disposed;
436+
/// <summary>
437+
/// Disposed flag
438+
/// </summary>
439+
public bool IsDisposed { get; private set; }
440+
441+
/// <summary>
442+
/// Acceptor socket disposed flag
443+
/// </summary>
444+
public bool IsSocketDisposed { get; private set; } = true;
432445

433446
// Implement IDisposable.
434447
public void Dispose()
@@ -451,7 +464,7 @@ protected virtual void Dispose(bool disposingManagedResources)
451464
// refer to reference type fields because those objects may
452465
// have already been finalized."
453466

454-
if (!_disposed)
467+
if (!IsDisposed)
455468
{
456469
if (disposingManagedResources)
457470
{
@@ -464,7 +477,7 @@ protected virtual void Dispose(bool disposingManagedResources)
464477
// Set large fields to null here...
465478

466479
// Mark as disposed.
467-
_disposed = true;
480+
IsDisposed = true;
468481
}
469482
}
470483

0 commit comments

Comments
 (0)