flow_control: implement pass / drop filtering policies

This change introduces a set of three modes for flow control
filters, one of which is default behavor and two extra modes
else described below:

  - FILTER_POLICY_PASS_ALL
  - FILTER_POLICY_DROP_ALL

Both modes are opposite, and make a filter either unconditionally
pass or drop all the data one gets to the input. They would be
usable for some external usage.
diff --git a/include/grgsm/flow_control/CMakeLists.txt b/include/grgsm/flow_control/CMakeLists.txt
index 9c20b59..322c8c8 100644
--- a/include/grgsm/flow_control/CMakeLists.txt
+++ b/include/grgsm/flow_control/CMakeLists.txt
@@ -21,6 +21,7 @@
 # Install public header files
 ########################################################################
 install(FILES
+    common.h
     burst_timeslot_splitter.h
     burst_sdcch_subslot_splitter.h
     burst_timeslot_filter.h
diff --git a/include/grgsm/flow_control/burst_fnr_filter.h b/include/grgsm/flow_control/burst_fnr_filter.h
index dd60830..0d94ff8 100644
--- a/include/grgsm/flow_control/burst_fnr_filter.h
+++ b/include/grgsm/flow_control/burst_fnr_filter.h
@@ -26,6 +26,7 @@
 
 #include <grgsm/api.h>
 #include <gnuradio/block.h>
+#include <grgsm/flow_control/common.h>
 
 namespace gr {
   namespace gsm {
@@ -62,6 +63,10 @@
 
       virtual filter_mode get_mode(void) = 0;
       virtual filter_mode set_mode(filter_mode mode) = 0;
+
+      /* Filtering policy */
+      virtual filter_policy get_policy(void) = 0;
+      virtual filter_policy set_policy(filter_policy policy) = 0;
     };
 
   } // namespace gsm
diff --git a/include/grgsm/flow_control/burst_sdcch_subslot_filter.h b/include/grgsm/flow_control/burst_sdcch_subslot_filter.h
index 5bcf829..a68782f 100644
--- a/include/grgsm/flow_control/burst_sdcch_subslot_filter.h
+++ b/include/grgsm/flow_control/burst_sdcch_subslot_filter.h
@@ -25,6 +25,7 @@
 
 #include <grgsm/api.h>
 #include <gnuradio/block.h>
+#include <grgsm/flow_control/common.h>
 
 namespace gr {
   namespace gsm {
@@ -61,6 +62,10 @@
 
       virtual subslot_filter_mode get_mode(void) = 0;
       virtual subslot_filter_mode set_mode(subslot_filter_mode mode) = 0;
+
+      /* Filtering policy */
+      virtual filter_policy get_policy(void) = 0;
+      virtual filter_policy set_policy(filter_policy policy) = 0;
     };
   } // namespace gsm
 } // namespace gr
diff --git a/include/grgsm/flow_control/burst_timeslot_filter.h b/include/grgsm/flow_control/burst_timeslot_filter.h
index 2f16b77..79d677c 100644
--- a/include/grgsm/flow_control/burst_timeslot_filter.h
+++ b/include/grgsm/flow_control/burst_timeslot_filter.h
@@ -25,6 +25,7 @@
 
 #include <grgsm/api.h>
 #include <gnuradio/block.h>
+#include <grgsm/flow_control/common.h>
 
 namespace gr {
   namespace gsm {
@@ -52,6 +53,10 @@
       /* External API */
       virtual unsigned int get_tn(void) = 0;
       virtual unsigned int set_tn(unsigned int tn) = 0;
+
+      /* Filtering policy */
+      virtual filter_policy get_policy(void) = 0;
+      virtual filter_policy set_policy(filter_policy policy) = 0;
     };
   } // namespace gsm
 } // namespace gr
diff --git a/include/grgsm/flow_control/common.h b/include/grgsm/flow_control/common.h
new file mode 100644
index 0000000..fa4725c
--- /dev/null
+++ b/include/grgsm/flow_control/common.h
@@ -0,0 +1,38 @@
+/* -*- c++ -*- */
+/*
+ * @file
+ * @author Vadim Yanitskiy <axilirator@gmail.com>
+ * @section LICENSE
+ *
+ * Gr-gsm is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * Gr-gsm is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gr-gsm; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GSM_FLOW_CONTROL_COMMON_H
+#define INCLUDED_GSM_FLOW_CONTROL_COMMON_H
+
+namespace gr {
+  namespace gsm {
+
+    enum filter_policy {
+      FILTER_POLICY_DEFAULT,
+      FILTER_POLICY_PASS_ALL,
+      FILTER_POLICY_DROP_ALL,
+    };
+
+  } /* namespace gsm */
+} /* namespace gr */
+
+#endif
diff --git a/include/grgsm/flow_control/dummy_burst_filter.h b/include/grgsm/flow_control/dummy_burst_filter.h
index b969611..bf956bb 100644
--- a/include/grgsm/flow_control/dummy_burst_filter.h
+++ b/include/grgsm/flow_control/dummy_burst_filter.h
@@ -25,6 +25,7 @@
 
 #include <grgsm/api.h>
 #include <gnuradio/block.h>
+#include <grgsm/flow_control/common.h>
 
 namespace gr {
   namespace gsm {
@@ -48,6 +49,11 @@
        * creating new instances.
        */
       static sptr make();
+
+      /* External API */
+      /* Filtering policy */
+      virtual filter_policy get_policy(void) = 0;
+      virtual filter_policy set_policy(filter_policy policy) = 0;
     };
   } // namespace gsm
 } // namespace gr
diff --git a/lib/flow_control/burst_fnr_filter_impl.cc b/lib/flow_control/burst_fnr_filter_impl.cc
index 940dcdf..5d1ffbc 100644
--- a/lib/flow_control/burst_fnr_filter_impl.cc
+++ b/lib/flow_control/burst_fnr_filter_impl.cc
@@ -49,7 +49,8 @@
               gr::io_signature::make(0, 0, 0),
               gr::io_signature::make(0, 0, 0)),
       d_mode(mode),
-      d_framenr(fnr)
+      d_framenr(fnr),
+      d_filter_policy(FILTER_POLICY_DEFAULT)
     {
         message_port_register_in(pmt::mp("in"));       
         message_port_register_out(pmt::mp("out"));
@@ -64,6 +65,14 @@
 
     void burst_fnr_filter_impl::process_burst(pmt::pmt_t msg)
     {
+        if (d_filter_policy == FILTER_POLICY_DROP_ALL)
+          return;
+
+        if (d_filter_policy == FILTER_POLICY_PASS_ALL) {
+          message_port_pub(pmt::mp("out"), msg);
+          return;
+        }
+
         pmt::pmt_t header_plus_burst = pmt::cdr(msg);
         gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(header_plus_burst);
         
@@ -106,5 +115,19 @@
       return d_mode;
     }
 
+    /* Filtering policy */
+    filter_policy
+    burst_fnr_filter_impl::get_policy(void)
+    {
+      return d_filter_policy;
+    }
+
+    filter_policy
+    burst_fnr_filter_impl::set_policy(filter_policy policy)
+    {
+      d_filter_policy = policy;
+      return d_filter_policy;
+    }
+
   } /* namespace gsm */
 } /* namespace gr */
diff --git a/lib/flow_control/burst_fnr_filter_impl.h b/lib/flow_control/burst_fnr_filter_impl.h
index b113679..9d13825 100644
--- a/lib/flow_control/burst_fnr_filter_impl.h
+++ b/lib/flow_control/burst_fnr_filter_impl.h
@@ -34,6 +34,7 @@
     class burst_fnr_filter_impl : public burst_fnr_filter
     {
      private:
+      filter_policy d_filter_policy;
       unsigned int d_framenr;
       filter_mode d_mode;
      public:
@@ -47,6 +48,10 @@
 
       filter_mode get_mode(void);
       filter_mode set_mode(filter_mode mode);
+
+      /* Filtering policy */
+      filter_policy get_policy(void);
+      filter_policy set_policy(filter_policy policy);
     };
 
   } // namespace gsm
diff --git a/lib/flow_control/burst_sdcch_subslot_filter_impl.cc b/lib/flow_control/burst_sdcch_subslot_filter_impl.cc
index 76bf9cd..80e7c89 100644
--- a/lib/flow_control/burst_sdcch_subslot_filter_impl.cc
+++ b/lib/flow_control/burst_sdcch_subslot_filter_impl.cc
@@ -48,7 +48,8 @@
               gr::io_signature::make(0, 0, 0),
               gr::io_signature::make(0, 0, 0)),
       d_mode(mode),
-      d_subslot(subslot)
+      d_subslot(subslot),
+      d_filter_policy(FILTER_POLICY_DEFAULT)
     {     
         message_port_register_in(pmt::mp("in"));
         message_port_register_out(pmt::mp("out"));
@@ -73,6 +74,14 @@
           0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,-1,-1,-1,
           0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,-1,-1,-1
         };
+
+        if (d_filter_policy == FILTER_POLICY_DROP_ALL)
+          return;
+
+        if (d_filter_policy == FILTER_POLICY_PASS_ALL) {
+          message_port_pub(pmt::mp("out"), msg);
+          return;
+        }
     
         pmt::pmt_t header_plus_burst = pmt::cdr(msg);
         gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(header_plus_burst);
@@ -133,5 +142,19 @@
       return d_mode;
     }
 
+    /* Filtering policy */
+    filter_policy
+    burst_sdcch_subslot_filter_impl::get_policy(void)
+    {
+      return d_filter_policy;
+    }
+
+    filter_policy
+    burst_sdcch_subslot_filter_impl::set_policy(filter_policy policy)
+    {
+      d_filter_policy = policy;
+      return d_filter_policy;
+    }
+
   } /* namespace gsm */
 } /* namespace gr */
diff --git a/lib/flow_control/burst_sdcch_subslot_filter_impl.h b/lib/flow_control/burst_sdcch_subslot_filter_impl.h
index 9068140..85a392f 100644
--- a/lib/flow_control/burst_sdcch_subslot_filter_impl.h
+++ b/lib/flow_control/burst_sdcch_subslot_filter_impl.h
@@ -31,6 +31,7 @@
     class burst_sdcch_subslot_filter_impl : public burst_sdcch_subslot_filter
     {
      private:
+      filter_policy d_filter_policy;
       subslot_filter_mode d_mode;
       unsigned int d_subslot;
      public:
@@ -44,6 +45,10 @@
 
       subslot_filter_mode get_mode(void);
       subslot_filter_mode set_mode(subslot_filter_mode mode);
+
+      /* Filtering policy */
+      filter_policy get_policy(void);
+      filter_policy set_policy(filter_policy policy);
     };
 
   } // namespace gsm
diff --git a/lib/flow_control/burst_timeslot_filter_impl.cc b/lib/flow_control/burst_timeslot_filter_impl.cc
index 20306d1..c93bc60 100644
--- a/lib/flow_control/burst_timeslot_filter_impl.cc
+++ b/lib/flow_control/burst_timeslot_filter_impl.cc
@@ -48,7 +48,8 @@
       : gr::block("burst_timeslot_filter",
               gr::io_signature::make(0, 0, 0),
               gr::io_signature::make(0, 0, 0)),
-       d_timeslot(timeslot)
+       d_timeslot(timeslot),
+       d_filter_policy(FILTER_POLICY_DEFAULT)
     {
         message_port_register_in(pmt::mp("in"));        
         message_port_register_out(pmt::mp("out"));
@@ -63,6 +64,14 @@
 
     void burst_timeslot_filter_impl::process_burst(pmt::pmt_t msg)
     {
+        if (d_filter_policy == FILTER_POLICY_DROP_ALL)
+          return;
+
+        if (d_filter_policy == FILTER_POLICY_PASS_ALL) {
+          message_port_pub(pmt::mp("out"), msg);
+          return;
+        }
+
         pmt::pmt_t header_plus_burst = pmt::cdr(msg);
         gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(header_plus_burst);
         
@@ -92,5 +101,19 @@
       return d_timeslot;
     }
 
+    /* Filtering policy */
+    filter_policy
+    burst_timeslot_filter_impl::get_policy(void)
+    {
+      return d_filter_policy;
+    }
+
+    filter_policy
+    burst_timeslot_filter_impl::set_policy(filter_policy policy)
+    {
+      d_filter_policy = policy;
+      return d_filter_policy;
+    }
+
   } /* namespace gsm */
 } /* namespace gr */
diff --git a/lib/flow_control/burst_timeslot_filter_impl.h b/lib/flow_control/burst_timeslot_filter_impl.h
index 130047e..fa54ef4 100644
--- a/lib/flow_control/burst_timeslot_filter_impl.h
+++ b/lib/flow_control/burst_timeslot_filter_impl.h
@@ -31,6 +31,7 @@
     class burst_timeslot_filter_impl : public burst_timeslot_filter
     {
      private:
+      filter_policy d_filter_policy;
       unsigned int d_timeslot;
      public:
       burst_timeslot_filter_impl(unsigned int timeslot);
@@ -40,6 +41,10 @@
       /* External API */
       unsigned int get_tn(void);
       unsigned int set_tn(unsigned int tn);
+
+      /* Filtering policy */
+      filter_policy get_policy(void);
+      filter_policy set_policy(filter_policy policy);
     };
 
   } // namespace gsm
diff --git a/lib/flow_control/dummy_burst_filter_impl.cc b/lib/flow_control/dummy_burst_filter_impl.cc
index 33c24cb..4241111 100644
--- a/lib/flow_control/dummy_burst_filter_impl.cc
+++ b/lib/flow_control/dummy_burst_filter_impl.cc
@@ -60,7 +60,8 @@
     dummy_burst_filter_impl::dummy_burst_filter_impl()
       : gr::block("dummy_burst_filter",
               gr::io_signature::make(0, 0, 0),
-              gr::io_signature::make(0, 0, 0))
+              gr::io_signature::make(0, 0, 0)),
+        d_filter_policy(FILTER_POLICY_DEFAULT)
     {
         message_port_register_in(pmt::mp("in"));        
         message_port_register_out(pmt::mp("out"));
@@ -75,6 +76,14 @@
 
     void dummy_burst_filter_impl::process_burst(pmt::pmt_t msg)
     {
+        if (d_filter_policy == FILTER_POLICY_DROP_ALL)
+          return;
+
+        if (d_filter_policy == FILTER_POLICY_PASS_ALL) {
+          message_port_pub(pmt::mp("out"), msg);
+          return;
+        }
+
         pmt::pmt_t header_plus_burst = pmt::cdr(msg);
         int8_t * burst = (int8_t *)(pmt::blob_data(header_plus_burst)) + sizeof(gsmtap_hdr);
         size_t burst_len = pmt::blob_length(header_plus_burst) - sizeof(gsmtap_hdr);
@@ -100,6 +109,20 @@
         }
         return true;
     }
+
+    /* Filtering policy */
+    filter_policy
+    dummy_burst_filter_impl::get_policy(void)
+    {
+      return d_filter_policy;
+    }
+
+    filter_policy
+    dummy_burst_filter_impl::set_policy(filter_policy policy)
+    {
+      d_filter_policy = policy;
+      return d_filter_policy;
+    }
     
   } /* namespace gsm */
 } /* namespace gr */
diff --git a/lib/flow_control/dummy_burst_filter_impl.h b/lib/flow_control/dummy_burst_filter_impl.h
index ce9c741..953ae94 100644
--- a/lib/flow_control/dummy_burst_filter_impl.h
+++ b/lib/flow_control/dummy_burst_filter_impl.h
@@ -35,10 +35,16 @@
      private:
       bool is_dummy_burst(int8_t *burst, size_t burst_len);
       static const int8_t d_dummy_burst[];
+      filter_policy d_filter_policy;
      public:
       dummy_burst_filter_impl();
       ~dummy_burst_filter_impl();
       void process_burst(pmt::pmt_t msg);
+
+      /* External API */
+      /* Filtering policy */
+      filter_policy get_policy(void);
+      filter_policy set_policy(filter_policy policy);
     };
 
   } // namespace gsm
diff --git a/swig/grgsm_swig.i b/swig/grgsm_swig.i
index 68911ae..eab179c 100644
--- a/swig/grgsm_swig.i
+++ b/swig/grgsm_swig.i
@@ -16,6 +16,7 @@
 #include "grgsm/decryption/decryption.h"
 #include "grgsm/demapping/universal_ctrl_chans_demapper.h"
 #include "grgsm/demapping/tch_f_chans_demapper.h"
+#include "grgsm/flow_control/common.h"
 #include "grgsm/flow_control/burst_timeslot_splitter.h"
 #include "grgsm/flow_control/burst_sdcch_subslot_splitter.h"
 #include "grgsm/flow_control/burst_timeslot_filter.h"
@@ -63,6 +64,7 @@
 %include "grgsm/demapping/tch_f_chans_demapper.h"
 GR_SWIG_BLOCK_MAGIC2(gsm, tch_f_chans_demapper);
 
+%include "grgsm/flow_control/common.h"
 %include "grgsm/flow_control/burst_timeslot_splitter.h"
 GR_SWIG_BLOCK_MAGIC2(gsm, burst_timeslot_splitter);
 %include "grgsm/flow_control/burst_sdcch_subslot_splitter.h"