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 override void DoRequest(DataPacket packet, PBCaGw.Workers.WorkerChain chain, DataPacketDelegate sendData)
 {
     /*DataPacket newPacket = (DataPacket)packet.Clone();
     newPacket.Destination = packet.Sender;
     newPacket.DataType = 0;
     newPacket.DataCount = Gateway.CA_PROTO_VERSION;
     SendData(newPacket);*/
 }
 public override void DoResponse(DataPacket packet, Workers.WorkerChain chain, DataPacketDelegate sendData)
 {
     Record record = InfoService.ChannelCid[packet.Parameter1];
     if (Log.WillDisplay(TraceEventType.Critical))
     {
         if (record != null)
             Log.TraceEvent(TraceEventType.Critical, chain.ChainId, "Proto Error (" + packet.Parameter2 + ") on CID: " + packet.Parameter1 + " (" + record.Channel + "), SID = " + record.SID);
         else
             Log.TraceEvent(TraceEventType.Critical, chain.ChainId, "Proto Error (" + packet.Parameter2 + ") on CID: " + packet.Parameter1);
     }
 }
        public override void DoResponse(DataPacket packet, Workers.WorkerChain chain, DataPacketDelegate sendData)
        {
            DataPacket newPacket = (DataPacket)packet.Clone();
            Record record = InfoService.IOID[packet.Parameter2];
            if (record == null || record.IOID == null)
                return;

            InfoService.IOID.Remove(packet.Parameter2);
            CidGenerator.ReleaseCid(packet.Parameter2);

            newPacket.Destination = record.Destination;
            newPacket.Parameter2 = record.IOID.Value;
            sendData(newPacket);
        }
 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 DoResponse(DataPacket packet, Workers.WorkerChain chain, DataPacketDelegate sendData)
        {
            DataPacket newPacket = (DataPacket)packet.Clone();
            Record record = InfoService.IOID[packet.Parameter2];

            if (record == null)
                return;

            // Removes it to avoid the cleaup
            InfoService.IOID.Remove(packet.Parameter2);
            CidGenerator.ReleaseCid(packet.Parameter2);

            lock (EventAdd.lockObject)
            {
                // It's the initial answer as get of "cached" monitor.
                if (record.IOID.HasValue && record.IOID.Value == 0)
                {
                    if (!record.SID.HasValue)
                        return;

                    if (record.CID.HasValue && InfoService.ChannelSubscription.Knows(record.CID.Value))
                    {
                        if (InfoService.ChannelSubscription[record.CID.Value].PacketCount == 0 && InfoService.ChannelSubscription[record.CID.Value].FirstValue == true)
                        {
                            if (Log.WillDisplay(TraceEventType.Verbose))
                                Log.TraceEvent(TraceEventType.Verbose, chain.ChainId, "Sending readnotify data on " + record.SID.Value);

                            newPacket.Command = 1;
                            newPacket.Parameter1 = 1;
                            newPacket.Parameter2 = record.SID.Value;
                            newPacket.Destination = record.Destination;
                            newPacket.DataCount = record.DataCount.Value;
                            newPacket.DataType = record.DBRType.Value;

                            sendData(newPacket);
                            InfoService.ChannelSubscription[record.CID.Value].FirstValue = false;
                            InfoService.ChannelSubscription[record.CID.Value].PacketCount = 1;
                        }
                    }
                    return;
                }
            }

            newPacket.Destination = record.Destination;
            newPacket.Parameter1 = 1;
            newPacket.Parameter2 = record.IOID.Value;
            sendData(newPacket);
        }
        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)
        {
            IPAddress senderAddress=packet.Sender.Address;
            if (senderAddress.Equals(chain.Gateway.Configuration.LocalSideA.Address) || senderAddress.Equals(chain.Gateway.Configuration.LocalSideB.Address))
                return;

            // Use only the 5th beacon as restart
            if (packet.Parameter1 != 5)
                return;

            // Reset the beacon sender
            if (chain.Side == Workers.ChainSide.SIDE_A && chain.Gateway.beaconB != null)
                chain.Gateway.beaconB.ResetBeacon();
            else if (chain.Side == Workers.ChainSide.SIDE_B && chain.Gateway.beaconA != null)
                chain.Gateway.beaconA.ResetBeacon();
        }
 /// <summary>
 /// Both request / answer should be handled in the same way.
 /// If we didn't sent the first packet then we should answer,
 /// otherwise it's the answer to our own echo, therefore drop it.
 /// </summary>
 /// <param name="packet"></param>
 /// <param name="chain"></param>
 void HandleEcho(DataPacket packet, Workers.WorkerChain chain, DataPacketDelegate SendData)
 {
     // Answer to our own?
     if (InfoService.EchoSent[packet.Sender] != null)
     {
         // Yes then drop the packet and remove the info from our list
         InfoService.EchoSent.Remove(packet.Sender);
     }
     else
     {
         // No then let's answer with the same content just changing the destination as the sender
         DataPacket newPacket = (DataPacket)packet.Clone();
         newPacket.Destination = packet.Sender;
         //newPacket.NeedToFlush = true;
         SendData(newPacket);
     }
 }
 public override void DoRequest(DataPacket packet, Workers.WorkerChain chain, DataPacketDelegate sendData)
 {
     chain.Username = packet.GetDataAsString();
 }
 /// <summary>
 /// Doesn't have a response for this message
 /// </summary>
 /// <param name="packet"></param>
 /// <param name="chain"></param>
 /// <param name="sendData"> </param>
 public override void DoResponse(DataPacket packet, Workers.WorkerChain chain, DataPacketDelegate sendData)
 {
 }
        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);
                    }
                }
            }
        }
示例#13
0
 public override void DoResponse(DataPacket packet, Workers.WorkerChain chain, DataPacketDelegate sendData)
 {
     HandleEcho(packet, chain, sendData);
 }
        public override void DoResponse(DataPacket packet, Workers.WorkerChain chain, DataPacketDelegate sendData)
        {
            if (!InfoService.ChannelCid.Knows(packet.Parameter1))  // Response too late, we drop it.
            {
                if (Log.WillDisplay(TraceEventType.Verbose))
                    Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose, (packet.Chain == null ? 0 : packet.Chain.ChainId), "Drop late reponse.");
                return;
            }

            Record record = InfoService.ChannelCid[packet.Parameter1];
            if (record.Channel == null) // Response too late, we drop it.
            {
                if (Log.WillDisplay(TraceEventType.Verbose))
                    Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose, (packet.Chain == null ? 0 : packet.Chain.ChainId), "Drop late reponse.");
                return;
            }
            if (Log.WillDisplay(TraceEventType.Verbose))
                Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose, (packet.Chain == null ? 0 : packet.Chain.ChainId), "Got response for " + record.Channel + ".");

            record.SID = packet.Parameter2;
            if(!chain.Channels.Any(row=>row == record.Channel))
                chain.Channels.Add(record.Channel);

            object lockOper = locks.GetOrAdd(record.Channel, new object());

            // Stores in the channel end point the retreiven info
            Record channelInfo;
            lock (lockOper)
            //if(true)
            {
                channelInfo = InfoService.ChannelEndPoint[record.Channel];
                if (channelInfo == null)
                {
                    if (Log.WillDisplay(TraceEventType.Error))
                        Log.TraceEvent(System.Diagnostics.TraceEventType.Error, (packet.Chain == null ? 0 : packet.Chain.ChainId), "Got create channel response, but lost the request.");
                    return;
                }
                channelInfo.SID = packet.Parameter2;
                channelInfo.DBRType = packet.DataType;
                channelInfo.DataCount = packet.DataCount;
                channelInfo.GWCID = packet.Parameter1;
            }
            channelInfo.Notify(chain, packet);

            // Was a prepared creation, let's stop
            if (record.Client != null && record.Channel != null)
            {
                WorkerChain destChain = TcpManager.GetClientChain(record.Client);
                if (destChain != null)
                {
                    Log.TraceEvent(TraceEventType.Verbose, chain.ChainId, "Direct responce create channel cid " + destChain.ChannelCid[record.Channel]);

                    // Give back access rights before the create channel
                    DataPacket accessPacket = DataPacket.Create(0, packet.Chain);
                    accessPacket.Command = 22;
                    accessPacket.DataType = 0;
                    accessPacket.DataCount = 0;
                    accessPacket.Parameter1 = destChain.ChannelCid[record.Channel];
                    accessPacket.Parameter2 = (uint)record.AccessRight;
                    accessPacket.Sender = packet.Sender;
                    accessPacket.Destination = record.Client;
                    sendData(accessPacket);

                    DataPacket newPacket = (DataPacket)packet.Clone();
                    newPacket.Parameter1 = destChain.ChannelCid[record.Channel];
                    newPacket.Parameter2 = packet.Parameter1;
                    newPacket.Destination = record.Client;
                    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);
        }
 /// <summary>
 /// Closing channel is currently simply answering as if we do it... but in fact does nothing.
 /// </summary>
 /// <param name="packet"></param>
 /// <param name="chain"></param>
 /// <param name="sendData"> </param>
 public override void DoRequest(DataPacket packet, Workers.WorkerChain chain, DataPacketDelegate sendData)
 {
     DataPacket newPacket = (DataPacket)packet.Clone();
     newPacket.Destination = packet.Sender;
     sendData(newPacket);
 }
 /// <summary>
 /// Used to answer to a response
 /// </summary>
 /// <param name="command"></param>
 /// <param name="packet"></param>
 /// <param name="chain"></param>
 /// <param name="send"> </param>
 /// <returns></returns>
 public static void ExecuteResponseHandler(UInt16 command, DataPacket packet, PBCaGw.Workers.WorkerChain chain, DataPacketDelegate send)
 {
     if (!(command >= handlers.Length || handlers[command] == null))
         handlers[command].DoResponse(packet, chain, send);
 }
        public override void DoRequest(DataPacket packet, PBCaGw.Workers.WorkerChain chain, DataPacketDelegate sendData)
        {
            // From ourself? Skip it.
            if (packet.Sender.Equals(chain.ClientEndPoint))
                    return;

            /*// Not coming from one of the allowed destination
            if (chain.Destinations.Any(i => CompareNetC(i.Address, packet.Sender.Address)))
                return;*/

            if (chain.Destinations == null)
                return;

            if (packet.Sender == null)
                return;
            if (Log.WillDisplay(TraceEventType.Verbose))
                Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose, chain.ChainId, "Search from: " + packet.Sender);

            //if(chain.Gateway.Configuration.LocalSideA.Port == chain.Gateway.Configuration.LocalSideB.Port)

            // It's a response
            //if (packet.PayloadSize <= 8 && packet.Chain.Gateway.Configuration.ConfigurationType == ConfigurationType.BIDIRECTIONAL)
            if (packet.PayloadSize == 8)
            {
                DoResponse(packet, chain, sendData);
                return;
            }

            DiagnosticServer.NbSearches++;
            DataPacket newPacket = (DataPacket)packet.Clone();
            string channelName = packet.GetDataAsString();

            if (chain.Side == Workers.ChainSide.SIDE_A)
            {
                if (!chain.Gateway.Configuration.Security.EvaluateSideA(channelName, null, null, packet.Sender.Address.ToString()).Has(SecurityAccess.READ))
                    return;
            }
            else
            {
                if (!chain.Gateway.Configuration.Security.EvaluateSideB(channelName, null, null, packet.Sender.Address.ToString()).Has(SecurityAccess.READ))
                    return;
            }

            Record record;

            // Maybe this request is known.
            if (InfoService.ChannelEndPoint.Knows(channelName))
            {
                record = InfoService.ChannelEndPoint[channelName];
                bool knownChannel = false;
                if (chain.Side == ChainSide.SIDE_A && record.knownFromSideA == true)
                    knownChannel=true;
                else if (chain.Side == ChainSide.SIDE_B && record.knownFromSideB == true)
                    knownChannel=true;

                if(knownChannel)
                {
                    if (Log.WillDisplay(TraceEventType.Information))
                        Log.TraceEvent(TraceEventType.Information, chain.ChainId, "Cached search " + channelName);
                    newPacket = DataPacket.Create(8, packet.Chain);
                    newPacket.ReverseAnswer = true;
                    newPacket.Command = 6;
                    newPacket.Parameter1 = 0xffffffff;
                    newPacket.Parameter2 = packet.Parameter1;
                    if (chain.Side == Workers.ChainSide.SIDE_A)
                        newPacket.DataType = (UInt16)chain.Gateway.Configuration.LocalSideA.Port;
                    else
                        newPacket.DataType = (UInt16)chain.Gateway.Configuration.LocalSideB.Port;
                    newPacket.DataCount = 0;
                    newPacket.SetUInt16(16, Gateway.CA_PROTO_VERSION);

                    newPacket.Destination = packet.Sender;
                    sendData(newPacket);
                    return;
                }
            }

            if (chain.Side == ChainSide.SIDE_A)
                record = InfoService.SearchChannelEndPointA[channelName];
            else
                record = InfoService.SearchChannelEndPointB[channelName];

            // We have the info stored in the channel end point? Yes let's use it then.
            /*if (record == null
                && InfoService.ChannelEndPoint.Knows(channelName))
            {
                record = InfoService.ChannelEndPoint[channelName];
            }*/

            // First time, or never got answer, let's ask to the IOCS
            // Step 1
            if (record == null)
            {
                record = InfoService.SearchChannel.Create();
                // ReSharper disable PossibleInvalidOperationException
                uint gwcid = record.GWCID.Value;
                // ReSharper restore PossibleInvalidOperationException
                record.CID = packet.Parameter1;
                record.Client = packet.Sender;
                record.Channel = channelName;

                // Diagnostic search
                newPacket = (DataPacket)packet.Clone();
                newPacket.Parameter1 = gwcid;
                newPacket.Parameter2 = gwcid;
                newPacket.Destination = new IPEndPoint(chain.Gateway.Configuration.LocalSideB.Address, 7890);
                if (chain.Side == Workers.ChainSide.SIDE_B)
                    newPacket.ReverseAnswer = true;
                sendData(newPacket);

                foreach (IPEndPoint dest in chain.Destinations)
                {
                    newPacket = (DataPacket)packet.Clone();
                    newPacket.Parameter1 = gwcid;
                    newPacket.Parameter2 = gwcid;
                    newPacket.Destination = dest;
                    sendData(newPacket);
                }
            }
            // We have the info, therefore use the stored info to answer (cached)
            else
            {
                newPacket = DataPacket.Create(8, packet.Chain);
                newPacket.ReverseAnswer = true;
                newPacket.Command = 6;
                newPacket.Parameter1 = 0xffffffff;
                newPacket.Parameter2 = packet.Parameter1;
                if (chain.Side == Workers.ChainSide.SIDE_A)
                    newPacket.DataType = (UInt16)chain.Gateway.Configuration.LocalSideA.Port;
                else
                    newPacket.DataType = (UInt16)chain.Gateway.Configuration.LocalSideB.Port;
                newPacket.DataCount = 0;
                newPacket.SetUInt16(16, Gateway.CA_PROTO_VERSION);

                newPacket.Destination = packet.Sender;
                sendData(newPacket);
            }
        }
        // We get back the answer from the IOC
        public override void DoResponse(DataPacket packet, Workers.WorkerChain chain, DataPacketDelegate sendData)
        {
            Record record = InfoService.SearchChannel[packet.Parameter2];
            if (record == null)
                return;

            // Let's create the channel in parallel. That should speedup the communication.
            string channelName = record.Channel;

            if (Gateway.AutoCreateChannel)
            {
                if (!InfoService.ChannelEndPoint.Knows(channelName))
                {
                    Record channelInfo = InfoService.ChannelEndPoint[channelName];
                    if (Log.WillDisplay(TraceEventType.Information))
                        Log.TraceEvent(TraceEventType.Information, chain.ChainId, "Pre-create the channel " + channelName);

                    UInt32 gwcid = CidGenerator.Next();

                    channelInfo = InfoService.ChannelEndPoint.Create(record.Channel);
                    channelInfo.Destination = new IPEndPoint(packet.Sender.Address, packet.DataType);
                    channelInfo.GWCID = gwcid;

                    record = InfoService.ChannelCid.Create(gwcid);
                    record.Channel = channelName;
                    record.GWCID = gwcid;
                    record.Destination = new IPEndPoint(packet.Sender.Address, packet.DataType);

                    DataPacket channelPacket = DataPacket.Create(16 + channelName.Length + DataPacket.Padding(channelName.Length));
                    channelPacket.PayloadSize = (ushort)(channelName.Length + DataPacket.Padding(channelName.Length));
                    channelPacket.DataType = 0;
                    channelPacket.DataCount = 0;
                    channelPacket.Command = 18;
                    channelPacket.Parameter1 = gwcid;
                    // Version
                    channelPacket.Parameter2 = Gateway.CA_PROTO_VERSION;
                    IPEndPoint dest = new IPEndPoint(packet.Sender.Address, packet.DataType);
                    channelPacket.Destination = dest;
                    //channelPacket.NeedToFlush = true;
                    channelPacket.SetDataAsString(channelName);

                    Gateway gw = packet.Chain.Gateway;

                    System.Threading.ThreadPool.QueueUserWorkItem(state =>
                    {
                        try
                        {
                            TcpManager.SendIocPacket(gw, channelPacket);
                            //TcpManager.FlushBuffer(dest);
                        }
                        catch
                        {
                        }
                    });

                    record = InfoService.SearchChannel[packet.Parameter2];
                }
            }

            if (chain.Side == ChainSide.SIDE_B || chain.Side == ChainSide.UDP_RESP_SIDE_A)
                InfoService.SearchChannelEndPointA.Remove(channelName);
            else
                InfoService.SearchChannelEndPointB.Remove(channelName);

            IPEndPoint destination = new IPEndPoint(packet.Sender.Address, packet.DataType);
            WorkerChain ioc = TcpManager.GetIocChain(chain.Gateway, destination);
            // We can't connect to the IOC...
            if (ioc == null)
                return;
            if (!ioc.Channels.Any(row => row == channelName))
                ioc.Channels.Add(channelName);
            Record channel = InfoService.ChannelEndPoint[channelName];
            if (channel == null)
                channel = InfoService.ChannelEndPoint.Create(channelName);
            channel.Server = destination;

            if (chain.Side == ChainSide.SIDE_B || chain.Side == ChainSide.UDP_RESP_SIDE_A)
                channel.knownFromSideA = true;
            else
                channel.knownFromSideA = false;

            if (record == null || record.CID == null)
                return;
            // Auto-creation of the channels after a restart
            if (record.CID == 0)
            {
                if (Log.WillDisplay(TraceEventType.Information))
                    Log.TraceEvent(TraceEventType.Information, chain.ChainId, "Recovered channel " + channelName);
                return;
            }

            DataPacket newPacket = (DataPacket)packet.Clone();

            if (packet.Chain.Gateway.Configuration.ConfigurationType == ConfigurationType.BIDIRECTIONAL)
            {
                if (chain.Side == Workers.ChainSide.SIDE_A)
                    newPacket.DataType = (UInt16)chain.Gateway.Configuration.LocalSideB.Port;
                else
                    newPacket.DataType = (UInt16)chain.Gateway.Configuration.LocalSideA.Port;
            }
            else if (chain.Side == Workers.ChainSide.UDP_RESP_SIDE_A)
                newPacket.DataType = (UInt16)chain.Gateway.Configuration.LocalSideA.Port;
            else
                newPacket.DataType = (UInt16)chain.Gateway.Configuration.LocalSideB.Port;
            newPacket.Parameter1 = 0xffffffff;
            newPacket.Parameter2 = record.CID.Value;
            newPacket.Destination = record.Client;
            newPacket.SetUInt16(16, Gateway.CA_PROTO_VERSION);

            sendData(newPacket);
        }
 public abstract void DoResponse(DataPacket packet, Workers.WorkerChain chain, DataPacketDelegate sendData);
 /// <summary>
 /// Doesn't have a response for this message
 /// </summary>
 /// <param name="packet"></param>
 /// <param name="chain"></param>
 public override void DoResponse(DataPacket packet, Workers.WorkerChain chain, DataPacketDelegate sendData)
 {
     throw new NotImplementedException();
 }