xref: /openbmc/boost-dbus/include/dbus/filter.hpp (revision 17826fe7)
1 #ifndef DBUS_FILTER_HPP
2 #define DBUS_FILTER_HPP
3 
4 #include <boost/asio.hpp>
5 #include <dbus/detail/queue.hpp>
6 #include <dbus/message.hpp>
7 #include <dbus/connection.hpp>
8 #include <dbus/functional.hpp>
9 
10 namespace dbus {
11 
12 /// Represents a filter of incoming messages.
13 /**
14  * Filters examine incoming messages, demuxing them to multiple queues.
15  */
16 class filter
17 {
18   connection& connection_;
19   function<bool(message)> predicate_;
20   detail::queue<message> queue_;
21 
22 public:
23   // friend DBusHandlerResult connection_service::filter_callback(
24   //     DBusConnection *, DBusMessage *, void *);
25 
26   bool offer(message m)
27   {
28     bool passed = predicate_(m);
29     queue_.push(m);
30     return passed;
31   }
32 
33   template<typename MessagePredicate>
34   filter(connection& c,
35       BOOST_ASIO_MOVE_ARG(MessagePredicate) p)
36     : connection_(c),
37       predicate_(BOOST_ASIO_MOVE_CAST(MessagePredicate)(p)),
38       queue_(connection_.get_io_service())
39   {
40     connection_.new_filter(*this);
41   }
42 
43   ~filter()
44   {
45     connection_.delete_filter(*this);
46   }
47 
48   // connection& get_connection() { return connection_; }
49 
50   template<typename MessageHandler>
51   inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler,
52       void(boost::system::error_code, message))
53   async_dispatch(
54       BOOST_ASIO_MOVE_ARG(MessageHandler) handler)
55   {
56     return queue_.async_pop(
57       BOOST_ASIO_MOVE_CAST(MessageHandler)(handler));
58   }
59 
60 };
61 
62 //TODO move this to dbus::impl stat
63 DBusHandlerResult connection_service::filter_callback(
64     DBusConnection *c,
65     DBusMessage *m,
66     void *userdata)
67 {
68   try
69   {
70     filter& f = *static_cast<filter *>(userdata);
71     if(f.offer(message(m)))
72     {
73       return DBUS_HANDLER_RESULT_HANDLED;
74     }
75   } catch(...) {
76     // do not throw in C callbacks. Just don't.
77   }
78 
79   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
80 }
81 
82 void connection_service::new_filter(implementation_type& impl,
83     filter& f)
84 {
85   dbus_connection_add_filter(impl,
86       &filter_callback, &f, NULL);
87 }
88 
89 void connection_service::delete_filter(implementation_type& impl,
90     filter& f)
91 {
92   dbus_connection_remove_filter(impl,
93       &filter_callback, &f);
94 }
95 
96 
97 } // namespace dbus
98 
99 
100 #endif // DBUS_FILTER_HPP
101