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