init
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{E08382C1-F0B4-44C4-9676-C32FD442228A}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>DTS.DASLib.Connection</RootNamespace>
|
||||
<AssemblyName>EthernetConnection</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<TargetFrameworkProfile />
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<SccProjectName>
|
||||
</SccProjectName>
|
||||
<SccLocalPath>
|
||||
</SccLocalPath>
|
||||
<SccAuxPath>
|
||||
</SccAuxPath>
|
||||
<SccProvider>
|
||||
</SccProvider>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<NoWarn>0067</NoWarn>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="EthernetConnection.cs" />
|
||||
<Compile Include="RESTConnection.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Windows Installer 3.1</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\DTS.Common.DASResource\DTS.Common.DASResource.csproj">
|
||||
<Project>{f621ce48-bb4b-4cfc-a325-9410b721cc44}</Project>
|
||||
<Name>DTS.Common.DASResource</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\DTS.Common.Utilities\DTS.Common.Utilities.csproj">
|
||||
<Project>{d6da1b74-c711-43c2-91b1-1908a8d04dbf}</Project>
|
||||
<Name>DTS.Common.Utilities</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\DTS.Common\DTS.Common.csproj">
|
||||
<Project>{f7a0804f-61a4-40ae-83d0-f1137622b592}</Project>
|
||||
<Name>DTS.Common</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Design\DTS.Common.EthernetConnectionClassDiagram.cd" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ClassDiagram MajorVersion="1" MinorVersion="1">
|
||||
<Class Name="DTS.Common.EthernetConnection" Collapsed="true">
|
||||
<Position X="0.5" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAQxAJEACCUTEgIAAoQJAKAgAggAEAgBAAAggBAIEA=</HashCode>
|
||||
<FileName>EthernetConnection.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Font Name="Segoe UI" Size="9" />
|
||||
</ClassDiagram>
|
||||
@@ -0,0 +1,452 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
using DTS.Common.DASResource;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using DTS.Common.Interface.Connection;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
|
||||
namespace DTS.Common
|
||||
{
|
||||
public class EthernetConnection : IConnection
|
||||
{
|
||||
/// <summary>
|
||||
/// returns true if the unit is soft disconnected
|
||||
/// </summary>
|
||||
public bool IsSoftDisconnected { get; private set; } = false;
|
||||
/// <summary>
|
||||
/// soft disconnects the unit, kills the socket and disposes it
|
||||
/// </summary>
|
||||
public void SoftDisconnect()
|
||||
{
|
||||
if (!Enums.Hardware.HardwareConstants.AllowSoftDisconnects) { return; }
|
||||
if (Sock.Connected)
|
||||
{
|
||||
Sock.Disconnect(false);
|
||||
Sock.Dispose();
|
||||
IsSoftDisconnected = true;
|
||||
APILogger.Log($"SoftDisconnect {ConnectString}");
|
||||
System.Threading.Thread.Sleep(50);
|
||||
}
|
||||
else
|
||||
{
|
||||
APILogger.Log($"SoftDisconnect denied {ConnectString}");
|
||||
}
|
||||
}
|
||||
|
||||
public bool RequiresKeepAliveReset { get; set; } = false;
|
||||
/// <summary>
|
||||
/// soft connects the unit
|
||||
/// </summary>
|
||||
public void SoftConnect()
|
||||
{
|
||||
if (!Enums.Hardware.HardwareConstants.AllowSoftDisconnects) { return; }
|
||||
if (Sock.Connected)
|
||||
{
|
||||
APILogger.Log($"SoftConnect denied {ConnectString}");
|
||||
return;
|
||||
}
|
||||
|
||||
var parameters = Connect_String.Split(':');
|
||||
//create and setup socket
|
||||
Create(Connect_String, _hostIPAddress);
|
||||
|
||||
if (RequiresKeepAliveReset)
|
||||
{
|
||||
APILogger.Log("SoftConnect connecting to HB");
|
||||
//before we connect to the socket we must talk to the command port and setup
|
||||
//keep alive
|
||||
var sock2 = CreateSock(ConnectString, _hostIPAddress);
|
||||
sock2.Connect(parameters[0], 8200);
|
||||
|
||||
var msg = "<60,5,4>";
|
||||
sock2.Send(System.Text.Encoding.ASCII.GetBytes(msg));
|
||||
System.Threading.Thread.Sleep(100);
|
||||
var bytes = new byte[1024];
|
||||
sock2.Receive(bytes);
|
||||
sock2.Disconnect(false);
|
||||
sock2.Dispose();
|
||||
//we're done with the command port, go connect to the actual device port
|
||||
}
|
||||
|
||||
int attempt = 0;
|
||||
while (attempt < 3)
|
||||
{
|
||||
attempt++;
|
||||
try
|
||||
{
|
||||
Sock.Connect(parameters[0], Convert.ToInt32(parameters[1]));
|
||||
attempt = 4;//break out
|
||||
}
|
||||
catch (SocketException se)
|
||||
{
|
||||
APILogger.Log(se);
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
IsSoftDisconnected = false;
|
||||
APILogger.Log($"Soft connect {parameters[0]}:{parameters[1]}");
|
||||
}
|
||||
void IConnection.KeepAliveErrorReceived()
|
||||
{
|
||||
if (Sock != null)
|
||||
{
|
||||
if (Sock.Connected)
|
||||
{
|
||||
Sock.Shutdown(SocketShutdown.Both);
|
||||
Sock.Close();
|
||||
}
|
||||
|
||||
Sock.Dispose();
|
||||
Sock = null;
|
||||
}
|
||||
OnDisconnected?.Invoke(this, new EventArgs());
|
||||
}
|
||||
public string GetConnectionData()
|
||||
{
|
||||
try
|
||||
{
|
||||
return null == Sock ? "" : $"local: {Sock.LocalEndPoint}, Remote: {Sock.RemoteEndPoint}";
|
||||
}
|
||||
catch (Exception) { }
|
||||
return "";
|
||||
}
|
||||
public Socket Sock;
|
||||
protected string Connect_String;
|
||||
private bool _disposed;
|
||||
|
||||
public event EventHandler OnDisconnected;
|
||||
|
||||
public bool Connected => Sock != null && Sock.Connected;
|
||||
|
||||
//public bool connected;
|
||||
public string ConnectString => Connect_String;
|
||||
|
||||
public SocketFlags Flags { get; set; }
|
||||
|
||||
public EthernetConnection()
|
||||
{
|
||||
_disposed = false;
|
||||
}
|
||||
|
||||
|
||||
protected EthernetConnection(Socket sock)
|
||||
{
|
||||
_disposed = false;
|
||||
Sock = sock;
|
||||
}
|
||||
|
||||
~EthernetConnection()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed){ return; }
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Sock != null)
|
||||
{
|
||||
APILogger.Log("sock.Disconnect() - during dispose", ConnectString);
|
||||
if (Sock.Connected)
|
||||
{
|
||||
Sock.Shutdown(SocketShutdown.Both);
|
||||
Sock.Close();
|
||||
}
|
||||
Sock.Dispose();
|
||||
}
|
||||
|
||||
Sock = null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
public void Create(string connectString)
|
||||
{
|
||||
//Create(ConnectString); this is recursive!
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the host ip address, sent during original connect and preserved for future connect/disconnect
|
||||
/// </summary>
|
||||
private string _hostIPAddress;
|
||||
|
||||
/// <summary>
|
||||
/// creates and setups up a socket, returns the socket created
|
||||
/// </summary>
|
||||
/// <param name="connectString"></param>
|
||||
/// <param name="hostIPAddress"></param>
|
||||
/// <returns></returns>
|
||||
public Socket CreateSock(string connectString, string hostIPAddress)
|
||||
{
|
||||
var sock2 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
|
||||
sock2.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
|
||||
sock2.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
|
||||
|
||||
sock2.SendBufferSize = DFConstantsAndEnums.SendBufferSizeBytes;
|
||||
sock2.ReceiveBufferSize = DFConstantsAndEnums.ReceiveBufferSizeBytes;
|
||||
// https://benohead.com/windows-network-connections-timing-quickly-temporary-connectivity-loss/
|
||||
|
||||
//KeepAliveTime: default value is 2hr
|
||||
//KeepAliveInterval: default value is 1s and Detect 5 times
|
||||
const uint dummy = 0; //lenth = 4
|
||||
var inOptionValues = new byte[System.Runtime.InteropServices.Marshal.SizeOf(dummy) * 3];
|
||||
|
||||
BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0); // Keepalive On true
|
||||
BitConverter.GetBytes(DFConstantsAndEnums.LocalKeepAliveTimeOutMS)
|
||||
.CopyTo(inOptionValues, System.Runtime.InteropServices.Marshal.SizeOf(dummy));
|
||||
BitConverter.GetBytes(DFConstantsAndEnums.LocalKeepAliveRetryIntervalMS)
|
||||
.CopyTo(inOptionValues, System.Runtime.InteropServices.Marshal.SizeOf(dummy) * 2);
|
||||
sock2.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
|
||||
if (!string.IsNullOrEmpty(hostIPAddress))
|
||||
{
|
||||
APILogger.Log($"Binding to {hostIPAddress}");
|
||||
sock2.Bind(new IPEndPoint(IPAddress.Parse(hostIPAddress), 0));
|
||||
}
|
||||
|
||||
return sock2;
|
||||
}
|
||||
|
||||
public void Create(string connectString, string hostIPAddress)
|
||||
{
|
||||
_hostIPAddress = hostIPAddress;
|
||||
Sock = CreateSock(connectString, hostIPAddress);
|
||||
Connect_String = connectString;
|
||||
}
|
||||
|
||||
#region Connect
|
||||
public IAsyncResult BeginConnect(AsyncCallback cb, object state)
|
||||
{
|
||||
if (Sock == null)
|
||||
{
|
||||
// "EthernetConnection.BeginConnect: socket is not created"
|
||||
throw new Exception(DASResource.Strings.EthernetConnection_BeginConnect_Err3);
|
||||
}
|
||||
if (string.IsNullOrEmpty(Connect_String))
|
||||
{
|
||||
// "EthernetConnection.BeginConnect: Connect_String is empty"
|
||||
throw new Exception(DASResource.Strings.EthernetConnection_BeginConnect_Err1);
|
||||
}
|
||||
var parameters = Connect_String.Split(':');
|
||||
if (parameters.Length != 2)
|
||||
{
|
||||
// "EthernetConnection.BeginConnect: Connect_String is invalid"
|
||||
throw new Exception(DASResource.Strings.EthernetConnection_BeginConnect_Err2);
|
||||
}
|
||||
if (!int.TryParse(parameters[1], out var portNum))
|
||||
{
|
||||
// "EthernetConnection.BeginConnect: Connect_String has invalid port number"
|
||||
throw new Exception(DASResource.Strings.EthernetConnection_BeginConnect_Err4);
|
||||
}
|
||||
return Sock.BeginConnect(parameters[0], portNum, cb, state);
|
||||
}
|
||||
|
||||
public void EndConnect(IAsyncResult ar)
|
||||
{
|
||||
if (Sock == null)
|
||||
{
|
||||
APILogger.Log("EthernetConnection::EndConnect socket is not created");
|
||||
// "EthernetConnection.EndConnect: socket is not created"
|
||||
throw new Exception(DASResource.Strings.EthernetConnection_EndConnect_Err1);
|
||||
}
|
||||
APILogger.Log("Successfully connected local: " + Sock.LocalEndPoint + " remote: " + Sock.RemoteEndPoint);
|
||||
Sock.EndConnect(ar);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Disconnect
|
||||
|
||||
public IAsyncResult BeginDisconnect(bool reuseSocket,
|
||||
AsyncCallback cb,
|
||||
object state)
|
||||
{
|
||||
APILogger.Log("BeginDisconnect", ConnectString);
|
||||
if (Sock == null)
|
||||
{
|
||||
// "EthernetConnection.BeginDisconnect: socket is not created"
|
||||
throw new Exception(DASResource.Strings.EthernetConnection_BeginDisconnect_Err1);
|
||||
}
|
||||
|
||||
//if know the socket is not connected there's no point in trying to disconnect
|
||||
//however we need to let the caller know that they shouldn't wait for the
|
||||
//EndDisconnect
|
||||
if (!Sock.Connected)
|
||||
{
|
||||
throw new SocketException(DFConstantsAndEnums.WSAEISCONN);
|
||||
}
|
||||
return Sock.BeginDisconnect(reuseSocket, cb, state);
|
||||
}
|
||||
|
||||
public void EndDisconnect(IAsyncResult asyncResult)
|
||||
{
|
||||
APILogger.Log("EndDisconnect()", ConnectString);
|
||||
if (Sock == null)
|
||||
{
|
||||
// "EthernetConnection.EndDisconnect: socket is not created"
|
||||
throw new Exception(DASResource.Strings.EthernetConnection_EndDisconnect_Err1);
|
||||
}
|
||||
Sock.EndDisconnect(asyncResult);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Accept
|
||||
|
||||
public IAsyncResult BeginAccept(AsyncCallback callback,
|
||||
object state)
|
||||
{
|
||||
if (Sock == null)
|
||||
{
|
||||
// "EthernetConnection.BeginAccept: socket is not created"
|
||||
throw new Exception(DASResource.Strings.EthernetConnection_BeginAccept_Err1);
|
||||
}
|
||||
return Sock.BeginAccept(callback, state);
|
||||
}
|
||||
|
||||
public IConnection EndAccept(IAsyncResult asyncResult)
|
||||
{
|
||||
if (Sock == null)
|
||||
{
|
||||
// "EthernetConnection.EndAccept: socket is not created"
|
||||
throw new Exception(DASResource.Strings.EthernetConnection_EndAccept_Err1);
|
||||
}
|
||||
var newSock = Sock.EndAccept(asyncResult);
|
||||
var newConnection = new EthernetConnection(newSock);
|
||||
return newConnection;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Bind
|
||||
|
||||
public void Bind(int port)
|
||||
{
|
||||
if (Sock == null)
|
||||
{
|
||||
// "EthernetConnection.Bind: socket is not created"
|
||||
throw new Exception(DASResource.Strings.EthernetConnection_Bind_Err1);
|
||||
}
|
||||
var ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
|
||||
var ipAddress = ipHostInfo.AddressList[0];
|
||||
var localEndPoint = new IPEndPoint(ipAddress, port);
|
||||
APILogger.Log($"EthernetConnection.Bind, binding to {localEndPoint.Address} - {ipHostInfo.HostName}");
|
||||
Sock.Bind(localEndPoint);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Listen
|
||||
|
||||
public void Listen(int backlog)
|
||||
{
|
||||
if (Sock == null)
|
||||
{
|
||||
// "EthernetConnection.Listen: socket is not created"
|
||||
throw new Exception(DASResource.Strings.EthernetConnection_Listen_Err1);
|
||||
}
|
||||
Sock.Listen(backlog);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Send
|
||||
public IAsyncResult BeginSend(byte[] buffer, int offset, int size,
|
||||
AsyncCallback cb, object state)
|
||||
{
|
||||
if (Sock == null)
|
||||
{
|
||||
// "EthernetConnection.BeginSend: socket is not created"
|
||||
throw new Exception(DASResource.Strings.EthernetConnection_BeginSend_Err1);
|
||||
}
|
||||
if (cb == null)
|
||||
{
|
||||
// "EthernetConnection.BeginSend: callback can't be null"
|
||||
throw new Exception(DASResource.Strings.EthernetConnection_BeginSend_Err2);
|
||||
}
|
||||
//FB 18389 if the connection is not open do not begin send process
|
||||
if (!Sock.Connected)
|
||||
{
|
||||
// "EthernetConnection.BeginSend: socket is not connected."
|
||||
throw new Exception(DASResource.Strings.EthernetConnection_BeginSend_Err3);
|
||||
}
|
||||
return Sock.BeginSend(buffer, offset, size, Flags, cb, state);
|
||||
}
|
||||
|
||||
public int EndSend(IAsyncResult ar)
|
||||
{
|
||||
if (Sock == null)
|
||||
{
|
||||
// "EthernetConnection.EndSend: socket is not created"
|
||||
throw new Exception(DASResource.Strings.EthernetConnection_EndSend_Err1);
|
||||
}
|
||||
try
|
||||
{
|
||||
var ret = Sock.EndSend(ar);
|
||||
return ret;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Sock = null;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<int> SendAsync(byte[] sendBuffer, int bufferStartOffset, int bufferSizeToSend)
|
||||
{
|
||||
return Task<int>.Factory.FromAsync(
|
||||
(callback, state) => BeginSend(sendBuffer, bufferStartOffset, bufferSizeToSend, callback, state),
|
||||
EndSend, state: null
|
||||
);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Receive
|
||||
|
||||
public IAsyncResult BeginReceive(byte[] buffer, int offset, int size,
|
||||
AsyncCallback cb, object state)
|
||||
{
|
||||
if (Sock == null)
|
||||
{
|
||||
// "EthernetConnection.BeginReceive: socket is not created"
|
||||
throw new Exception(DASResource.Strings.EthernetConnection_BeginReceive_Err1);
|
||||
}
|
||||
if (cb == null)
|
||||
{
|
||||
// "EthernetConnection.BeginReceive: callback can't be null"
|
||||
throw new Exception(DASResource.Strings.EthernetConnection_BeginReceive_Err2);
|
||||
}
|
||||
|
||||
return Sock.BeginReceive(buffer, offset, size, Flags, cb, state);
|
||||
}
|
||||
|
||||
public int EndReceive(IAsyncResult ar)
|
||||
{
|
||||
if (Sock == null)
|
||||
{
|
||||
// "EthernetConnection.EndReceive: socket is not created"
|
||||
throw new Exception(DASResource.Strings.EthernetConnection_EndReceive_Err1);
|
||||
}
|
||||
return Sock.EndReceive(ar);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("EthernetConnection")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("EthernetConnection")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2008")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("355ff6bb-d823-4853-93aa-4c12fd8c350e")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("1.06.0081")]
|
||||
[assembly: AssemblyFileVersion("1.06.0081")]
|
||||
@@ -0,0 +1,218 @@
|
||||
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()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = "")]
|
||||
@@ -0,0 +1,4 @@
|
||||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user