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); }