@@ -72,6 +72,14 @@ public int GetConnectionCount(IPAddress ipAddress)
7272 return 0 ;
7373 }
7474
75+ /// <summary>
76+ /// Releases a connection associated with the specified IP address and updates the connection count.
77+ /// </summary>
78+ /// <remarks>Connection removal is deferred and handled by a cleanup timer to avoid race
79+ /// conditions when multiple threads interact with connection state. Immediate removal is not performed to
80+ /// ensure thread safety and prevent premature deletion of connection information.</remarks>
81+ /// <param name="ipAddress">The IP address for which the connection is being released.</param>
82+ /// <param name="info">The connection information object that manages the state and count for the specified IP address.</param>
7583 private void ReleaseConnection ( IPAddress ipAddress , ConnectionInfo info )
7684 {
7785 try
@@ -96,6 +104,13 @@ private void ReleaseConnection(IPAddress ipAddress, ConnectionInfo info)
96104 }
97105 }
98106
107+ /// <summary>
108+ /// Removes expired connection entries from the internal collection.
109+ /// </summary>
110+ /// <remarks>This method is intended to be used as a callback for timer-based cleanup operations.
111+ /// It safely disposes of expired connections and logs any errors encountered during the cleanup process. The
112+ /// method is thread-safe and can be invoked concurrently.</remarks>
113+ /// <param name="state">An optional state object provided by the timer or scheduling mechanism. This parameter is not used.</param>
99114 private void CleanupExpired ( object ? state )
100115 {
101116 try
@@ -130,6 +145,12 @@ private void CleanupExpired(object? state)
130145 }
131146 }
132147
148+ /// <summary>
149+ /// Releases all resources used by the instance and disposes of managed connections and timers.
150+ /// </summary>
151+ /// <remarks>Call this method when the instance is no longer needed to free associated resources
152+ /// promptly. After calling <see cref="Dispose"/>, the instance should not be used. This method is safe to call
153+ /// multiple times; subsequent calls have no effect.</remarks>
133154 public void Dispose ( )
134155 {
135156 if ( _disposed )
@@ -166,21 +187,14 @@ public void Dispose()
166187 /// <summary>
167188 /// Per-IP connection tracking information
168189 /// </summary>
169- internal sealed class ConnectionInfo : IDisposable
190+ internal sealed class ConnectionInfo ( int maxConnections ) : IDisposable
170191 {
171- private readonly int _maxConnections ;
172- private readonly SemaphoreSlim _semaphore ;
192+ private readonly SemaphoreSlim _semaphore = new ( maxConnections , maxConnections ) ;
173193 private readonly ReaderWriterLockSlim _lock = new ( ) ;
174194 private int _activeConnections = 0 ;
175195 private DateTime _lastAccess = DateTime . UtcNow ;
176196 private bool _markedForRemoval = false ;
177197
178- public ConnectionInfo ( int maxConnections )
179- {
180- _maxConnections = maxConnections ;
181- _semaphore = new SemaphoreSlim ( maxConnections , maxConnections ) ;
182- }
183-
184198 public int CurrentCount
185199 {
186200 get
@@ -301,6 +315,11 @@ public bool TryMarkForRemoval()
301315 }
302316 }
303317
318+ /// <summary>
319+ /// Releases all resources used by the current instance.
320+ /// </summary>
321+ /// <remarks>Call this method when you are finished using the instance to free unmanaged
322+ /// resources. After calling Dispose, the instance should not be used.</remarks>
304323 public void Dispose ( )
305324 {
306325 _semaphore ? . Dispose ( ) ;
0 commit comments