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