Stores a processing chain composed of workers
Inheritance: IDisposable
        /// <summary>
        /// Used to populate the chain based on a list of types
        /// </summary>
        /// <param name="gateway"></param>
        /// <param name="side"> </param>
        /// <param name="workersNeeded"></param>
        /// <param name="client"></param>
        /// <param name="server"></param>
        /// <returns></returns>
        static WorkerChain PopulateChain(Gateway gateway, ChainSide side, IEnumerable<Type> workersNeeded, IPEndPoint client, IPEndPoint server)
        {
            WorkerChain chain = new WorkerChain { ClientEndPoint = client, ServerEndPoint = server, Gateway = gateway, Side = side };

            foreach (Type t in workersNeeded)
            {
                // ReSharper disable PossibleNullReferenceException
                Worker w = (Worker)t.GetConstructor(new Type[] { }).Invoke(new object[] { });
                // ReSharper restore PossibleNullReferenceException
                w.Chain = chain;
                w.ClientEndPoint = client;
                w.ServerEndPoint = server;
                chain.Add(w);
            }

            /*lock (lockChainManagement)
            {
                knownChains.Add(chain);
            }*/
            knownChains.Add(chain);

            return chain;
        }
        public DebugPortWorker(WorkerChain chain, IPEndPoint client, IPEndPoint server)
        {
            Chain = chain;
            socket = ((TcpReceiver)Chain[0]).Socket;
            base.ClientEndPoint = client;
            base.ServerEndPoint = server;

            sendStream = new BufferedStream(new NetworkStream(socket));

            try
            {
                lock (sendStream)
                {
                    Send((int)DebugDataType.GW_NAME);
                    Send(Chain.Gateway.Configuration.GatewayName);

                    Send((int)DebugDataType.FULL_IOC);
                    Send(Chain.Gateway.KnownIocs.Count);
                    foreach (var i in Chain.Gateway.KnownIocs)
                    {
                        Send(i.Key);
                        Send(i.Value.Count);
                        foreach (var j in i.Value)
                        {
                            Send(j);
                        }
                    }

                    Send((int)DebugDataType.FULL_CLIENT);
                    Send(Chain.Gateway.KnownClients.Count);
                    foreach (var i in Chain.Gateway.KnownClients)
                    {
                        Send(i.Key);
                        Send(i.Value.Count);
                        foreach (var j in i.Value)
                        {
                            Send(j);
                        }
                    }

                    if (PBCaGw.Services.DebugTraceListener.TraceAll)
                        Send((int)DebugDataType.FULL_LOGS);
                    else
                        Send((int)DebugDataType.CRITICAL_LOGS);
                    Flush();

                    PBCaGw.Services.LogEntry[] logs = PBCaGw.Services.DebugTraceListener.LastEntries;
                    foreach (var i in logs)
                    {
                        Send((int)DebugDataType.LOG);
                        Send(i.Source);
                        Send((int)i.EventType);
                        Send(i.Id);
                        Send(i.Message);
                        Flush();
                    }
                }
            }
            catch
            {
                Chain.Dispose();
            }

            Chain.Gateway.NewIocChannel += new NewIocChannelDelegate(GatewayNewIocChannel);
            Chain.Gateway.DropIoc += new DropIocDelegate(GatewayDropIoc);
            Chain.Gateway.NewClientChannel += new NewClientChannelDelegate(GatewayNewClientChannel);
            Chain.Gateway.DropClient += new DropClientDelegate(GatewayDropClient);

            PBCaGw.Services.DebugTraceListener.LogEntry += GatewayLogEntry;
            PBCaGw.Services.DebugTraceListener.TraceLevelChanged += new System.EventHandler(DebugTraceListenerTraceLevelChanged);
        }
 /// <summary>
 /// Link 2 chains together (a client which is connected to an IOC)
 /// </summary>
 /// <param name="chain"></param>
 public void UseChain(WorkerChain chain)
 {
     if (chain == null)
         return;
     chain.lastNonUsed = null;
     if (!chain.usedBy.ContainsKey(this))
         chain.usedBy.TryAdd(this, this);
 }
        internal void StartGateway()
        {
            Configuration.Security.Init();

            if (Log.WillDisplay(System.Diagnostics.TraceEventType.Start))
                Log.TraceEvent(TraceEventType.Start, -1, "Starting gateway chains");
            udpChainA = WorkerChain.UdpChain(this, ChainSide.SIDE_A, configuration.LocalSideA, configuration.RemoteSideB);
            tcpListenerA = new GwTcpListener(this, ChainSide.SIDE_A, configuration.LocalSideA);
            beaconA = new BeaconSender(configuration.UdpReceiverA, configuration.LocalSideA, configuration.RemoteSideA);

            if (configuration.ConfigurationType == ConfigurationType.BIDIRECTIONAL)
            {
                udpChainB = WorkerChain.UdpChain(this, ChainSide.SIDE_B, configuration.LocalSideB, configuration.RemoteSideA);
                tcpListenerB = new GwTcpListener(this, ChainSide.SIDE_B, configuration.LocalSideB);
                beaconB = new BeaconSender(configuration.UdpReceiverB, configuration.LocalSideB, configuration.RemoteSideB);
            }
            else
            {
                udpResponseChainA = WorkerChain.UdpResponseChain(this, ChainSide.UDP_RESP_SIDE_A, configuration.LocalSideB, configuration.RemoteSideA);
            }
            if (Log.WillDisplay(System.Diagnostics.TraceEventType.Start))
                Log.TraceEvent(TraceEventType.Start, -1, "Gateway is ready");

            // Recover channels created on a previous session of the gateway
            if (File.Exists("knownChannels.txt") && RestoreCache)
            {
                string[] channelsToRecover;
                lock (lockChannelList)
                    channelsToRecover = File.ReadAllLines("knownChannels.txt");

                foreach (var channelName in channelsToRecover)
                {
                    DataPacket searchPacket = DataPacket.Create(16 + channelName.Length + DataPacket.Padding(channelName.Length));
                    searchPacket.PayloadSize = (ushort)(channelName.Length + DataPacket.Padding(channelName.Length));
                    searchPacket.Kind = DataPacketKind.COMPLETE;
                    searchPacket.DataType = 0;
                    searchPacket.DataCount = Gateway.CA_PROTO_VERSION;
                    searchPacket.Command = 6;
                    searchPacket.Parameter1 = 0;
                    // Version
                    searchPacket.Parameter2 = 0;
                    searchPacket.Sender = udpChainA.ClientEndPoint;
                    searchPacket.SetDataAsString(channelName);

                    udpChainA[2].ProcessData(searchPacket);
                    if (configuration.ConfigurationType == ConfigurationType.BIDIRECTIONAL)
                    {
                        searchPacket = DataPacket.Create(16 + channelName.Length + DataPacket.Padding(channelName.Length));
                        searchPacket.PayloadSize = (ushort)(channelName.Length + DataPacket.Padding(channelName.Length));
                        searchPacket.Kind = DataPacketKind.COMPLETE;
                        searchPacket.DataType = 0;
                        searchPacket.DataCount = Gateway.CA_PROTO_VERSION;
                        searchPacket.Command = 6;
                        searchPacket.Parameter1 = 0;
                        // Version
                        searchPacket.Parameter2 = 0;
                        searchPacket.Sender = udpChainB.ClientEndPoint;
                        searchPacket.SetDataAsString(channelName);
                        udpChainB[2].ProcessData(searchPacket);
                    }
                }
            }
            TenSecJobs += new EventHandler(StoreKnownChannels);
        }
 /// <summary>
 /// Called by the TCP Listener when receiving a new connection.
 /// Stores a client (request) chain.
 /// </summary>
 /// <param name="iPEndPoint"></param>
 /// <param name="chain"></param>
 internal static void RegisterClient(IPEndPoint iPEndPoint, WorkerChain chain)
 {
     lock (clientConnections)
     {
         clientConnections.Add(iPEndPoint, ((TcpReceiver)chain[0]).Socket);
         clientChains.Add(iPEndPoint, chain);
     }
 }
        /// <summary>
        /// Removes an IOC (response) chain
        /// </summary>
        /// <param name="chain"></param>
        internal static void DropServerConnection(WorkerChain chain)
        {
            if (chain == null || chain[0] as TcpReceiver == null || ((TcpReceiver)chain[0]).Socket == null)
                return;

            IPEndPoint endPoint;
            try
            {
                endPoint = ((TcpReceiver)chain[0]).RemoteEndPoint;
            }
            catch
            {
                return;
            }

            Socket toDisconnect = null;
            lock (iocConnections)
            {
                if (!iocConnections.ContainsKey(endPoint))
                    return;

                if (Log.WillDisplay(System.Diagnostics.TraceEventType.Stop))
                    Log.TraceEvent(System.Diagnostics.TraceEventType.Stop, iocChains[endPoint].ChainId, "Disposing IOC chain " + endPoint);

                toDisconnect = iocConnections[endPoint];

                iocConnections.Remove(endPoint);
                iocChains.Remove(endPoint);
            }

            try
            {
                toDisconnect.Disconnect(false);
            }
            catch
            {
            }

            // Cleanup which shall not be usefull but somehow we get wrong data..
            // It's a work around not the real fix sadly.
            List<string> toCleanup = InfoService.ChannelEndPoint.OfType<KeyValuePair<string, Record>>()
                .Where(row => row.Value.Destination != null
                    && row.Value.Destination.ToString() == endPoint.ToString())
                .Select(row => row.Key).ToList();

            foreach (var i in toCleanup)
                InfoService.ChannelEndPoint.Remove(i);

            chain.Gateway.DoDropIoc(endPoint.ToString());
            chain.Dispose();
        }
 /// <summary>
 /// Creates a new message based on the byte buffer however use only the first "size" byte for it.
 /// </summary>
 /// <param name="buff"></param>
 /// <param name="size"></param>
 /// <param name="chain"> </param>
 /// <param name="reuseBuffer"></param>
 public static DataPacket Create(byte[] buff, int size, WorkerChain chain, bool reuseBuffer = false)
 {
     if (reuseBuffer)
     {
         DataPacket p = new DataPacket();
         p.Data = buff;
         p.Chain = chain;
         p.bufferSize = size;
         return p;
     }
     else
     {
         DataPacket p = Create(size);
         p.Chain = chain;
         Buffer.BlockCopy(buff, 0, p.Data, 0, size);
         return p;
     }
 }
 /// <summary>
 /// Creates a new message with the given payload size and sets the payload size correctly.
 /// </summary>
 /// <param name="payloadSize"></param>
 /// <param name="chain"> </param>
 public static DataPacket Create(int payloadSize, WorkerChain chain)
 {
     DataPacket p = Create(payloadSize + 16);
     p.Chain = chain;
     p.SetUInt16(2, (UInt16)payloadSize);
     return p;
 }