using System; using System.Collections.Generic; 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.artes.ihap.serialize; using com.itac.mes.domain; using com.itac.mes.proxy.business; using com.itac.mes.tools; 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; namespace com.itac.mes.proxy.sockets { public delegate void ClientDisconnectedHandler(IhapHandler handler); public class IhapHandler : RealProxy { private static IDictionary _methodMap; private static int handlerCounter; private Object lockObject = new Object(); private int handlerNr; private TcpClient _client; private IhapOutputStream _ios; private IhapInputStream _iis; private OIBServiceImpl _serviceImpl; private bool _isShutdown; private long lastCall = DateTime.Now.Ticks; public IhapHandler(TcpClient client, OIBServiceImpl oibServiceImpl) : base(typeof(OIBEvents)) { lock (typeof(IhapHandler)) { handlerCounter++; this.handlerNr = handlerCounter; } this._client = client; this._serviceImpl = oibServiceImpl; // damit zum testen callbacks aufgerufen werden koennen initMethodMap(); Thread thread = new Thread(new ThreadStart(Run)); thread.Start(); } public event ClientDisconnectedHandler ClientDisconnected; private static void initMethodMap() { if (_methodMap != null) { return; } _methodMap = new Dictionary(); ProtocolMapping protocolMapping = new ProtocolMapping_v1(); MethodInfo[] methods = typeof(OIBService).GetMethods(); foreach (MethodInfo method in methods) { _methodMap.Add(protocolMapping.getOverloadMethodName(method), method); } // Alle Methoden aller implmentierten Interface eintragen... Type[] array = typeof(OIBService).GetInterfaces(); foreach (Type innerType in array) { methods = innerType.GetMethods(); foreach (MethodInfo method in methods) { _methodMap.Add(protocolMapping.getOverloadMethodName(method), method); } } } public void shutdown() { _isShutdown = true; try { _serviceImpl.Shutdown(); _client.Close(); } catch (Exception) { } } public long getLastCall() { return lastCall; } public bool isConnected() { return _client.Client.Connected; } public string getName() { return "IhapHandler" + handlerNr; } 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(IBoardGateKeeper).GetMethod(methodMsg.MethodName, (Type[])methodMsg.MethodSignature); } if (methodInfo == null) { throw new Exception("IHapHandler.cs: methode 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); } 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); } } public void Run() { Thread.CurrentThread.Name = "IhapHandler-" + handlerNr; _ios = new IhapOutputStream(_client.GetStream()); _iis = new IhapInputStream(_client.GetStream()); try { while (!_isShutdown && isConnected()) { receiveCall(); } } catch (Exception) { shutdown(); } } private void receiveCall() { lock (lockObject) { try { Exception fault = null; Object returnValue = null; String methodName = null; try { if (!_iis.readBoolean()) { IhapCall lCall = _iis.readCall(); methodName = lCall.getOverloadMethodName(); if (_methodMap.ContainsKey(methodName)) { MethodInfo lMethod = _methodMap[methodName]; Object[] args = lCall.getArgs(); returnValue = lMethod.Invoke(_serviceImpl, args); lastCall = DateTime.Now.Ticks; } else { throw new NotImplementedException(); } } else { //ping... return; } } catch (IhapProtocolException pe) { if (pe.Message.EndsWith("end of file")) { throw pe; } fault = new ArtesRemoteException("Unable to read client request on " + getName(), pe); _ios.writeFaultReply(FaultCode.ProtocolException, fault); } catch (NotImplementedException) { fault = new ArtesRemoteException("Unknown method '" + methodName + "'"); _ios.writeFaultReply(FaultCode.NoSuchMethodException, fault); } catch (IOException ioe) { throw ioe; } catch (Exception e) { if (e is TargetInvocationException) { e = ((TargetInvocationException)e).InnerException; } fault = e; _ios.writeFaultReply(FaultCode.ServiceException, fault); } if (fault == null) { _ios.writeSuccessReply(returnValue); } } catch (IOException ioe) { if (ioe.Message.EndsWith("end of file")) { LogHandler.log(Constants.LOGGER, TraceEventType.Information, "Socket " + _client.Client.RemoteEndPoint + " disconnected for " + getName()); ClientDisconnected(this); shutdown(); } else { LogHandler.log(Constants.LOGGER, TraceEventType.Error, "Error receiving call for " + getName() + ":" + ioe.Message); ClientDisconnected(this); } throw ioe; } finally { try { _ios.Flush(); } catch (IOException) { } } } } private Object sendCall(MethodInfo method, Object[] args) { lock (lockObject) { LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, "Send event '" + method.Name + "' to socket " + _client.Client.RemoteEndPoint + " for " + getName()); 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 for " + getName() + " . " + e.Message + "\n" + e.StackTrace); shutdown(); } return result; } } public void setAdapterControl(IAdapterControl adapterControl) { _serviceImpl.SetAdapterControl(adapterControl); } } }