--- source_files: - Common/DTS.Common.IConnection/EthernetConnection/RESTConnection.cs - Common/DTS.Common.IConnection/EthernetConnection/EthernetConnection.cs generated_at: "2026-04-16T02:09:04.702798+00:00" model: "Qwen/Qwen3-Coder-Next-FP8" schema_version: 1 sha256: "21dfcca726b35e5d" --- # Documentation: `RESTConnection` and `EthernetConnection` Classes ## 1. Purpose This module provides two concrete implementations of the `IConnection` interface for network communication: `RESTConnection`, a stub implementation that simulates connection operations without actual network activity (intended for REST-based or mock scenarios), and `EthernetConnection`, a full-featured implementation using `System.Net.Sockets.Socket` for real-time Ethernet communication with hardware devices. `RESTConnection` exists to satisfy interface contracts in environments where actual socket communication is unnecessary or undesirable (e.g., testing, REST API interactions), while `EthernetConnection` handles real socket operations including connection establishment, data transfer, keep-alive configuration, and soft disconnect/reconnect workflows for embedded hardware. ## 2. Public Interface ### `RESTConnection` (namespace `DTS.DASLib.Connection`) - **`bool IConnection.IsSoftDisconnected => false`** Always returns `false`; does not support soft disconnect semantics. - **`SocketFlags IConnection.Flags { get; set; }`** Gets/sets socket flags (unused; always `SocketFlags.None`). - **`string IConnection.ConnectString => _ConnectString`** Returns the stored connection string (e.g., `"host:port"`), set via `Create`. - **`bool IConnection.Connected => _bConnected`** Returns internal `_bConnected` state (set to `true` on `BeginConnect`, `false` on `BeginDisconnect`). - **`event EventHandler OnDisconnected`** Declared but never raised (no invocation in source). - **`void IConnection.Create(string connectString)`** Stores `connectString` in `_ConnectString`. - **`void IConnection.Create(string connectString, string hostIPAddress)`** Stores `connectString` and `hostIPAddress` in respective fields. - **`IAsyncResult IConnection.BeginConnect(AsyncCallback callback, object callbackObject)`** Sets `_bConnected = true` and returns a *synchronously completed* `IAsyncResult` via `GetAlreadyCompleted`. - **`IAsyncResult IConnection.BeginDisconnect(bool reuseSocket, AsyncCallback callback, object state)`** Sets `_bConnected = false` and returns a *synchronously completed* `IAsyncResult`. - **`IAsyncResult IConnection.BeginSend(...)` / `BeginReceive(...)` / `BeginAccept(...)`** All return *synchronously completed* `IAsyncResult` instances; no actual I/O. - **`void IConnection.EndConnect(...)` / `EndDisconnect(...)` / `EndSend(...)` / `EndReceive(...)` / `EndAccept(...)`** No-op implementations. `EndSend`/`EndReceive` return `0`. `EndAccept` returns `this`. - **`void IConnection.Bind(int port)`** Stub; no-op. - **`void IConnection.Listen(int backlog)`** Stub; no-op. - **`void IConnection.KeepAliveErrorReceived()`** Stub; no-op. - **`string IConnection.GetConnectionData()`** Returns `"{_ConnectString} - {_hostIPAddress}"`. - **`Task IConnection.SendAsync(...)`** Wraps `BeginSend`/`EndSend` using `Task.Factory.FromAsync`; returns a completed task with result `0`. - **`void IConnection.SoftConnect()` / `SoftDisconnect()`** Stubs; no-op. - **`void Dispose()` / `~RESTConnection()`** Implements `IDisposable`; marks `_disposed = true` but performs no socket cleanup. ### `EthernetConnection` (namespace `DTS.Common`) - **`bool IsSoftDisconnected { get; private set; }`** Tracks soft-disconnect state; `true` after successful `SoftDisconnect()`. - **`bool Connected => Sock != null && Sock.Connected`** Reflects underlying socket state. - **`string ConnectString => Connect_String`** Returns stored connection string. - **`SocketFlags Flags { get; set; }`** Gets/sets socket flags used in `BeginSend`/`BeginReceive`. - **`Socket Sock`** Public field holding the underlying `Socket` instance. - **`event EventHandler OnDisconnected`** Raised in `KeepAliveErrorReceived()`. - **`void Create(string connectString, string hostIPAddress)`** Stores `connectString` and `hostIPAddress`, then calls `CreateSock` to initialize `Sock`. - **`Socket CreateSock(string connectString, string hostIPAddress)`** Creates and configures a `Socket` with: - `NoDelay = true` (Nagle disabled) - `KeepAlive = true` - Buffer sizes from `DFConstantsAndEnums.SendBufferSizeBytes` / `ReceiveBufferSizeBytes` - Custom keep-alive parameters from `DFConstantsAndEnums.LocalKeepAliveTimeOutMS` / `LocalKeepAliveRetryIntervalMS` - Optional binding to `hostIPAddress` if provided. - **`void SoftDisconnect()`** If `HardwareConstants.AllowSoftDisconnects` is `true` and socket is connected: - Disconnects and disposes `Sock` - Sets `IsSoftDisconnected = true` - Logs action. - **`void SoftConnect()`** If `AllowSoftDisconnects` is `true` and socket is not connected: - Parses `Connect_String` as `"host:port"`. - If `RequiresKeepAliveReset` is `true`, connects to port `8200`, sends `<60,5,4>`, receives response, then disconnects. - Retries up to 3 times to connect to `host:port` (1s delay between attempts). - Sets `IsSoftDisconnected = false`, logs success. - **`void KeepAliveErrorReceived()`** Shuts down, closes, and disposes `Sock`, sets `Sock = null`, and raises `OnDisconnected`. - **`string GetConnectionData()`** Returns `"local: {LocalEndPoint}, Remote: {RemoteEndPoint}"` or `""` on error. - **`IAsyncResult BeginConnect(AsyncCallback, object)`** Validates `Sock`, `Connect_String`, and port format; delegates to `Sock.BeginConnect`. - **`void EndConnect(IAsyncResult)`** Calls `Sock.EndConnect`, logs connection details. - **`IAsyncResult BeginDisconnect(bool, AsyncCallback, object)`** Validates `Sock`; throws if socket is `null` or *not* connected (`SocketException WSAEISCONN`); delegates to `Sock.BeginDisconnect`. - **`void EndDisconnect(IAsyncResult)`** Calls `Sock.EndDisconnect`. - **`IAsyncResult BeginAccept(AsyncCallback, object)`** Validates `Sock`; delegates to `Sock.BeginAccept`. - **`IConnection EndAccept(IAsyncResult)`** Calls `Sock.EndAccept`, wraps result in a *new* `EthernetConnection` instance. - **`void Bind(int port)`** Validates `Sock`; binds to first DNS-resolved IP address on `port`. - **`void Listen(int backlog)`** Validates `Sock`; calls `Sock.Listen`. - **`IAsyncResult BeginSend(byte[], int, int, AsyncCallback, object)`** Validates `Sock`, callback, and connection state; throws if not connected; delegates to `Sock.BeginSend`. - **`int EndSend(IAsyncResult)`** Calls `Sock.EndSend`; sets `Sock = null` on exception. - **`Task SendAsync(...)`** Wraps `BeginSend`/`EndSend` via `Task.Factory.FromAsync`. - **`IAsyncResult BeginReceive(byte[], int, int, AsyncCallback, object)`** Validates `Sock` and callback; delegates to `Sock.BeginReceive`. - **`int EndReceive(IAsyncResult)`** Calls `Sock.EndReceive`. - **`void Dispose()` / `~EthernetConnection()`** Implements `IDisposable`; safely shuts down/disposes `Sock` in `Dispose(bool)`. ## 3. Invariants - **`RESTConnection`**: - `_bConnected` is the sole source of truth for connection state; never updated by external I/O. - All `Begin*`/`End*` operations are synchronous and return immediately; no async state is maintained. - `IsSoftDisconnected` is always `false`; soft disconnect logic is absent. - `Connected` reflects `_bConnected`, which is manually toggled by `BeginConnect`/`BeginDisconnect`. - **`EthernetConnection`**: - `Connected` depends on `Sock != null && Sock.Connected`; `Sock` may be `null` after errors or disposal. - `SoftDisconnect()` and `SoftConnect()` only execute if `HardwareConstants.AllowSoftDisconnects` is `true`. - `SoftConnect()` requires `Connect_String` to be in `"host:port"` format; port must be parseable as `int`. - `BeginDisconnect` throws `SocketException` if socket is not connected (per `WSAEISCONN`). - `BeginSend`/`BeginReceive` throw if socket is not connected or callback is `null`. - `KeepAliveErrorReceived()` guarantees `Sock` is `null` after execution (disposal path). ## 4. Dependencies ### `RESTConnection`: - **Imports**: - `DTS.Common.Interface.Connection` (for `IConnection`) - `DTS.Common.Utilities.Logging` (for `APILogger`, but *not used* in this file) - Standard .NET libraries (`System.Net.Sockets`, `System.Threading`, etc.) - **Depended on by**: Any code requiring an `IConnection` instance where network activity is unnecessary (e.g., unit tests, REST-based workflows). ### `EthernetConnection`: - **Imports**: - `DTS.Common.Interface.Connection` (`IConnection`) - `DTS.Common.DASResource` (for `Strings.EthernetConnection_*_Err*` exception messages) - `DTS.Common.Enums.DASFactory` (for `HardwareConstants.AllowSoftDisconnects`) - `DTS.Common.Utilities.Logging` (for `APILogger`) - `DFConstantsAndEnums` (for buffer sizes, keep-alive timeouts, `WSAEISCONN`) - **Depended on by**: Higher-level connection management logic (e.g., device initialization, data acquisition pipelines) requiring real Ethernet communication. ## 5. Gotchas - **`RESTConnection`**: - `IsSoftDisconnected` is hardcoded to `false`; callers expecting soft-disconnect behavior will be misled. - `OnDisconnected` is declared but never raised; event subscriptions have no effect. - `Begin*`/`End*` methods are *synchronous stubs*; using them in async contexts may cause deadlocks or incorrect assumptions about I/O latency. - `EndSend`/`EndReceive` always return `0`—no actual bytes sent/received. - `SoftConnect`/`SoftDisconnect` are no-ops despite being part of `IConnection`. - **`EthernetConnection`**: - `SoftConnect()` uses `Thread.Sleep` (50ms/100ms/1000ms) for timing; this is blocking and may cause issues in high-throughput or UI contexts. - `SoftConnect()` sends `<60,5,4>` to port `8200` for keep-alive setup; this is a hardcoded protocol-specific command (device-dependent). - `BeginDisconnect` throws `SocketException` if socket is not connected—*not* an error condition per se, but callers must handle this exception to avoid crashes. - `EndSend` sets `Sock = null` on exception; this may cause subsequent operations to fail unexpectedly. - `Bind` uses the *first* DNS-resolved IP address (`AddressList[0]`), which may be non-deterministic or IPv6 in some environments. - `CreateSock` uses `IOControlCode.KeepAliveValues` with hardcoded `KeepAliveOn = 1`; this may conflict with system-wide settings. - `IsSoftDisconnected` is not reset to `false` in `SoftConnect` if `AllowSoftDisconnects` is `false`—only if soft disconnect logic runs. - **Both**: - Neither class validates `connectString` format in `Create(string)` alone (only in `Create(string, string)` or `BeginConnect`). - `RESTConnection` and `EthernetConnection` share the same `IConnection` interface but have wildly different semantics; callers must know which implementation they hold. - `RESTConnection`’s `GetConnectionData()` returns a string with `_hostIPAddress`, but `_hostIPAddress` is never used in `RESTConnection` beyond storage—no binding or resolution occurs. None identified beyond those above.