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