Ejemplo n.º 1
0
        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;
                }
            }
        }
Ejemplo n.º 2
0
        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");
        }