public void ReadState(string stateFile) { Log.Info("ReadState from " + stateFile); if (!File.Exists(stateFile)) { Log.Warn("Unable to read state file " + stateFile + ", file doesn't exist"); return; } long currTime = DateTime.UtcNow.Ticks; lock (thisQDataLock) { try { using (Stream fileStream = new FileStream(stateFile, FileMode.Open, FileAccess.Read)) using (GZipStream gzipStream = new GZipStream(fileStream, CompressionMode.Decompress)) using (BinaryReader stream = new BinaryReader(gzipStream)) { while (true) { //byte[] header = stream.ReadBytes(4); byte[] header = new byte[4]; if (stream.Read(header, 0, 4) == 0) { // reached end of stream break; } if (header[0] != 'F' || header[1] != '2' && header[2] != 'B') { throw new InvalidDataException("Invalid state file structure (F2B data block header not found)"); } int size = IPAddress.NetworkToHostOrder(stream.ReadInt32()); byte[] data = stream.ReadBytes(size); if (header[3] != (byte)F2B_DATA_TYPE_ENUM.F2B_FWDATA_TYPE0) { Log.Error("Invalid data type: " + header[3]); continue; } long expiration = FwData.Expiration(data); byte[] hash = FwData.GetHash(data); if (expiration < currTime) { Log.Info("Invalid message expiration (expired)"); continue; } // 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"); } } } } catch (Exception ex) { Log.Error("Failed to read state from " + stateFile + ": " + ex.Message); //throw; } } }
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"); }