Files
imsInterface/interface/asm/dotnet/AdapterApplication3x/com.itac.mes.proxy.sockets/IhapEventChannel.cs
2025-06-06 09:15:13 +02:00

290 lines
11 KiB
C#

using com.itac.mes.tools;
using System;
using System.Diagnostics;
using System.IO;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.Threading;
using com.itac.artes.ihap;
using com.itac.mes.domain;
using com.itac.oib;
using com.itac.oib.boardgatekeeper.service;
using com.itac.oib.linecontrol.service;
using com.itac.oib.monitoring.service;
using com.itac.oib.siplacesetupcenter.service;
using com.itac.oib.traceability.service;
// Handler der das callen von Methoden des DataInterface aus dem iTAC.OIB.Adapter übernimmt
namespace com.itac.mes.proxy.sockets
{
public delegate void PropertyChangeListener(object sender, string channelName, string message);
public class IhapEventChannel : RealProxy
{
private static int CONNECTION_CHECK_MILLIES = 500;
private TcpClient _client;
private IhapOutputStream _ios;
private IhapInputStream _iis;
private bool _isShutdown;
public string channelName { get; set; }
private long lastCall = DateTime.Now.Ticks;
private Object lockObject = new Object();
private Thread aliveThread;
public event PropertyChangeListener connectionStateChangeListener;
public IhapEventChannel(TcpClient client, String channelName)
: base(typeof(OIBEvents))
{
lock (typeof(IhapHandler))
{
}
this.channelName = channelName;
this._client = client;
_ios = new IhapOutputStream(_client.GetStream());
_iis = new IhapInputStream(_client.GetStream());
aliveThread = new Thread(new ThreadStart(aliveThreadRun));
}
public void shutdown()
{
LogHandler.log(Constants.LOGGER, TraceEventType.Information, "closing channel" + channelName);
_isShutdown = true;
try
{
_client.Close();
}
catch (Exception)
{
LogHandler.log(Constants.LOGGER, TraceEventType.Warning, "closing channel" + channelName + " failed");
}
}
public long getLastCall()
{
return lastCall;
}
public bool isConnected()
{
return _client.Client.Connected;
}
public bool isShutdownInProgress()
{
return _isShutdown;
}
public override IMessage Invoke(IMessage message)
{
lastCall = new DateTime().Ticks;
IMethodCallMessage methodMsg = (IMethodCallMessage)message;
try
{
MethodInfo methodInfo = typeof(OIBEvents).GetMethod(methodMsg.MethodName, (Type[])methodMsg.MethodSignature);
// der Reihe nach alle Interface durchgehen, die als Callback implementiert sind
if (methodInfo == null)
{
methodInfo = typeof(ISiplaceSetupCenterNotify).GetMethod(methodMsg.MethodName, (Type[])methodMsg.MethodSignature);
}
if (methodInfo == null)
{
methodInfo = typeof(ITraceability).GetMethod(methodMsg.MethodName, (Type[])methodMsg.MethodSignature);
}
if (methodInfo == null)
{
methodInfo = typeof(ISetupCenterExternalControl).GetMethod(methodMsg.MethodName, (Type[])methodMsg.MethodSignature);
}
if (methodInfo == null)
{
methodInfo = typeof(IMonitoringReceiver).GetMethod(methodMsg.MethodName, (Type[])methodMsg.MethodSignature);
}
if (methodInfo == null)
{
methodInfo = typeof(ILineControlReceiver).GetMethod(methodMsg.MethodName, (Type[])methodMsg.MethodSignature);
}
if (methodInfo == null)
{
methodInfo = typeof(IAdapterNotify).GetMethod(methodMsg.MethodName, (Type[])methodMsg.MethodSignature);
}
if (methodInfo == null)
{
methodInfo = typeof(IChangeoverManager).GetMethod(methodMsg.MethodName, (Type[])methodMsg.MethodSignature);
}
if (methodInfo == null)
{
methodInfo = typeof(IBoardGateKeeper).GetMethod(methodMsg.MethodName, (Type[])methodMsg.MethodSignature);
}
if (methodInfo == null)
{
throw new Exception("IHapHandler.cs: methode '" + methodMsg.MethodName + "' nicht in den Interfacen gefunden");
}
object[] args = methodMsg.Args;
if (methodMsg.MethodName.Equals("Equals"))
{
return new ReturnMessage(args[0].Equals(this), args, 0, methodMsg.LogicalCallContext, methodMsg);
}
else if (methodMsg.MethodName.Equals("GetHashCode"))
{
return new ReturnMessage(this.GetHashCode(), args, 0, methodMsg.LogicalCallContext, methodMsg);
}
else if (methodMsg.MethodName.Equals("shutdown"))
{
shutdown();
stopAliveThread();
connectionClosed();
return new ReturnMessage(null, args, 0, methodMsg.LogicalCallContext, methodMsg);
}
else if (methodMsg.MethodName.Equals("startup"))
{
aliveThread.Start();
return new ReturnMessage(null, args, 0, methodMsg.LogicalCallContext, methodMsg);
}
Object retValue = sendCall(methodInfo, args);
return new ReturnMessage(retValue, args, 0, methodMsg.LogicalCallContext, methodMsg);
}
catch (TargetInvocationException ite)
{
return new ReturnMessage(ite.GetBaseException(), methodMsg);
}
catch (Exception ite)
{
return new ReturnMessage(ite.GetBaseException(), methodMsg);
}
}
private Object sendCall(MethodInfo method, Object[] args)
{
lock (lockObject)
{
LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, "Send event '" + method.Name + "' to socket " + _client.Client.RemoteEndPoint + " on " + channelName);
Object result = null;
try
{
_ios.writeBoolean(false);
_ios.call(method, args);
_ios.Flush();
IhapReply reply = _iis.readReply();
if (reply is IhapSuccessReply)
{
result = ((IhapSuccessReply)reply).getReturnValue();
}
else
{
IhapFaultReply fault = (IhapFaultReply)reply;
switch (fault.getFaultCode())
{
case FaultCode.NoSuchMethodException:
throw new NotImplementedException(fault.getMessage());
case FaultCode.ProtocolException:
throw new IhapProtocolException(fault.getMessage(), null);
default:
throw new IhapProtocolException(fault.getMessage(), null);
//(Exception)fault.getException();
}
}
}
catch (Exception e)
{
LogHandler.log(Constants.LOGGER, TraceEventType.Error, "Error while sending event call on " + channelName + ":" + e.Message + "\n" + e.StackTrace);
shutdown();
}
return result;
}
}
protected void connectionClosed()
{
// Hier wird überprüft, ob ein Eintrag in der Aufruf-Liste vorhanden ist.
if (this.connectionStateChangeListener != null)
{
// Hier wird jeder Delegat, der sich für den Event registriert hat, aufgerufen.
this.connectionStateChangeListener(this, channelName, "connectionClosed");
}
}
/**
*
*/
private void stopAliveThread()
{
if (aliveThread.IsAlive && (aliveThread.ThreadState != System.Threading.ThreadState.Running))
{
aliveThread.Interrupt();
}
}
public void aliveThreadRun()
{
while (!_isShutdown && aliveThread.ThreadState == System.Threading.ThreadState.Running)
{
// wenn der letzte Call länger als .. her ist...
try
{
Thread.Sleep(50);
}
catch (Exception )
{
// wenn beim schliessen der Verbindung noch was passiert ist das nicht schlimm
LogHandler.log(Constants.LOGGER, TraceEventType.Information, "interrupted for " + channelName);
}
if (DateTime.Now.Ticks - lastCall > CONNECTION_CHECK_MILLIES)
{
try
{
// versuchen den Server zu pingen
// wenn das fehlschlägt ist die Verbindung kaputt
lock (lockObject)
{ // das erfolgreiche Schreiben eines booleschen Wertes ist aus Kommunikationssicht zu sehen wie der
// erfolgreiche Aufruf einer Methode
if (!_isShutdown && (aliveThread.ThreadState == System.Threading.ThreadState.Running))
{
// nur wenn die Verbindung nicht bereits gestoppt wurde...
_ios.writeBoolean(true);
_ios.Flush();
lastCall = DateTime.Now.Ticks;
}
}
}
catch (Exception )
{
try
{
_isShutdown = true;
_client.Close();
}
catch (IOException e)
{
// wenn beim schliessen der Verbindung noch was passiert ist das nicht schlimm
LogHandler.log(Constants.LOGGER, TraceEventType.Information, "shutdown connection problem for " + channelName, e);
}
finally
{
// die Schreibverbindung ist kaputt, also diese Connection töten...
LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, "detected broken connection for " + channelName
+ " because Server closed port");
connectionClosed();
}
}
}
}
// wenn beim schliessen der Verbindung noch was passiert ist das nicht schlimm
LogHandler.log(Constants.LOGGER, TraceEventType.Information, "channel shut down finished for " + channelName);
}
}
}