using DTS.Common.Interface.Connection; using DTS.Common.Utilities.Logging; using System; using System.CodeDom; using System.Collections.Specialized; using System.Net.Sockets; using System.Runtime.Remoting.Messaging; using System.Threading; using System.Threading.Tasks; namespace DTS.DASLib.Connection { public class RESTConnection : IConnection { bool IConnection.IsSoftDisconnected => false; SocketFlags IConnection.Flags { get; set; } = SocketFlags.None; private string _hostIPAddress = string.Empty; private string _ConnectString = string.Empty; string IConnection.ConnectString => _ConnectString; private bool _bConnected = false; bool IConnection.Connected => _bConnected; public event EventHandler OnDisconnected; internal class AsyncNoResult : IAsyncResult { private readonly AsyncCallback _callback; private readonly object _state; private ManualResetEvent _waitHandle; private const int PENDING = 0; private const int COMPLETED_SYNC = 1; private const int COMPLETED_ASYNC = 2; private int _executionState = PENDING; bool IAsyncResult.IsCompleted => Thread.VolatileRead(ref _executionState) != PENDING; WaitHandle IAsyncResult.AsyncWaitHandle { get { if (_waitHandle == null) { var done = ((IAsyncResult)this).IsCompleted; ManualResetEvent mre = new ManualResetEvent(done); if (Interlocked.CompareExchange(ref _waitHandle, mre, null) != null) { // Another thread created this object's event; dispose // the event we just created mre.Close(); } else { if (!done && ((IAsyncResult)this).IsCompleted) { // If the operation wasn't done when we created // the event but now it is done, set the event _waitHandle.Set(); } } } return _waitHandle; } } object IAsyncResult.AsyncState => _state; bool IAsyncResult.CompletedSynchronously => Thread.VolatileRead(ref _executionState) == COMPLETED_SYNC; public AsyncNoResult(AsyncCallback callback, object state) { _callback = callback; _state = state; } public void SetCompleted(bool completedSync) { var prevState = Interlocked.Exchange(ref _executionState, completedSync ? COMPLETED_SYNC : COMPLETED_ASYNC); if (prevState != PENDING) { throw new InvalidOperationException("Complete called on an operation already complete"); } _waitHandle?.Set(); _callback?.Invoke(this); } } private IAsyncResult GetAlreadyCompleted(AsyncCallback callback, object state) { var result = new AsyncNoResult(callback, state); result.SetCompleted(true); return result; } IAsyncResult IConnection.BeginAccept(AsyncCallback callback, object state) { return GetAlreadyCompleted(callback, state); } IAsyncResult IConnection.BeginConnect(AsyncCallback callback, object callbackObject) { _bConnected = true; //we could check ConnectString and test REST API port return GetAlreadyCompleted(callback, callbackObject); } IAsyncResult IConnection.BeginDisconnect(bool reuseSocket, AsyncCallback callback, object state) { _bConnected = false; return GetAlreadyCompleted(callback, state); } IAsyncResult IConnection.BeginReceive(byte[] receiveBuffer, int bufferStartOffset, int maxSizeToReceive, AsyncCallback callback, object callbackObject) { return GetAlreadyCompleted(callback, callbackObject); } IAsyncResult IConnection.BeginSend(byte[] sendBuffer, int bufferStartOffset, int bufferSizeToSend, AsyncCallback callback, object callbackObject) { return GetAlreadyCompleted(callback, callbackObject); } void IConnection.Bind(int port) { //not really needed } void IConnection.Create(string connectString) { _ConnectString = connectString; } void IConnection.Create(string connectString, string hostIPAddress) { _ConnectString = connectString; _hostIPAddress = hostIPAddress; } private bool _disposed = false; ~RESTConnection() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_disposed) { return; } //do any cleanup of sockets, etc here if disposing is true _disposed = true; } IConnection IConnection.EndAccept(IAsyncResult asyncResult) { //ethernet connection returns a copy, but I'm not sure why return this; } void IConnection.EndConnect(IAsyncResult ar) { } void IConnection.EndDisconnect(IAsyncResult asyncResult) { } int IConnection.EndReceive(IAsyncResult ar) { return 0; } int IConnection.EndSend(IAsyncResult ar) { return 0; } string IConnection.GetConnectionData() { return $"{_ConnectString} - {_hostIPAddress}"; } void IConnection.KeepAliveErrorReceived() { } void IConnection.Listen(int backlog) { } Task IConnection.SendAsync(byte[] sendBuffer, int bufferStartOffset, int bufferSizeToSend) { return Task.Factory.FromAsync( (callback, state) => ((IConnection)this).BeginSend(sendBuffer, bufferStartOffset, bufferSizeToSend, callback, state), ((IConnection)this).EndSend, state: null ); } void IConnection.SoftConnect() { } void IConnection.SoftDisconnect() { } } }