147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/* 247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Copyright 2004 The WebRTC Project Authors. All rights reserved. 347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * 447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Use of this source code is governed by a BSD-style license 547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * that can be found in the LICENSE file in the root of the source 647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * tree. An additional intellectual property rights grant can be found 747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * in the file PATENTS. All contributing project authors may 847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * be found in the AUTHORS file in the root of the source tree. 947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */ 1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef HAVE_DBUS_GLIB 1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/dbus.h" 1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <glib.h> 1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/logging.h" 1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/thread.h" 1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc { 2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Avoid static object construction/destruction on startup/shutdown. 2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic pthread_once_t g_dbus_init_once = PTHREAD_ONCE_INIT; 2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic LibDBusGlibSymbolTable *g_dbus_symbol = NULL; 2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Releases DBus-Glib symbols. 2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic void ReleaseDBusGlibSymbol() { 2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (g_dbus_symbol != NULL) { 2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org delete g_dbus_symbol; 3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org g_dbus_symbol = NULL; 3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Loads DBus-Glib symbols. 3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic void InitializeDBusGlibSymbol() { 3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // This is thread safe. 3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (NULL == g_dbus_symbol) { 3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org g_dbus_symbol = new LibDBusGlibSymbolTable(); 3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Loads dbus-glib 4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (NULL == g_dbus_symbol || !g_dbus_symbol->Load()) { 4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_WARNING) << "Failed to load dbus-glib symbol table."; 4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ReleaseDBusGlibSymbol(); 4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Nothing we can do if atexit() failed. Just ignore its returned value. 4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org atexit(ReleaseDBusGlibSymbol); 4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orginline static LibDBusGlibSymbolTable *GetSymbols() { 5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return DBusMonitor::GetDBusGlibSymbolTable(); 5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Implementation of class DBusSigMessageData 5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgDBusSigMessageData::DBusSigMessageData(DBusMessage *message) 5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org : TypedMessageData<DBusMessage *>(message) { 5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GetSymbols()->dbus_message_ref()(data()); 5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgDBusSigMessageData::~DBusSigMessageData() { 6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GetSymbols()->dbus_message_unref()(data()); 6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Implementation of class DBusSigFilter 6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Builds a DBus filter string from given DBus path, interface and member. 6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstd::string DBusSigFilter::BuildFilterString(const std::string &path, 6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const std::string &interface, 7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const std::string &member) { 7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org std::string ret(DBUS_TYPE "='" DBUS_SIGNAL "'"); 7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!path.empty()) { 7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ret += ("," DBUS_PATH "='"); 7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ret += path; 7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ret += "'"; 7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!interface.empty()) { 7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ret += ("," DBUS_INTERFACE "='"); 7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ret += interface; 8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ret += "'"; 8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!member.empty()) { 8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ret += ("," DBUS_MEMBER "='"); 8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ret += member; 8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ret += "'"; 8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return ret; 8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Forwards the message to the given instance. 9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgDBusHandlerResult DBusSigFilter::DBusCallback(DBusConnection *dbus_conn, 9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org DBusMessage *message, 9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org void *instance) { 9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(instance); 9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (instance) { 9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return static_cast<DBusSigFilter *>(instance)->Callback(message); 9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Posts a message to caller thread. 10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgDBusHandlerResult DBusSigFilter::Callback(DBusMessage *message) { 10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (caller_thread_) { 10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org caller_thread_->Post(this, DSM_SIGNAL, new DBusSigMessageData(message)); 10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Don't "eat" the message here. Let it pop up. 10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// From MessageHandler. 11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid DBusSigFilter::OnMessage(Message *message) { 11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (message != NULL && DSM_SIGNAL == message->message_id) { 11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org DBusSigMessageData *msg = 11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org static_cast<DBusSigMessageData *>(message->pdata); 11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (msg) { 11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ProcessSignal(msg->data()); 11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org delete msg; 11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Definition of private class DBusMonitoringThread. 12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// It creates a worker-thread to listen signals on DBus. The worker-thread will 12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// be running in a priate GMainLoop forever until either Stop() has been invoked 12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// or it hits an error. 12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass DBusMonitor::DBusMonitoringThread : public rtc::Thread { 12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public: 12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org explicit DBusMonitoringThread(DBusMonitor *monitor, 12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GMainContext *context, 13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GMainLoop *mainloop, 13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org std::vector<DBusSigFilter *> *filter_list) 13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org : monitor_(monitor), 13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org context_(context), 13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org mainloop_(mainloop), 13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org connection_(NULL), 13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org idle_source_(NULL), 13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org filter_list_(filter_list) { 13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(monitor_); 13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(context_); 14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(mainloop_); 14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(filter_list_); 14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org virtual ~DBusMonitoringThread() { 14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Stop(); 14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Override virtual method of Thread. Context: worker-thread. 14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org virtual void Run() { 15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(NULL == connection_); 15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Setup DBus connection and start monitoring. 15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org monitor_->OnMonitoringStatusChanged(DMS_INITIALIZING); 15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!Setup()) { 15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "DBus monitoring setup failed."; 15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org monitor_->OnMonitoringStatusChanged(DMS_FAILED); 15747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CleanUp(); 15847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 15947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 16047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org monitor_->OnMonitoringStatusChanged(DMS_RUNNING); 16147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org g_main_loop_run(mainloop_); 16247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org monitor_->OnMonitoringStatusChanged(DMS_STOPPED); 16347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 16447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Done normally. Clean up DBus connection. 16547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CleanUp(); 16647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 16747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 16847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 16947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Override virtual method of Thread. Context: caller-thread. 17047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org virtual void Stop() { 17147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(NULL == idle_source_); 17247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Add an idle source and let the gmainloop quit on idle. 17347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org idle_source_ = g_idle_source_new(); 17447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (idle_source_) { 17547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org g_source_set_callback(idle_source_, &Idle, this, NULL); 17647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org g_source_attach(idle_source_, context_); 17747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 17847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "g_idle_source_new() failed."; 17947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org QuitGMainloop(); // Try to quit anyway. 18047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 18147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 18247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Thread::Stop(); // Wait for the thread. 18347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 18447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 18547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org private: 18647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Registers all DBus filters. 18747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org void RegisterAllFilters() { 18847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(NULL != GetSymbols()->dbus_g_connection_get_connection()( 18947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org connection_)); 19047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 19147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org for (std::vector<DBusSigFilter *>::iterator it = filter_list_->begin(); 19247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org it != filter_list_->end(); ++it) { 19347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org DBusSigFilter *filter = (*it); 19447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!filter) { 19547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "DBusSigFilter list corrupted."; 19647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org continue; 19747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 19847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 19947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GetSymbols()->dbus_bus_add_match()( 20047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GetSymbols()->dbus_g_connection_get_connection()(connection_), 20147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org filter->filter().c_str(), NULL); 20247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 20347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!GetSymbols()->dbus_connection_add_filter()( 20447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GetSymbols()->dbus_g_connection_get_connection()(connection_), 20547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org &DBusSigFilter::DBusCallback, filter, NULL)) { 20647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "dbus_connection_add_filter() failed." 20747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << "Filter: " << filter->filter(); 20847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org continue; 20947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 21047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 21147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 21247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 21347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Unregisters all DBus filters. 21447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org void UnRegisterAllFilters() { 21547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(NULL != GetSymbols()->dbus_g_connection_get_connection()( 21647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org connection_)); 21747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 21847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org for (std::vector<DBusSigFilter *>::iterator it = filter_list_->begin(); 21947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org it != filter_list_->end(); ++it) { 22047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org DBusSigFilter *filter = (*it); 22147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!filter) { 22247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "DBusSigFilter list corrupted."; 22347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org continue; 22447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 22547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GetSymbols()->dbus_connection_remove_filter()( 22647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GetSymbols()->dbus_g_connection_get_connection()(connection_), 22747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org &DBusSigFilter::DBusCallback, filter); 22847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 22947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 23047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 23147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Sets up the monitoring thread. 23247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org bool Setup() { 23347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org g_main_context_push_thread_default(context_); 23447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 23547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Start connection to dbus. 23647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // If dbus daemon is not running, returns false immediately. 23747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org connection_ = GetSymbols()->dbus_g_bus_get_private()(monitor_->type_, 23847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org context_, NULL); 23947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (NULL == connection_) { 24047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "dbus_g_bus_get_private() unable to get connection."; 24147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 24247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 24347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (NULL == GetSymbols()->dbus_g_connection_get_connection()(connection_)) { 24447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "dbus_g_connection_get_connection() returns NULL. " 24547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << "DBus daemon is probably not running."; 24647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 24747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 24847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 24947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Application don't exit if DBus daemon die. 25047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GetSymbols()->dbus_connection_set_exit_on_disconnect()( 25147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GetSymbols()->dbus_g_connection_get_connection()(connection_), FALSE); 25247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 25347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Connect all filters. 25447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org RegisterAllFilters(); 25547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 25647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 25747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 25847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 25947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Cleans up the monitoring thread. 26047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org void CleanUp() { 26147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (idle_source_) { 26247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // We did an attach() with the GSource, so we need to destroy() it. 26347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org g_source_destroy(idle_source_); 26447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // We need to unref() the GSource to end the last reference we got. 26547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org g_source_unref(idle_source_); 26647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org idle_source_ = NULL; 26747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 26847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (connection_) { 26947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (GetSymbols()->dbus_g_connection_get_connection()(connection_)) { 27047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org UnRegisterAllFilters(); 27147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GetSymbols()->dbus_connection_close()( 27247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GetSymbols()->dbus_g_connection_get_connection()(connection_)); 27347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 27447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GetSymbols()->dbus_g_connection_unref()(connection_); 27547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org connection_ = NULL; 27647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 27747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org g_main_loop_unref(mainloop_); 27847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org mainloop_ = NULL; 27947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org g_main_context_unref(context_); 28047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org context_ = NULL; 28147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 28247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 28347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Handles callback on Idle. We only add this source when ready to stop. 28447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org static gboolean Idle(gpointer data) { 28547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org static_cast<DBusMonitoringThread *>(data)->QuitGMainloop(); 28647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return TRUE; 28747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 28847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 28947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // We only hit this when ready to quit. 29047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org void QuitGMainloop() { 29147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org g_main_loop_quit(mainloop_); 29247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 29347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 29447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org DBusMonitor *monitor_; 29547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 29647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GMainContext *context_; 29747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GMainLoop *mainloop_; 29847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org DBusGConnection *connection_; 29947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GSource *idle_source_; 30047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 30147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org std::vector<DBusSigFilter *> *filter_list_; 30247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}; 30347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 30447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Implementation of class DBusMonitor 30547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 30647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Returns DBus-Glib symbol handle. Initialize it first if hasn't. 30747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgLibDBusGlibSymbolTable *DBusMonitor::GetDBusGlibSymbolTable() { 30847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // This is multi-thread safe. 30947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org pthread_once(&g_dbus_init_once, InitializeDBusGlibSymbol); 31047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 31147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return g_dbus_symbol; 31247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}; 31347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 31447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Creates an instance of DBusMonitor 31547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgDBusMonitor *DBusMonitor::Create(DBusBusType type) { 31647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (NULL == DBusMonitor::GetDBusGlibSymbolTable()) { 31747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 31847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 31947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return new DBusMonitor(type); 32047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 32147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 32247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgDBusMonitor::DBusMonitor(DBusBusType type) 32347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org : type_(type), 32447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org status_(DMS_NOT_INITIALIZED), 32547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org monitoring_thread_(NULL) { 32647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(type_ == DBUS_BUS_SYSTEM || type_ == DBUS_BUS_SESSION); 32747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 32847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 32947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgDBusMonitor::~DBusMonitor() { 33047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org StopMonitoring(); 33147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 33247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 33347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool DBusMonitor::AddFilter(DBusSigFilter *filter) { 33447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (monitoring_thread_) { 33547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 33647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 33747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!filter) { 33847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 33947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 34047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org filter_list_.push_back(filter); 34147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 34247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 34347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 34447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool DBusMonitor::StartMonitoring() { 34547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!monitoring_thread_) { 34647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org g_type_init(); 34747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org g_thread_init(NULL); 34847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GetSymbols()->dbus_g_thread_init()(); 34947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 35047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GMainContext *context = g_main_context_new(); 35147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (NULL == context) { 35247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "g_main_context_new() failed."; 35347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 35447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 35547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 35647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GMainLoop *mainloop = g_main_loop_new(context, FALSE); 35747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (NULL == mainloop) { 35847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "g_main_loop_new() failed."; 35947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org g_main_context_unref(context); 36047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 36147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 36247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 36347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org monitoring_thread_ = new DBusMonitoringThread(this, context, mainloop, 36447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org &filter_list_); 36547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (monitoring_thread_ == NULL) { 36647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "Failed to create DBus monitoring thread."; 36747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org g_main_context_unref(context); 36847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org g_main_loop_unref(mainloop); 36947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return false; 37047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 37147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org monitoring_thread_->Start(); 37247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 37347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 37447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 37547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 37647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool DBusMonitor::StopMonitoring() { 37747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (monitoring_thread_) { 37847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org monitoring_thread_->Stop(); 37947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org monitoring_thread_ = NULL; 38047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 38147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return true; 38247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 38347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 38447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgDBusMonitor::DBusMonitorStatus DBusMonitor::GetStatus() { 38547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return status_; 38647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 38747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 38847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid DBusMonitor::OnMonitoringStatusChanged(DBusMonitorStatus status) { 38947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org status_ = status; 39047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 39147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 39247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#undef LATE 39347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 39447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} // namespace rtc 39547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 39647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif // HAVE_DBUS_GLIB 397