private void RegistrationThread() { Log.Info("RegistrationThread starting"); int retryInterval = 250; LimitedLog ll = new LimitedLog(5, 1000); MessageQueue msmq = null; string queueName = computerName + "\\private$\\" + registrationQueue; while (!shutdown) { if (msmq == null) { msmq = new MessageQueue(queueName); //msmq.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); } try { // NOTE: we process only first F2B record from received message // and ignore the rest (including F2B_EOF) Message msg = msmq.Receive(receiveTimeout); BinaryReader stream = new BinaryReader(msg.BodyStream); byte[] header = stream.ReadBytes(4); if (header[0] != 'F' || header[1] != '2' || header[2] != 'B') { Log.Info("RegistrationThread: Invalid message header"); continue; } if (header[3] != (byte) F2B_DATA_TYPE_ENUM.F2B_FWQUEUE_SUBSCRIBE0 && header[3] != (byte)F2B_DATA_TYPE_ENUM.F2B_FWQUEUE_UNSUBSCRIBE0) { Log.Info("RegistrationThread: Invalid message type"); continue; } bool reg = header[3] == (byte)F2B_DATA_TYPE_ENUM.F2B_FWQUEUE_SUBSCRIBE0; int size = IPAddress.NetworkToHostOrder(stream.ReadInt32()); // message size BinaryReader data = new BinaryReader(new MemoryStream(stream.ReadBytes(size))); int dnsSize = IPAddress.NetworkToHostOrder(data.ReadInt32()); string dns = Encoding.Default.GetString(data.ReadBytes(dnsSize)); int uuidSize = IPAddress.NetworkToHostOrder(data.ReadInt32()); Guid guid = new Guid(data.ReadBytes(uuidSize)); string subscriberQueueName = ".\\Private$\\F2BFW_Subscriber_" + dns + "_" + guid.ToString(); Log.Info("RegistrationThread: " + (reg ? "Register" : "Unregister") + " client " + subscriberQueueName + " (" + msg.Label + ")"); bool sendAllData = false; MessageQueue subscriber = null; lock (thisSubscribersLock) { // check if we already registered queue with given name foreach (var item in subscribers) { if (item.Key.Path == subscriberQueueName) { subscriber = item.Key; break; } } if (reg) // subscription request / refresh { // create new message queue for subscriber if it doesn't exists if (!MessageQueue.Exists(subscriberQueueName)) { MessageQueue newMsMq = MessageQueue.Create(subscriberQueueName); // set the label name and close the message queue newMsMq.Label = msg.Label; //newMsMq.AccessMode = QueueAccessMode.SendAndReceive; //newMsMq.Authenticate = true; //newMsMq.EncryptionRequired = EncryptionRequired.Body; //newMsMq.MaximumJournalSize = 10 * 1024; //newMsMq.MaximumQueueSize = ???; // TODO: privileges newMsMq.Close(); } if (subscriber == null) { subscriber = new MessageQueue(subscriberQueueName); subscribers.Add(subscriber, DateTime.UtcNow.Ticks); sendAllData = true; } else { subscribers[subscriber] = DateTime.UtcNow.Ticks; } } else // unsubscribe request { if (subscriber != null) { subscriber.Close(); subscribers.Remove(subscriber); } if (MessageQueue.Exists(subscriberQueueName)) { MessageQueue.Delete(subscriberQueueName); } } } if (sendAllData) { SendAllData(subscriber); } ll.Reset(); } catch (MessageQueueException ex) { // Handle no message arriving in the queue. if (ex.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout) { //ll.Msg("RegistrationThread: No message arrived in queue."); } else if (ex.MessageQueueErrorCode == MessageQueueErrorCode.QueueDeleted) { Log.Info("RegistrationThread: Message queue was deleted ... recreate"); msmq.Close(); msmq = null; } else if (ex.MessageQueueErrorCode == MessageQueueErrorCode.QueueNotFound) { try { if (!MessageQueue.Exists(queueName)) { MessageQueue msmqNew = MessageQueue.Create(queueName); msmqNew.Label = "Fail2ban F2BQueue registration message queue"; msmqNew.Close(); Log.Info("RegistrationThread: Registration queue " + queueName + " created"); } else { ll.Msg("RegistrationThread: Registration queue " + queueName + " inacceslible: " + ex.Message); // Let's way a bit... ewh.WaitOne(retryInterval * (ll.Last < 10 ? ll.Last : 10)); ewh.Reset(); } } catch (MessageQueueException ex1) { ll.Msg("RegistrationThread: Unable to create registration queue " + queueName + ": " + ex1.Message); // Let's way a bit... ewh.WaitOne(retryInterval * (ll.Last < 10 ? ll.Last : 10)); ewh.Reset(); } } else { ll.Msg("RegistrationThread: Unexpected MSMQ exception (code " + ex.MessageQueueErrorCode + "): " + ex.Message); // Let's way a bit... ewh.WaitOne(retryInterval * (ll.Last < 10 ? ll.Last : 10)); ewh.Reset(); } } catch (EndOfStreamException) { Log.Info("RegistrationThread: Input data truncated"); } Log.Info("RegistrationThread loop cont(" + !shutdown + ")"); } Log.Info("RegistrationThread finished"); }
private void ProductionThread() { Log.Info("ProductionThread starting"); int retryInterval = 250; LimitedLog ll = new LimitedLog(5, 1000); MessageQueue msmq = null; string queueName = computerName + "\\Private$\\" + producerQueue; while (!shutdown) { if (msmq == null) { msmq = new MessageQueue(queueName); //msmq.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); } try { Message msg = msmq.Receive(receiveTimeout); BinaryReader istream = new BinaryReader(msg.BodyStream); byte[] header = istream.ReadBytes(4); if (header[0] != 'F' || header[1] != '2' || header[2] != 'B') { Log.Info("ProductionThread: Invalid message header"); continue; } int recordSize = IPAddress.NetworkToHostOrder(istream.ReadInt32()); if (header[3] == (byte) F2B_DATA_TYPE_ENUM.F2B_FWDATA_TYPE0) { // put message in all subscriber queues byte[] data = istream.ReadBytes(recordSize); long expiration = FwData.Expiration(data); byte[] hash = FwData.GetHash(data); if (expiration < DateTime.UtcNow.Ticks) { Log.Info("ProductionThread: Invalid message expiration (expired)"); continue; } lock (thisQDataLock) { // we need unique expiration time to keep all required // data in simple key/value hashmap structure (and we // really don't care about different expiration time in ns) while (qdata.ContainsKey(expiration)) { expiration++; } long expirationOld = 0; if (qhash.TryGetValue(hash, out expirationOld)) { if (expirationOld > expiration) { // same data with longer expiration time already exists continue; } } if (expirationOld != 0 || maxQueueSize == 0 || maxQueueSize > qdata.Count) { qdata[expiration] = new Tuple<byte[], byte[]>(data, hash); qhash[hash] = expiration; if (expirationOld != 0) { // remove data with older expiration time qdata.Remove(expirationOld); } } else { Log.Warn("Reached maximum number of F2B filter rules, skiping filter addition"); } } Log.Info("ProductionThread: Resubmit received message to " + subscribers.Count + " subscribers (expiration=" + expiration + ")"); foreach (MessageQueue subscriber in subscribers.Keys) { // create the message and set the base properties Message msgs = new Message(); msgs.Priority = MessagePriority.Normal; msgs.UseJournalQueue = true; msgs.Label = msg.Label; msgs.TimeToBeReceived = timeToBeReceived; BinaryWriter ostream = new BinaryWriter(msgs.BodyStream); ostream.Write(header); ostream.Write(IPAddress.HostToNetworkOrder(data.Length)); ostream.Write(data); subscriber.Send(msgs); } } else { Log.Error("ProductionThread: Unknown message type " + header[3]); } ll.Reset(); } catch (MessageQueueException ex) { // Handle no message arriving in the queue. if (ex.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout) { //ll.Msg("ProductionThread: No message arrived in queue."); } else if (ex.MessageQueueErrorCode == MessageQueueErrorCode.QueueDeleted) { Log.Info("ProductionThread: Message queue was deleted ... recreate"); msmq.Close(); msmq = null; } else if (ex.MessageQueueErrorCode == MessageQueueErrorCode.QueueNotFound) { try { if (!MessageQueue.Exists(queueName)) { MessageQueue msmqNew = MessageQueue.Create(queueName); msmqNew.Label = "Fail2ban F2BQueue FWDATA production message queue"; msmqNew.Close(); Log.Info("ProductionThread: Production queue " + queueName + " created"); } else { ll.Msg("ProductionThread: Production queue " + queueName + " inacceslible: " + ex.Message); // Let's way a bit... ewh.WaitOne(retryInterval * (ll.Last < 10 ? ll.Last : 10)); ewh.Reset(); } } catch (MessageQueueException ex1) { ll.Msg("ProductionThread: Unable to create production queue " + queueName + ": " + ex1.Message); // Let's way a bit... ewh.WaitOne(retryInterval * (ll.Last < 10 ? ll.Last : 10)); ewh.Reset(); } } else { ll.Msg("ProductionThread: Unexpected MSMQ exception (code " + ex.MessageQueueErrorCode + "): " + ex.Message); // Let's way a bit... ewh.WaitOne(retryInterval * (ll.Last < 10 ? ll.Last : 10)); ewh.Reset(); } } catch (EndOfStreamException) { Log.Info("ProductionThread: Input data truncated"); } Log.Info("ProductionThread loop cont(" + !shutdown + ")"); } Log.Info("ProductionThread finished"); }
private void ConsumptionThread() { Log.Info("ConsumptionThread starting"); int retryInterval = 250; LimitedLog ll = new LimitedLog(5, 1000); MessageQueue msmq = null; string queueName = computerName + "\\private$\\" + producerQueue; while (!shutdown) { if (msmq == null) { msmq = new MessageQueue(queueName); //msmq.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); } try { Message msg = msmq.Receive(receiveTimeout); processFwStream(msg.BodyStream); ll.Reset(); } catch (MessageQueueException ex) { // Handle no message arriving in the queue. if (ex.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout) { ll.Msg("ConsumptionThread: No message arrived in queue."); } else if (ex.MessageQueueErrorCode == MessageQueueErrorCode.QueueDeleted) { Log.Info("ConsumptionThread: Message queue was deleted ... recreate"); msmq.Close(); msmq = null; } else if (ex.MessageQueueErrorCode == MessageQueueErrorCode.QueueNotFound) { ll.Msg("ConsumptionThread: Producer queue " + queueName + " not found: " + ex.Message); // Let's way a bit... ewh.WaitOne(retryInterval * (ll.Last < 10 ? ll.Last : 10)); ewh.Reset(); } else { ll.Msg("ConsumptionThread: Unexpected MSMQ exception (code " + ex.MessageQueueErrorCode + "): " + ex.Message); // Let's way a bit... ewh.WaitOne(retryInterval * (ll.Last < 10 ? ll.Last : 10)); ewh.Reset(); } } catch (EndOfStreamException) { Log.Info("ConsumptionThread: Input data truncated"); } catch (Exception ex) { Log.Warn("ConsumptionThread: Unexpected exception: " + ex.Message); } //Log.Info("ConsumptionThread: loop cont(" + !shutdown + ")"); } Log.Info("ConsumptionThread finished"); }
private void ProductionThread() { Log.Info("ProductionThread starting"); int retryInterval = 250; LimitedLog ll = new LimitedLog(5, 1000); MessageQueue msmq = null; string queueName = computerName + "\\Private$\\" + producerQueue; while (!shutdown) { if (msmq == null) { msmq = new MessageQueue(queueName); //msmq.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); } try { Message msg = msmq.Receive(receiveTimeout); BinaryReader istream = new BinaryReader(msg.BodyStream); byte[] header = istream.ReadBytes(4); if (header[0] != 'F' || header[1] != '2' || header[2] != 'B') { Log.Info("ProductionThread: Invalid message header"); continue; } int recordSize = IPAddress.NetworkToHostOrder(istream.ReadInt32()); if (header[3] == (byte)F2B_DATA_TYPE_ENUM.F2B_FWDATA_TYPE0) { // put message in all subscriber queues byte[] data = istream.ReadBytes(recordSize); long expiration = FwData.Expiration(data); byte[] hash = FwData.GetHash(data); if (expiration < DateTime.UtcNow.Ticks) { Log.Info("ProductionThread: Invalid message expiration (expired)"); continue; } lock (thisQDataLock) { // we need unique expiration time to keep all required // data in simple key/value hashmap structure (and we // really don't care about different expiration time in ns) while (qdata.ContainsKey(expiration)) { expiration++; } long expirationOld = 0; if (qhash.TryGetValue(hash, out expirationOld)) { if (expirationOld > expiration) { // same data with longer expiration time already exists continue; } } if (expirationOld != 0 || maxQueueSize == 0 || maxQueueSize > qdata.Count) { qdata[expiration] = new Tuple <byte[], byte[]>(data, hash); qhash[hash] = expiration; if (expirationOld != 0) { // remove data with older expiration time qdata.Remove(expirationOld); } } else { Log.Warn("Reached maximum number of F2B filter rules, skiping filter addition"); } } Log.Info("ProductionThread: Resubmit received message to " + subscribers.Count + " subscribers (expiration=" + expiration + ")"); foreach (MessageQueue subscriber in subscribers.Keys) { // create the message and set the base properties Message msgs = new Message(); msgs.Priority = MessagePriority.Normal; msgs.UseJournalQueue = true; msgs.Label = msg.Label; msgs.TimeToBeReceived = timeToBeReceived; BinaryWriter ostream = new BinaryWriter(msgs.BodyStream); ostream.Write(header); ostream.Write(IPAddress.HostToNetworkOrder(data.Length)); ostream.Write(data); subscriber.Send(msgs); } } else { Log.Error("ProductionThread: Unknown message type " + header[3]); } ll.Reset(); } catch (MessageQueueException ex) { // Handle no message arriving in the queue. if (ex.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout) { //ll.Msg("ProductionThread: No message arrived in queue."); } else if (ex.MessageQueueErrorCode == MessageQueueErrorCode.QueueDeleted) { Log.Info("ProductionThread: Message queue was deleted ... recreate"); msmq.Close(); msmq = null; } else if (ex.MessageQueueErrorCode == MessageQueueErrorCode.QueueNotFound) { try { if (!MessageQueue.Exists(queueName)) { MessageQueue msmqNew = MessageQueue.Create(queueName); msmqNew.Label = "Fail2ban F2BQueue FWDATA production message queue"; msmqNew.Close(); Log.Info("ProductionThread: Production queue " + queueName + " created"); } else { ll.Msg("ProductionThread: Production queue " + queueName + " inacceslible: " + ex.Message); // Let's way a bit... ewh.WaitOne(retryInterval * (ll.Last < 10 ? ll.Last : 10)); ewh.Reset(); } } catch (MessageQueueException ex1) { ll.Msg("ProductionThread: Unable to create production queue " + queueName + ": " + ex1.Message); // Let's way a bit... ewh.WaitOne(retryInterval * (ll.Last < 10 ? ll.Last : 10)); ewh.Reset(); } } else { ll.Msg("ProductionThread: Unexpected MSMQ exception (code " + ex.MessageQueueErrorCode + "): " + ex.Message); // Let's way a bit... ewh.WaitOne(retryInterval * (ll.Last < 10 ? ll.Last : 10)); ewh.Reset(); } } catch (EndOfStreamException) { Log.Info("ProductionThread: Input data truncated"); } Log.Info("ProductionThread loop cont(" + !shutdown + ")"); } Log.Info("ProductionThread finished"); }
private void RegistrationThread() { Log.Info("RegistrationThread starting"); int retryInterval = 250; LimitedLog ll = new LimitedLog(5, 1000); MessageQueue msmq = null; string queueName = computerName + "\\private$\\" + registrationQueue; while (!shutdown) { if (msmq == null) { msmq = new MessageQueue(queueName); //msmq.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); } try { // NOTE: we process only first F2B record from received message // and ignore the rest (including F2B_EOF) Message msg = msmq.Receive(receiveTimeout); BinaryReader stream = new BinaryReader(msg.BodyStream); byte[] header = stream.ReadBytes(4); if (header[0] != 'F' || header[1] != '2' || header[2] != 'B') { Log.Info("RegistrationThread: Invalid message header"); continue; } if (header[3] != (byte)F2B_DATA_TYPE_ENUM.F2B_FWQUEUE_SUBSCRIBE0 && header[3] != (byte)F2B_DATA_TYPE_ENUM.F2B_FWQUEUE_UNSUBSCRIBE0) { Log.Info("RegistrationThread: Invalid message type"); continue; } bool reg = header[3] == (byte)F2B_DATA_TYPE_ENUM.F2B_FWQUEUE_SUBSCRIBE0; int size = IPAddress.NetworkToHostOrder(stream.ReadInt32()); // message size BinaryReader data = new BinaryReader(new MemoryStream(stream.ReadBytes(size))); int dnsSize = IPAddress.NetworkToHostOrder(data.ReadInt32()); string dns = Encoding.Default.GetString(data.ReadBytes(dnsSize)); int uuidSize = IPAddress.NetworkToHostOrder(data.ReadInt32()); Guid guid = new Guid(data.ReadBytes(uuidSize)); string subscriberQueueName = ".\\Private$\\F2BFW_Subscriber_" + dns + "_" + guid.ToString(); Log.Info("RegistrationThread: " + (reg ? "Register" : "Unregister") + " client " + subscriberQueueName + " (" + msg.Label + ")"); bool sendAllData = false; MessageQueue subscriber = null; lock (thisSubscribersLock) { // check if we already registered queue with given name foreach (var item in subscribers) { if (item.Key.Path == subscriberQueueName) { subscriber = item.Key; break; } } if (reg) // subscription request / refresh { // create new message queue for subscriber if it doesn't exists if (!MessageQueue.Exists(subscriberQueueName)) { MessageQueue newMsMq = MessageQueue.Create(subscriberQueueName); // set the label name and close the message queue newMsMq.Label = msg.Label; //newMsMq.AccessMode = QueueAccessMode.SendAndReceive; //newMsMq.Authenticate = true; //newMsMq.EncryptionRequired = EncryptionRequired.Body; //newMsMq.MaximumJournalSize = 10 * 1024; //newMsMq.MaximumQueueSize = ???; // TODO: privileges newMsMq.Close(); } if (subscriber == null) { subscriber = new MessageQueue(subscriberQueueName); subscribers.Add(subscriber, DateTime.UtcNow.Ticks); sendAllData = true; } else { subscribers[subscriber] = DateTime.UtcNow.Ticks; } } else // unsubscribe request { if (subscriber != null) { subscriber.Close(); subscribers.Remove(subscriber); } if (MessageQueue.Exists(subscriberQueueName)) { MessageQueue.Delete(subscriberQueueName); } } } if (sendAllData) { SendAllData(subscriber); } ll.Reset(); } catch (MessageQueueException ex) { // Handle no message arriving in the queue. if (ex.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout) { //ll.Msg("RegistrationThread: No message arrived in queue."); } else if (ex.MessageQueueErrorCode == MessageQueueErrorCode.QueueDeleted) { Log.Info("RegistrationThread: Message queue was deleted ... recreate"); msmq.Close(); msmq = null; } else if (ex.MessageQueueErrorCode == MessageQueueErrorCode.QueueNotFound) { try { if (!MessageQueue.Exists(queueName)) { MessageQueue msmqNew = MessageQueue.Create(queueName); msmqNew.Label = "Fail2ban F2BQueue registration message queue"; msmqNew.Close(); Log.Info("RegistrationThread: Registration queue " + queueName + " created"); } else { ll.Msg("RegistrationThread: Registration queue " + queueName + " inacceslible: " + ex.Message); // Let's way a bit... ewh.WaitOne(retryInterval * (ll.Last < 10 ? ll.Last : 10)); ewh.Reset(); } } catch (MessageQueueException ex1) { ll.Msg("RegistrationThread: Unable to create registration queue " + queueName + ": " + ex1.Message); // Let's way a bit... ewh.WaitOne(retryInterval * (ll.Last < 10 ? ll.Last : 10)); ewh.Reset(); } } else { ll.Msg("RegistrationThread: Unexpected MSMQ exception (code " + ex.MessageQueueErrorCode + "): " + ex.Message); // Let's way a bit... ewh.WaitOne(retryInterval * (ll.Last < 10 ? ll.Last : 10)); ewh.Reset(); } } catch (EndOfStreamException) { Log.Info("RegistrationThread: Input data truncated"); } Log.Info("RegistrationThread loop cont(" + !shutdown + ")"); } Log.Info("RegistrationThread finished"); }