blob: 938301c49de924ef533aba5c49bed41d24e8b485 [file] [log] [blame]
David Sodmanbbcb0522014-09-19 10:34:07 -07001/*
2 * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7#include <stdlib.h>
8#include "dbus.h"
9#include "util.h"
10
11struct _dbus_t {
12 DBusConnection *conn;
13 int terminate;
14 struct {
15 DBusObjectPathVTable vtable;
16 const char* interface;
17 const char* signal;
18 const char* rule;
19 void* user_data;
20 dbus_message_handler_t signal_handler;
21 } signal;
22};
23
24dbus_t* dbus_init()
25{
26 dbus_t* new_dbus;
27 DBusError err;
28
29 dbus_error_init(&err);
30
31 new_dbus = (dbus_t*)calloc(1, sizeof(*new_dbus));
32
33 new_dbus->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
34 if (dbus_error_is_set(&err)) {
35 LOG(ERROR, "Cannot get dbus connection");
36 free(new_dbus);
37 return NULL;
38 }
39
40 dbus_connection_set_exit_on_disconnect(new_dbus->conn, FALSE);
41
42 return new_dbus;
43}
44
45
David Sodman003faed2014-11-03 09:02:10 -080046bool dbus_method_call0(dbus_t* dbus, const char* service_name,
47 const char* service_path, const char* service_interface,
48 const char* method)
49{
50 DBusMessage *msg = NULL;
51
52 msg = dbus_message_new_method_call(service_name,
53 service_path, service_interface, method);
54
55 if (!msg)
56 return false;
57
58 if (!dbus_connection_send_with_reply_and_block(dbus->conn,
David Sodmanbf3f2842014-11-12 08:26:58 -080059 msg, 3000, NULL)) {
David Sodman003faed2014-11-03 09:02:10 -080060 dbus_message_unref(msg);
61 return false;
62 }
63
64 dbus_connection_flush(dbus->conn);
65 dbus_message_unref(msg);
66
67 return true;
68}
69
70bool dbus_method_call1(dbus_t* dbus, const char* service_name,
David Sodmanbbcb0522014-09-19 10:34:07 -070071 const char* service_path, const char* service_interface,
David Sodman19e4f9d2015-03-10 11:11:09 -070072 const char* method, int arg_type, void* param)
David Sodmanbbcb0522014-09-19 10:34:07 -070073{
74 DBusMessage *msg = NULL;
75
76 msg = dbus_message_new_method_call(service_name,
77 service_path, service_interface, method);
78
79 if (!msg)
80 return false;
81
82 if (!dbus_message_append_args(msg,
David Sodman19e4f9d2015-03-10 11:11:09 -070083 arg_type, param, DBUS_TYPE_INVALID)) {
David Sodmanbbcb0522014-09-19 10:34:07 -070084 dbus_message_unref(msg);
85 return false;
86 }
87
88 if (!dbus_connection_send_with_reply_and_block(dbus->conn,
David Sodmanbf3f2842014-11-12 08:26:58 -080089 msg, 3000, NULL)) {
David Sodmanbbcb0522014-09-19 10:34:07 -070090 dbus_message_unref(msg);
91 return false;
92 }
93
94 dbus_connection_flush(dbus->conn);
95 dbus_message_unref(msg);
96
97 return true;
98}
99
100static void
101dbus_path_unregister_function(DBusConnection *connection, void *user_data)
102{
103}
104
105static DBusHandlerResult
106dbus_message_function(DBusConnection *connection,
107 DBusMessage *message, void* user_data)
108{
109 dbus_t* dbus = (dbus_t*)user_data;
110
111 if (dbus_message_is_signal(message, dbus->signal.interface,
112 dbus->signal.signal)) {
113 dbus->signal.signal_handler(dbus, dbus->signal.user_data);
114 }
115 return DBUS_HANDLER_RESULT_HANDLED;
116}
117
118bool dbus_signal_match_handler(
119 dbus_t* dbus,
120 const char* signal,
121 const char* path,
122 const char* interface,
123 const char* rule,
124 dbus_message_handler_t handler,
125 void *user_data)
126{
127 DBusError err;
128 dbus->signal.vtable.unregister_function = dbus_path_unregister_function;
129 dbus->signal.vtable.message_function = dbus_message_function;
130 dbus->signal.signal_handler = handler;
131 dbus->signal.signal = signal;
132 dbus->signal.user_data = user_data;
133 dbus->signal.interface = interface;
134
135 if (!dbus_connection_register_object_path(dbus->conn, path,
136 &dbus->signal.vtable, dbus)) {
137 LOG(ERROR, "register_object_path failed");
138 return false;
139 }
140
141 dbus_error_init(&err);
142 dbus_bus_add_match(dbus->conn, rule, &err);
143 if (dbus_error_is_set(&err)) {
144 LOG(ERROR, "add_match failed: %s", err.message);
145 return false;
146 }
147
148 return true;
149}
150
151
David Sodman3430aae2014-11-10 08:15:01 -0800152int dbus_wait_for_messages(dbus_t *dbus, int64_t timeout_ms)
David Sodmanbbcb0522014-09-19 10:34:07 -0700153{
David Sodman3430aae2014-11-10 08:15:01 -0800154 int ret = DBUS_STATUS_NOERROR;
155 int64_t terminate_ms = -1;
156 if (timeout_ms > 0)
157 terminate_ms = get_monotonic_time_ms() + timeout_ms;
158
David Sodmanbbcb0522014-09-19 10:34:07 -0700159 while (dbus_connection_read_write_dispatch(dbus->conn, -1)) {
David Sodman3430aae2014-11-10 08:15:01 -0800160 if ((terminate_ms > 0) && (get_monotonic_time_ms() > terminate_ms)) {
161 dbus->terminate = true;
162 ret = DBUS_STATUS_TIMEOUT;
163 }
164
David Sodmanbbcb0522014-09-19 10:34:07 -0700165 if (dbus->terminate)
166 break;
167 }
David Sodman3430aae2014-11-10 08:15:01 -0800168
169 return ret;
David Sodmanbbcb0522014-09-19 10:34:07 -0700170}
171
172
173void dbus_stop_wait(dbus_t* dbus)
174{
175 dbus->terminate = true;
176}
177
178
179void dbus_destroy(dbus_t* dbus)
180{
181 /* FIXME - not sure what the right counterpart to
182 dbus_bus_get() is, unref documentation is rather
183 unclear. Not a big issue but it would be nice to
184 clean up properly here */
185 /* dbus_connection_unref(dbus->conn); */
186 free(dbus);
187}