--- source_files: - Common/DTS.Common.IConnection/EthernetConnection/RESTConnection.cs - Common/DTS.Common.IConnection/EthernetConnection/EthernetConnection.cs generated_at: "2026-04-16T11:48:39.886921+00:00" model: "zai-org/GLM-5-FP8" schema_version: 1 sha256: "21dfcca726b35e5d" --- # Documentation: IConnection Implementations ## 1. Purpose This module provides two implementations of the `IConnection` interface for network communication within the DTS system. `EthernetConnection` is a full TCP socket wrapper that manages asynchronous socket operations, connection lifecycle, and keep-alive configuration for hardware devices. `RESTConnection` is a stub/skeleton implementation that immediately completes all operations without actual network I/O, designed to satisfy the `IConnection` interface contract for scenarios where REST-based communication replaces traditional socket connections. --- ## 2. Public Interface ### EthernetConnection (DTS.Common) #### Properties | Signature | Description | |-----------|-------------| | `bool IsSoftDisconnected { get; private set; }` | Returns `true` if the connection has been soft-disconnected. | | `bool RequiresKeepAliveReset { get; set; }` | When `true`, `SoftConnect()` performs additional handshake on command port 8200 before connecting. | | `Socket Sock` | The underlying `System.Net.Sockets.Socket` instance. Publicly accessible. | | `bool Connected` | Returns `Sock != null && Sock.Connected`. | | `string ConnectString` | Returns the connection string (format: `"host:port"`). | | `SocketFlags Flags { get; set; }` | Socket flags used for send/receive operations. | #### Events | Signature | Description | |-----------|-------------| | `event EventHandler OnDisconnected` | Raised when `KeepAliveErrorReceived()` is invoked, indicating connection loss. | #### Methods | Signature | Description | |-----------|-------------| | `void Create(string connectString, string hostIPAddress)` | Creates and configures the underlying socket with keep-alive settings. Stores connection parameters. | | `Socket CreateSock(string connectString, string hostIPAddress)` | Factory method that creates a configured `Socket` with TCP NoDelay, KeepAlive, and buffer sizes from `DFConstantsAndEnums`. Binds to `hostIPAddress` if provided. | | `void SoftDisconnect()` | If `HardwareConstants.AllowSoftDisconnects` is true, disconnects and disposes the socket, sets `IsSoftDisconnected = true`. | | `void SoftConnect()` | Reconnects a soft-disconnected socket. Optionally performs keep-alive reset via port 8200 if `RequiresKeepAliveReset` is true. Retries connection up to 3 times. | | `void KeepAliveErrorReceived()` | Shuts down, closes, and disposes the socket; invokes `OnDisconnected` event. | | `string GetConnectionData()` | Returns a string with local and remote endpoints, or empty string if unavailable. | | `IAsyncResult BeginConnect(AsyncCallback cb, object state)` | Begins asynchronous connection. Throws if socket is null, `Connect_String` is empty/malformed, or port is invalid. | | `void EndConnect(IAsyncResult ar)` | Completes the connection. Logs success with endpoints. | | `IAsyncResult BeginDisconnect(bool reuseSocket, AsyncCallback cb, object state)` | Begins asynchronous disconnect. Throws `SocketException(WSAEISCONN)` if socket is not connected. | | `void EndDisconnect(IAsyncResult asyncResult)` | Completes the disconnect operation. | | `IAsyncResult BeginAccept(AsyncCallback callback, object state)` | Begins asynchronous accept for incoming connections. | | `IConnection EndAccept(IAsyncResult asyncResult)` | Returns a new `EthernetConnection` wrapping the accepted socket. | | `IAsyncResult BeginSend(byte[] buffer, int offset, int size, AsyncCallback cb, object state)` | Begins asynchronous send. Throws if socket is null, callback is null, or socket is not connected. | | `int EndSend(IAsyncResult ar)` | Completes the send; returns bytes sent. Sets `Sock = null` on exception. | | `Task SendAsync(byte[] sendBuffer, int bufferStartOffset, int bufferSizeToSend)` | Task-based async wrapper over BeginSend/EndSend. | | `IAsyncResult BeginReceive(byte[] buffer, int offset, int size, AsyncCallback cb, object state)` | Begins asynchronous receive. Throws if socket is null or callback is null. | | `int EndReceive(IAsyncResult ar)` | Completes the receive; returns bytes received. | | `void Bind(int port)` | Binds socket to local endpoint resolved via DNS. | | `void Listen(int backlog)` | Starts listening for incoming connections. | | `void Dispose()` | Disposes the socket and resources. | --- ### RESTConnection (DTS.DASLib.Connection) #### Properties | Signature | Description | |-----------|-------------| | `bool IConnection.IsSoftDisconnected` | Always returns `false`. | | `SocketFlags IConnection.Flags { get; set; }` | Stored value, defaults to `SocketFlags.None`. | | `string IConnection.ConnectString` | Returns the stored `_ConnectString`. | | `bool IConnection.Connected` | Returns `_bConnected` (set by `BeginConnect`/`BeginDisconnect`). | #### Events | Signature | Description | |-----------|-------------| | `event EventHandler OnDisconnected` | Defined but never invoked in the source. | #### Methods | Signature | Description | |-----------|-------------| | `void IConnection.Create(string connectString)` | Stores `connectString` in `_ConnectString`. | | `void IConnection.Create(string connectString, string hostIPAddress)` | Stores both parameters in private fields. | | `IAsyncResult IConnection.BeginConnect(AsyncCallback callback, object callbackObject)` | Sets `_bConnected = true`; returns an already-completed `AsyncNoResult`. | | `void IConnection.EndConnect(IAsyncResult ar)` | No-op. | | `IAsyncResult IConnection.BeginDisconnect(bool reuseSocket, AsyncCallback callback, object state)` | Sets `_bConnected = false`; returns an already-completed `AsyncNoResult`. | | `void IConnection.EndDisconnect(IAsyncResult asyncResult)` | No-op. | | `IAsyncResult IConnection.BeginAccept(AsyncCallback callback, object state)` | Returns an already-completed `AsyncNoResult`. | | `IConnection IConnection.EndAccept(IAsyncResult asyncResult)` | Returns `this`. | | `IAsyncResult IConnection.BeginSend(byte[] sendBuffer, int bufferStartOffset, int bufferSizeToSend, AsyncCallback callback, object callbackObject)` | Returns an already-completed `AsyncNoResult`. | | `int IConnection.EndSend(IAsyncResult ar)` | Returns `0`. | | `IAsyncResult IConnection.BeginReceive(byte[] receiveBuffer, int bufferStartOffset, int maxSizeToReceive, AsyncCallback callback, object callbackObject)` | Returns an already-completed `AsyncNoResult`. | | `int IConnection.EndReceive(IAsyncResult ar)` | Returns `0`. | | `Task IConnection.SendAsync(byte[] sendBuffer, int bufferStartOffset, int bufferSizeToSend)` | Task wrapper over BeginSend/EndSend. | | `void IConnection.Bind(int port)` | No-op (commented as "not really needed"). | | `void IConnection.Listen(int backlog)` | No-op. | | `void IConnection.KeepAliveErrorReceived()` | No-op. | | `void IConnection.SoftConnect()` | No-op. | | `void IConnection.SoftDisconnect()` | No-op. | | `string IConnection.GetConnectionData()` | Returns `"$(_ConnectString) - $(_hostIPAddress)"`. | | `void Dispose()` | Standard dispose pattern; no actual resource cleanup. | #### Internal Class: AsyncNoResult An `IAsyncResult` implementation used to represent immediately-completed operations. | Member | Description | |--------|-------------| | `bool IsCompleted` | Returns `true` if `_executionState != PENDING`. | | `WaitHandle AsyncWaitHandle` | Lazily-created `ManualResetEvent`. | | `object AsyncState` | Returns the state object passed to constructor. | | `bool CompletedSynchronously` | Returns `true` if `_executionState == COMPLETED_SYNC`. | | `void SetCompleted(bool completedSync)` | Transitions from PENDING to COMPLETED_SYNC or COMPLETED_ASYNC; invokes callback. Throws `InvalidOperationException` if already completed. | --- ## 3. Invariants ### EthernetConnection - **Connect string format**: Must be `"hostname:port"` where port is a valid integer. Validated in `BeginConnect`. - **Socket creation prerequisite**: `Sock` must be created via `Create()` before calling `BeginConnect`, `BeginSend`, `BeginReceive`, `BeginAccept`, `BeginDisconnect`, `Bind`, or `Listen`. All these methods throw if `Sock` is null. - **Connection state for send**: `BeginSend` throws if `Sock.Connected` is `false`. - **Connection state for disconnect**: `BeginDisconnect` throws `SocketException(DFConstantsAndEnums.WSAEISCONN)` if `Sock.Connected` is `false`. - **Callback requirement**: `BeginSend` and `BeginReceive` throw if callback is null. - **Soft disconnect gate**: `SoftDisconnect()` and `SoftConnect()` do nothing if `HardwareConstants.AllowSoftDisconnects` is `false`. - **Keep-alive configuration**: All sockets created via `CreateSock` have keep-alive enabled with values from `DFConstantsAndEnums.LocalKeepAliveTimeOutMS` and `DFConstantsAndEnums.LocalKeepAliveRetryIntervalMS`. ### RESTConnection - **No actual I/O**: All Begin* methods return immediately with `CompletedSynchronously = true`. - **Send/Receive return zero**: `EndSend` and `EndReceive` always return `0`. - **IsSoftDisconnected**: Always `false`. - **AsyncNoResult state machine**: `SetCompleted` can only be called once; subsequent calls throw `InvalidOperationException`. --- ## 4. Dependencies ### EthernetConnection depends on: - `DTS.Common.Interface.Connection.IConnection` - Interface being implemented. - `DTS.Common.Utilities.Logging.APILogger` - Used for logging throughout. - `DTS.Common.DASResource.DFConstantsAndEnums` - Provides `SendBufferSizeBytes`, `ReceiveBufferSizeBytes`, `LocalKeepAliveTimeOutMS`, `LocalKeepAliveRetryIntervalMS`, `WSAEISCONN`. - `DTS.Common.Enums.DASFactory` - Namespace imported but no direct usage visible in source. - `DTS.Common.Enums.Hardware.HardwareConstants.AllowSoftDisconnects` - Controls soft disconnect behavior. - `System.Net.Sockets.Socket` - Core socket functionality. - `System.Net.Dns`, `System.Net.IPEndPoint`, `System.Net.IPAddress` - Network addressing. ### RESTConnection depends on: - `DTS.Common.Interface.Connection.IConnection` - Interface being implemented. - `DTS.Common.Utilities.Logging` - Namespace imported but no direct usage visible in source. - `System.Net.Sockets.SocketFlags` - Used for the `Flags` property. - `System.Threading` - `ManualResetEvent`, `Interlocked`, `Thread.VolatileRead`. ### What depends on these modules: - Unclear from source alone. Both implement `IConnection`, suggesting consumers depend on that interface rather than concrete types directly. --- ## 5. Gotchas ### EthernetConnection 1. **Dead code in `Create(string connectString)`**: The single-parameter overload contains a commented-out recursive call with the comment `"this is recursive!"`. The method body is effectively empty and does nothing. 2. **Counterintuitive error code in `BeginDisconnect`**: When the socket is *not* connected, `BeginDisconnect` throws `SocketException(WSAEISCONN)`. The constant name suggests "is connected" which is the opposite of the actual condition being checked. 3. **SoftConnect has hardcoded command port logic**: When `RequiresKeepAliveReset` is true, `SoftConnect()` connects to port 8200 and sends `<60,5,4>` before connecting to the actual target port. This appears to be device-specific protocol behavior embedded in the connection class. 4. **Socket is public and mutable**: The `Sock` field is public, allowing external code to modify or replace it, potentially bypassing the class's invariants. 5. **EndSend nullifies socket on exception**: If `EndSend` throws, it sets `Sock = null` before re-throwing. This is not documented and could surprise callers. 6. **Thread.Sleep in SoftConnect/SoftDisconnect**: Both methods use `Thread.Sleep` (50ms and 100ms/1000ms respectively), which blocks the calling thread. ### RESTConnection 1. **No-op implementations**: Most methods do nothing or return immediately. This is by design but could cause confusion if developers expect actual network behavior. 2. **OnDisconnected never raised**: The event is declared but never invoked anywhere in the class. 3. **Namespace mismatch**: The file path suggests `DTS.Common.IConnection` but the namespace is `DTS.DASLib.Connection`. This may indicate a historical refactoring or organizational inconsistency. 4. **Unused imports**: `System.CodeDom`, `System.Collections.Specialized`, `System.Runtime.Remoting.Messaging` are imported but not used in the source.