Skip to content

Commit

Permalink
API Proposal: Check Disposed Socket #54
Browse files Browse the repository at this point in the history
  • Loading branch information
chronoxor committed Mar 31, 2020
1 parent d35c2e4 commit 710500a
Show file tree
Hide file tree
Showing 10 changed files with 249 additions and 35 deletions.
2 changes: 1 addition & 1 deletion .appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Specify version format
version: "3.0.7.{build}"
version: "3.0.8.{build}"

# Image to use
image: Visual Studio 2019
Expand Down
2 changes: 1 addition & 1 deletion source/NetCoreServer/NetCoreServer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<Version>3.0.7</Version>
<Version>3.0.8</Version>
<Authors>Ivan Shynkarenka</Authors>
<Copyright>Copyright (c) 2019-2020 Ivan Shynkarenka</Copyright>
<RepositoryUrl>https://github.com/chronoxor/NetCoreServer</RepositoryUrl>
Expand Down
27 changes: 22 additions & 5 deletions source/NetCoreServer/SslClient.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
Expand Down Expand Up @@ -200,12 +199,20 @@ public virtual bool Connect()
}
catch (SocketException ex)
{
// Close the client socket
Socket.Close();
// Dispose the client socket
Socket.Dispose();

// Call the client disconnected handler
SendError(ex.SocketErrorCode);
OnDisconnected();
return false;
}

// Update the client socket disposed flag
IsSocketDisposed = false;

// Apply the option: keep alive
if (OptionKeepAlive)
Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
Expand Down Expand Up @@ -310,6 +317,9 @@ public virtual bool Disconnect()

// Dispose the client socket
Socket.Dispose();

// Update the client socket disposed flag
IsSocketDisposed = true;
}
catch (ObjectDisposedException) {}

Expand Down Expand Up @@ -978,8 +988,15 @@ private void SendError(SocketError error)

#region IDisposable implementation

// Disposed flag.
private bool _disposed;
/// <summary>
/// Disposed flag
/// </summary>
public bool IsDisposed { get; private set; }

/// <summary>
/// Client socket disposed flag
/// </summary>
public bool IsSocketDisposed { get; private set; } = true;

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

if (!_disposed)
if (!IsDisposed)
{
if (disposingManagedResources)
{
Expand All @@ -1015,7 +1032,7 @@ protected virtual void Dispose(bool disposingManagedResources)
// Set large fields to null here...

// Mark as disposed.
_disposed = true;
IsDisposed = true;
}
}

Expand Down
21 changes: 17 additions & 4 deletions source/NetCoreServer/SslServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ public virtual bool Start()
// Create a new acceptor socket
_acceptorSocket = new Socket(Endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

// Update the acceptor socket disposed flag
IsSocketDisposed = false;

// Apply the option: reuse address
_acceptorSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, OptionReuseAddress);
// Apply the option: exclusive address use
Expand Down Expand Up @@ -197,6 +200,9 @@ public virtual bool Stop()
// Dispose the acceptor socket
_acceptorSocket.Dispose();

// Update the acceptor socket disposed flag
IsSocketDisposed = true;

// Disconnect all sessions
DisconnectAll();

Expand Down Expand Up @@ -442,8 +448,15 @@ private void SendError(SocketError error)

#region IDisposable implementation

// Disposed flag.
private bool _disposed;
/// <summary>
/// Disposed flag
/// </summary>
public bool IsDisposed { get; private set; }

/// <summary>
/// Acceptor socket disposed flag
/// </summary>
public bool IsSocketDisposed { get; private set; } = true;

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

if (!_disposed)
if (!IsDisposed)
{
if (disposingManagedResources)
{
Expand All @@ -479,7 +492,7 @@ protected virtual void Dispose(bool disposingManagedResources)
// Set large fields to null here...

// Mark as disposed.
_disposed = true;
IsDisposed = true;
}
}

Expand Down
68 changes: 66 additions & 2 deletions source/NetCoreServer/SslSession.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.IO;
using System.Net.Security;
using System.Net.Sockets;
using System.Text;
Expand All @@ -12,7 +11,7 @@ namespace NetCoreServer
/// SSL session is used to read and write data from the connected SSL client
/// </summary>
/// <remarks>Thread-safe</remarks>
public class SslSession
public class SslSession : IDisposable
{
/// <summary>
/// Initialize the session with a given server
Expand Down Expand Up @@ -125,6 +124,9 @@ internal void Connect(Socket socket)
{
Socket = socket;

// Update the session socket disposed flag
IsSocketDisposed = false;

// Setup buffers
_receiveBuffer = new Buffer();
_sendBufferMain = new Buffer();
Expand Down Expand Up @@ -213,6 +215,9 @@ public virtual bool Disconnect()

// Dispose the session socket
Socket.Dispose();

// Update the session socket disposed flag
IsSocketDisposed = true;
}
catch (ObjectDisposedException) {}

Expand Down Expand Up @@ -751,5 +756,64 @@ private void SendError(SocketError error)
}

#endregion

#region IDisposable implementation

/// <summary>
/// Disposed flag
/// </summary>
public bool IsDisposed { get; private set; }

/// <summary>
/// Session socket disposed flag
/// </summary>
public bool IsSocketDisposed { get; private set; } = true;

// Implement IDisposable.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposingManagedResources)
{
// The idea here is that Dispose(Boolean) knows whether it is
// being called to do explicit cleanup (the Boolean is true)
// versus being called due to a garbage collection (the Boolean
// is false). This distinction is useful because, when being
// disposed explicitly, the Dispose(Boolean) method can safely
// execute code using reference type fields that refer to other
// objects knowing for sure that these other objects have not been
// finalized or disposed of yet. When the Boolean is false,
// the Dispose(Boolean) method should not execute code that
// refer to reference type fields because those objects may
// have already been finalized."

if (!IsDisposed)
{
if (disposingManagedResources)
{
// Dispose managed resources here...
Disconnect();
}

// Dispose unmanaged resources here...

// Set large fields to null here...

// Mark as disposed.
IsDisposed = true;
}
}

// Use C# destructor syntax for finalization code.
~SslSession()
{
// Simply call Dispose(false).
Dispose(false);
}

#endregion
}
}
26 changes: 22 additions & 4 deletions source/NetCoreServer/TcpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,20 @@ public virtual bool Connect()
}
catch (SocketException ex)
{
// Close the client socket
Socket.Close();
// Dispose the client socket
Socket.Dispose();

// Call the client disconnected handler
SendError(ex.SocketErrorCode);
OnDisconnected();
return false;
}

// Update the client socket disposed flag
IsSocketDisposed = false;

// Apply the option: keep alive
if (OptionKeepAlive)
Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
Expand Down Expand Up @@ -246,6 +254,9 @@ public virtual bool Disconnect()

// Dispose the client socket
Socket.Dispose();

// Update the client socket disposed flag
IsSocketDisposed = true;
}
catch (ObjectDisposedException) {}

Expand Down Expand Up @@ -858,8 +869,15 @@ private void SendError(SocketError error)

#region IDisposable implementation

// Disposed flag.
private bool _disposed;
/// <summary>
/// Disposed flag
/// </summary>
public bool IsDisposed { get; private set; }

/// <summary>
/// Client socket disposed flag
/// </summary>
public bool IsSocketDisposed { get; private set; } = true;

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

if (!_disposed)
if (!IsDisposed)
{
if (disposingManagedResources)
{
Expand All @@ -895,7 +913,7 @@ protected virtual void Dispose(bool disposingManagedResources)
// Set large fields to null here...

// Mark as disposed.
_disposed = true;
IsDisposed = true;
}
}

Expand Down
21 changes: 17 additions & 4 deletions source/NetCoreServer/TcpServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ public virtual bool Start()
// Create a new acceptor socket
_acceptorSocket = new Socket(Endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

// Update the acceptor socket disposed flag
IsSocketDisposed = false;

// Apply the option: reuse address
_acceptorSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, OptionReuseAddress);
// Apply the option: exclusive address use
Expand Down Expand Up @@ -188,6 +191,9 @@ public virtual bool Stop()
// Dispose the acceptor socket
_acceptorSocket.Dispose();

// Update the acceptor socket disposed flag
IsSocketDisposed = true;

// Disconnect all sessions
DisconnectAll();

Expand Down Expand Up @@ -427,8 +433,15 @@ private void SendError(SocketError error)

#region IDisposable implementation

// Disposed flag.
private bool _disposed;
/// <summary>
/// Disposed flag
/// </summary>
public bool IsDisposed { get; private set; }

/// <summary>
/// Acceptor socket disposed flag
/// </summary>
public bool IsSocketDisposed { get; private set; } = true;

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

if (!_disposed)
if (!IsDisposed)
{
if (disposingManagedResources)
{
Expand All @@ -464,7 +477,7 @@ protected virtual void Dispose(bool disposingManagedResources)
// Set large fields to null here...

// Mark as disposed.
_disposed = true;
IsDisposed = true;
}
}

Expand Down
Loading

0 comments on commit 710500a

Please sign in to comment.