219 lines
7.0 KiB
Plaintext
219 lines
7.0 KiB
Plaintext
|
|
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<int> IConnection.SendAsync(byte[] sendBuffer, int bufferStartOffset, int bufferSizeToSend)
|
||
|
|
{
|
||
|
|
return Task<int>.Factory.FromAsync(
|
||
|
|
(callback, state) => ((IConnection)this).BeginSend(sendBuffer, bufferStartOffset, bufferSizeToSend, callback, state),
|
||
|
|
((IConnection)this).EndSend, state: null
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
void IConnection.SoftConnect()
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
void IConnection.SoftDisconnect()
|
||
|
|
{
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|