public override void DoRequest(DataPacket packet, Workers.WorkerChain chain, DataPacketDelegate sendData)
        {
            DataPacket newPacket = (DataPacket)packet.Clone();
            UInt32 gwioid = CidGenerator.Next();
            Record record = InfoService.IOID.Create(gwioid);
            record.Destination = packet.Sender;
            record.IOID = packet.Parameter2;

            record = InfoService.ChannelCid[packet.Parameter1];

            // Lost the CID
            if (record == null)
            {
                if (Log.WillDisplay(TraceEventType.Error))
                    Log.TraceEvent(System.Diagnostics.TraceEventType.Error, chain.ChainId, "Readnotify not linked to a correct channel");
                packet.Chain.Dispose();
                return;
            }

            if (record.SID == null)
            {
                if (Log.WillDisplay(TraceEventType.Error))
                    Log.TraceEvent(System.Diagnostics.TraceEventType.Error, chain.ChainId, "Readnotify without SID");
                chain.Dispose();
                return;
            }

            newPacket.Destination = record.Destination;
            newPacket.Parameter1 = record.SID.Value;
            newPacket.Parameter2 = gwioid;

            sendData(newPacket);
        }
 public bool Close()
 {
     Container?.SignalAbortReads(false);
     Workers?.Dispose();
     Container?.Dispose();
     Container = null;
     return(true);
 }
 public override void DoRequest(DataPacket packet, Workers.WorkerChain chain, DataPacketDelegate sendData)
 {
     try
     {
         EventAdd.Unsubscribe(chain.Subscriptions[packet.Parameter2]);
         uint res;
         chain.Subscriptions.TryRemove(packet.Parameter2, out res);
     }
     catch
     {
         if (Log.WillDisplay(System.Diagnostics.TraceEventType.Critical))
             Log.TraceEvent(System.Diagnostics.TraceEventType.Critical, chain.ChainId, "Error while cancelling a monitor.");
         chain.Dispose();
     }
 }
        public override void DoRequest(DataPacket packet, Workers.WorkerChain chain, DataPacketDelegate sendData)
        {
            Record channelInfo = InfoService.ChannelCid[packet.Parameter1];
            // Lost the CID
            if (channelInfo == null)
            {
                if (Log.WillDisplay(System.Diagnostics.TraceEventType.Error))
                    Log.TraceEvent(System.Diagnostics.TraceEventType.Error, chain.ChainId, "Write not linked to a correct channel");
                packet.Chain.Dispose();
                return;
            }
            SecurityAccess access;
            switch (chain.Side)
            {
                case Workers.ChainSide.SIDE_A:
                    access = chain.Gateway.Configuration.Security.EvaluateSideA(channelInfo.Channel, chain.Username, chain.Hostname, packet.Sender.Address.ToString());
                    break;
                default:
                    access = chain.Gateway.Configuration.Security.EvaluateSideB(channelInfo.Channel, chain.Username, chain.Hostname, packet.Sender.Address.ToString());
                    break;
            }
            // We don't have write access quit!
            if (!access.Has(SecurityAccess.WRITE))
            {
                return;
            }

            DataPacket newPacket = (DataPacket)packet.Clone();
            UInt32 gwioid = CidGenerator.Next();

            newPacket.Destination = channelInfo.Destination;
            // No SID? Can't write
            if (channelInfo.SID == null)
            {
                if (Log.WillDisplay(TraceEventType.Critical))
                    Log.TraceEvent(TraceEventType.Critical, chain.ChainId, "Write without SID");
                WorkerChain ioc = TcpManager.GetIocChain(null, channelInfo.Destination);
                if (ioc != null)
                    ioc.Dispose();
                chain.Dispose();
                return;
            }

            newPacket.Parameter1 = channelInfo.SID.Value;
            newPacket.Parameter2 = gwioid;

            sendData(newPacket);
        }
        public override void DoRequest(DataPacket packet, Workers.WorkerChain chain, DataPacketDelegate sendData)
        {
            if (packet.DataCount == 0)
            {
                if (Log.WillDisplay(TraceEventType.Error))
                    Log.TraceEvent(TraceEventType.Error, chain.ChainId, "Event add with datacount == 0!");
                packet.DataCount = 1;
            }
            lock (lockObject)
            {
                Record record = InfoService.ChannelCid[packet.Parameter1];
                // Lost the CID...
                if (record == null)
                {
                    if (Log.WillDisplay(TraceEventType.Error))
                        Log.TraceEvent(System.Diagnostics.TraceEventType.Error, chain.ChainId, "EventAdd not linked to a correct channel");
                    packet.Chain.Dispose();
                    return;
                }

                if (record.SID == null)
                {
                    if (Log.WillDisplay(TraceEventType.Error))
                        Log.TraceEvent(System.Diagnostics.TraceEventType.Error, chain.ChainId, "EventAdd SID null");
                    packet.Chain.Dispose();
                    return;
                }

                if (Log.WillDisplay(TraceEventType.Information))
                    Log.TraceEvent(System.Diagnostics.TraceEventType.Information, chain.ChainId, "Add event for " + record.Channel);

                // Not enough info
                if (packet.MessageSize < 12 + 2 + packet.HeaderSize)
                {

                }

                string recId = record.Channel + "/" + packet.DataType + "/" + packet.DataCount + "/" + packet.GetUInt16(12 + (int)packet.HeaderSize);
                //Console.WriteLine(recId);

                //recId = ""+CidGenerator.Next();

                UInt32 gwcid = CidGenerator.Next();
                Record currentMonitor = InfoService.ChannelSubscription.Create(gwcid);
                currentMonitor.Destination = record.Destination;
                currentMonitor.DBRType = packet.DataType;
                currentMonitor.DataCount = packet.DataCount;
                currentMonitor.Client = packet.Sender;
                currentMonitor.SubscriptionId = packet.Parameter2;
                currentMonitor.SID = record.SID.Value;
                currentMonitor.Channel = recId;
                currentMonitor.FirstValue = false;

                chain.Subscriptions[packet.Parameter2] = gwcid;

                // A new monitor
                // Create a new subscription for the main channel
                // And create a list of subscriptions
                if (!InfoService.SubscribedChannel.Knows(recId))
                {
                    if (Log.WillDisplay(TraceEventType.Information))
                        Log.TraceEvent(System.Diagnostics.TraceEventType.Information, chain.ChainId, "Creating new monitor monitor");

                    // Create the subscriptions record.
                    Record subscriptions = new Record();
                    subscriptions.SubscriptionList = new ConcurrentBag<UInt32>();
                    subscriptions.SubscriptionList.Add(gwcid);
                    subscriptions.FirstValue = true;
                    InfoService.SubscribedChannel[recId] = subscriptions;

                    // We don't need to skip till the first packet.
                    currentMonitor.PacketCount = 1;

                    gwcid = CidGenerator.Next();
                    subscriptions.GWCID = gwcid;

                    WorkerChain ioc = TcpManager.GetIocChain((packet.Chain == null ? null : packet.Chain.Gateway), record.Destination);
                    if (ioc == null)
                    {
                        if (Log.WillDisplay(TraceEventType.Error))
                            Log.TraceEvent(System.Diagnostics.TraceEventType.Error, chain.ChainId, "Lost IOC");
                        chain.Dispose();
                        return;
                    }
                    ioc.ChannelSubscriptions[recId] = gwcid;

                    currentMonitor = InfoService.ChannelSubscription.Create(gwcid);
                    currentMonitor.Channel = recId;
                    currentMonitor.Destination = record.Destination;
                    currentMonitor.SID = record.SID;
                    currentMonitor.DBRType = packet.DataType;
                    currentMonitor.DataCount = packet.DataCount;

                    DataPacket newPacket = (DataPacket)packet.Clone();
                    newPacket.Parameter1 = record.SID.Value;
                    newPacket.Parameter2 = gwcid;
                    newPacket.Destination = record.Destination;
                    sendData(newPacket);
                }
                else
                {
                    Record subscriptions = null;

                    if (Log.WillDisplay(TraceEventType.Information))
                        Log.TraceEvent(System.Diagnostics.TraceEventType.Information, chain.ChainId, "Linking to existing monitor");

                    // Add ourself to the subscriptions
                    subscriptions = InfoService.SubscribedChannel[recId];
                    if (subscriptions == null)
                    {
                        if (Log.WillDisplay(TraceEventType.Error))
                            Log.TraceEvent(System.Diagnostics.TraceEventType.Error, chain.ChainId, "Lost main monitor");
                        chain.Dispose();
                        return;
                    }
                    subscriptions.SubscriptionList.Add(gwcid);

                    // Channel never got the first answer
                    // So let's wait like the others
                    if (subscriptions.FirstValue)
                    {
                        currentMonitor.FirstValue = true;
                        currentMonitor.PacketCount = 1;
                    }
                    // Channel already got the first answer
                    // Send a ReadNotify to get the first value
                    else
                    {
                        /*DataPacket newPacket = (DataPacket)subscriptions.FirstPacket.Clone();
                        newPacket.Destination = packet.Sender;
                        newPacket.Parameter2 = packet.Parameter2;
                        newPacket.Sender = packet.Sender;
                        sendData(newPacket);*/

                        currentMonitor.FirstValue = true;
                        currentMonitor.PacketCount = 0;

                        UInt32 gwioid = CidGenerator.Next();
                        // Send an intial read-notify
                        DataPacket newPacket = DataPacket.Create(0, packet.Chain);
                        newPacket.Command = 15;
                        newPacket.DataCount = packet.DataCount;
                        newPacket.DataType = packet.DataType;
                        newPacket.Parameter1 = record.SID.Value;
                        newPacket.Parameter2 = gwioid;
                        newPacket.Destination = record.Destination;

                        record = InfoService.IOID.Create(gwioid);
                        record.Destination = packet.Sender;
                        record.IOID = 0;
                        record.SID = packet.Parameter2;
                        record.DBRType = packet.DataType;
                        record.DataCount = packet.DataCount;
                        record.CID = gwcid;

                        sendData(newPacket);
                    }
                }
            }
        }
        public override void DoResponse(DataPacket packet, Workers.WorkerChain chain, DataPacketDelegate sendData)
        {
            lock (lockObject)
            {
                if (packet.PayloadSize == 0)
                {
                    // Closing channel.
                    return;
                }

                Record mainSubscription = InfoService.ChannelSubscription[packet.Parameter2];
                if (mainSubscription == null)
                {
                    /*if (Log.WillDisplay(TraceEventType.Error))
                        Log.TraceEvent(TraceEventType.Error, chain.ChainId, "Main monitor not found.");*/
                    //chain.Dispose();
                    return;
                }
                string recId = mainSubscription.Channel;
                Record subscriptions = InfoService.SubscribedChannel[recId];

                if (subscriptions == null)
                {
                    if (Log.WillDisplay(TraceEventType.Error))
                        Log.TraceEvent(TraceEventType.Error, chain.ChainId, "Subscription list not found not found.");
                    chain.Dispose();
                    return;
                }

                // Keep a copy of the first packet.
                /*if (subscriptions.FirstPacket == null)
                    subscriptions.FirstPacket = (DataPacket)packet.Clone();*/

                subscriptions.FirstValue = false;

                foreach (UInt32 i in subscriptions.SubscriptionList)
                {
                    DataPacket newPacket = (DataPacket)packet.Clone();
                    Record subscription = InfoService.ChannelSubscription[i];

                    // Received a response after killing it maybe
                    if (subscription == null || subscription.SubscriptionId == null)
                        continue;

                    if (subscription.PacketCount == 0 && subscription.FirstValue == true)
                    {
                        //subscription.PacketCount++;
                        continue;
                    }

                    subscription.PacketCount++;

                    newPacket.Destination = subscription.Client;
                    newPacket.Parameter2 = subscription.SubscriptionId.Value;

                    // Event cancel send a command 1 as response (as event add)
                    // To see the difference check the payload as the event cancel always have a payload of 0
                    if (packet.PayloadSize == 0)
                    {
                        InfoService.ChannelSubscription.Remove(packet.Parameter2);
                        CidGenerator.ReleaseCid(packet.Parameter2);
                        WorkerChain clientChain = TcpManager.GetClientChain(newPacket.Destination);
                        if (clientChain != null)
                        {
                            uint val;
                            clientChain.Subscriptions.TryRemove(newPacket.Parameter2, out val);
                        }
                        continue;
                    }

                    sendData(newPacket);
                }
            }
        }
        public override void DoRequest(DataPacket packet, Workers.WorkerChain chain, DataPacketDelegate sendData)
        {
            /*Stopwatch sw = new Stopwatch();
            sw.Start();*/
            string channelName = packet.GetDataAsString();
            Record channelInfo = null;

            // Get a lock object for this particula channel name
            object lockOper = locks.GetOrAdd(channelName, new object());

            //if (InfoService.ChannelEndPoint.Knows(channelName))
            channelInfo = InfoService.ChannelEndPoint[channelName];

            // Never got this channel!
            if (channelInfo == null)
            {
                StorageService<string> searchService;
                if (chain.Side == ChainSide.SIDE_A)
                    searchService = InfoService.SearchChannelEndPointA;
                else
                    searchService = InfoService.SearchChannelEndPointB;

                if (!searchService.Knows(channelName))
                {
                    if (Log.WillDisplay(TraceEventType.Error))
                        Log.TraceEvent(TraceEventType.Error, chain.ChainId, "Created channel (" + channelName + ") without knowing where it should point at...");
                    chain.Dispose();
                    return;
                }
                channelInfo = searchService[channelName];
                channelInfo.ChainSide = chain.Side;
                InfoService.ChannelEndPoint[channelName] = channelInfo;

                channelInfo.GWCID = null;
            }
            //Console.WriteLine("Create 1: " + sw.Elapsed);

            if (Log.WillDisplay(TraceEventType.Verbose))
                Log.TraceEvent(TraceEventType.Verbose, chain.ChainId, "Request " + channelName + " with cid " + packet.Parameter1);

            SecurityAccess access;
            switch (chain.Side)
            {
                case Workers.ChainSide.SIDE_A:
                    access = chain.Gateway.Configuration.Security.EvaluateSideA(channelName, chain.Username, chain.Hostname, packet.Sender.Address.ToString());
                    break;
                default:
                    access = chain.Gateway.Configuration.Security.EvaluateSideB(channelName, chain.Username, chain.Hostname, packet.Sender.Address.ToString());
                    break;
            }

            // Don't have the right, return a fail create channel
            if (!access.Has(SecurityAccess.READ))
            {
                if (Log.WillDisplay(TraceEventType.Warning))
                    Log.TraceEvent(System.Diagnostics.TraceEventType.Warning, packet.Chain.ChainId, "Create channel " + channelName + " from " + packet.Sender + " while not having rights to read");
                DataPacket newPacket = DataPacket.Create(0, chain);
                newPacket.Command = 26;
                newPacket.Parameter1 = packet.Parameter1;
                newPacket.Sender = packet.Sender;
                newPacket.Destination = packet.Sender;
                sendData(newPacket);
                return;
            }

            var knownGWCID = false;
            var knownSID = false;
            lock (lockOper)
            {
                knownGWCID = channelInfo.GWCID.HasValue;
                knownSID = channelInfo.SID.HasValue;
            }

            // We never got back any answer, let's trash the GWCID to re-create it
            if (knownGWCID
                && !knownSID
                && (Gateway.Now - channelInfo.CreatedOn).TotalSeconds > 10)
            {
                channelInfo.GWCID = null;
                knownGWCID = false;
            }

            // Checks if we have already a channel open with the IOC or not
            // If we have it we can answer directly
            if (knownGWCID)
            {
                //Console.WriteLine("Create 2: " + sw.Elapsed);
                if (Log.WillDisplay(TraceEventType.Verbose))
                    Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose, (packet.Chain == null ? 0 : packet.Chain.ChainId), "Request of a known channel (" + channelName + ")");
                // We need to check if this is something currently in creation

                // Seems we know all
                if (knownSID)
                {

                    Log.TraceEvent(TraceEventType.Verbose, chain.ChainId, "Cached responce create channel cid " + packet.Parameter1);

                    // Give back access rights before the create channel
                    DataPacket newPacket = DataPacket.Create(0, packet.Chain);
                    newPacket.Command = 22;
                    newPacket.DataType = 0;
                    newPacket.DataCount = 0;
                    newPacket.Parameter1 = packet.Parameter1;
                    newPacket.Parameter2 = (uint)access;
                    newPacket.Sender = packet.Sender;
                    newPacket.Destination = packet.Sender;
                    sendData(newPacket);

                    // Gives the create channel answer
                    newPacket = DataPacket.Create(0, packet.Chain);
                    newPacket.Command = 18;
                    // ReSharper disable PossibleInvalidOperationException
                    newPacket.DataType = channelInfo.DBRType.Value;
                    // ReSharper restore PossibleInvalidOperationException
                    // ReSharper disable PossibleInvalidOperationException
                    newPacket.DataCount = channelInfo.DataCount.Value;
                    // ReSharper restore PossibleInvalidOperationException
                    newPacket.Parameter1 = packet.Parameter1;
                    newPacket.Parameter2 = channelInfo.GWCID.Value;
                    newPacket.Sender = packet.Sender;
                    newPacket.Destination = packet.Sender;
                    sendData(newPacket);

                    chain.ChannelCid[channelName] = packet.Parameter1;

                    // We have all the info we can continue.
                    chain.Gateway.DoClientConnectedChannels(chain.ClientEndPoint.ToString(), channelName);

                    //Console.WriteLine("Create 2.1: " + sw.Elapsed);
                    return;
                }

                // Still in creation then let's wait till the channel actually is created
                lock (lockOper)
                {
                    uint clientCid = packet.Parameter1;
                    IPEndPoint clientIp = packet.Sender;
                    Log.TraceEvent(TraceEventType.Verbose, chain.ChainId, "Add event for " + clientCid);

                    channelInfo.GetNotification += delegate(object sender, DataPacket receivedPacket)
                    {
                        //Console.WriteLine("Create 5: " + sw.Elapsed);
                        Record record = InfoService.ChannelCid[receivedPacket.Parameter1];
                        if (record == null || record.Channel == null) // Response too late, we drop it.
                            return;

                        Record resChannelInfo = InfoService.ChannelEndPoint[record.Channel];
                        if (resChannelInfo == null)
                            return;

                        Log.TraceEvent(TraceEventType.Verbose, chain.ChainId, "Event responce create channel cid " + clientCid);

                        // Give back access rights before the create channel
                        DataPacket resPacket = DataPacket.Create(0, packet.Chain);
                        resPacket.Command = 22;
                        resPacket.DataType = 0;
                        resPacket.DataCount = 0;
                        //resPacket.Parameter1 = packet.Parameter1;
                        resPacket.Parameter1 = clientCid;
                        resPacket.Parameter2 = (uint)access;
                        resPacket.Sender = clientIp;
                        resPacket.Destination = clientIp;
                        TcpManager.SendClientPacket(resPacket);

                        resPacket = (DataPacket)receivedPacket.Clone();
                        resPacket.Command = 18;
                        resPacket.Destination = clientIp;
                        resPacket.Parameter1 = clientCid;
                        resPacket.Parameter2 = channelInfo.GWCID.Value;
                        resPacket.Sender = clientIp;
                        TcpManager.SendClientPacket(resPacket);

                        chain.ChannelCid[channelName] = clientCid;
                        chain.Gateway.DoClientConnectedChannels(chain.ClientEndPoint.ToString(), channelName);
                    };
                }
            }
            // We don't have, we need therefore to connect to the IOC to create one
            else
            {
                //Console.WriteLine("Create 3: " + sw.Elapsed);
                /*if (chain.ChannelCid.ContainsKey(channelName))
                {
                    if (Log.WillDisplay(TraceEventType.Warning))
                        Log.TraceEvent(System.Diagnostics.TraceEventType.Warning, (packet.Chain == null ? 0 : packet.Chain.ChainId), "Duplicated request (" + channelName + ")");
                }*/

                if (Log.WillDisplay(TraceEventType.Verbose))
                    Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose, (packet.Chain == null ? 0 : packet.Chain.ChainId), "Request of a new channel (" + channelName + ")");
                channelInfo.GWCID = packet.Parameter1;

                UInt32 gwcid = CidGenerator.Next();
                Record record = InfoService.ChannelCid.Create(gwcid);
                record.Channel = channelName;
                record.GWCID = gwcid;
                record.Client = packet.Sender;
                record.AccessRight = access;
                record.Destination = channelInfo.Server;
                record.ChainSide = chain.Side;
                chain.ChannelCid[channelName] = packet.Parameter1;

                // Send create channel
                DataPacket newPacket = (DataPacket)packet.Clone();
                newPacket.Parameter1 = gwcid;
                // Version
                newPacket.Parameter2 = Gateway.CA_PROTO_VERSION;
                newPacket.Destination = channelInfo.Server;
                sendData(newPacket);

                chain.Gateway.DoClientConnectedChannels(chain.ClientEndPoint.ToString(), channelName);
            }
            //Console.WriteLine("Create 6: " + sw.Elapsed);
        }