blob: 5d71d95fc4678c2d2da8de4679eb86299d5eb7b4 [file] [log] [blame]
Chris Masoned0ceb8c2011-06-02 10:05:39 -07001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Chris Masone8fe2c7e2011-06-09 15:51:19 -07005#include <map>
Chris Masoned0ceb8c2011-06-02 10:05:39 -07006#include <string>
Chris Masone8fe2c7e2011-06-09 15:51:19 -07007#include <vector>
Chris Masoned0ceb8c2011-06-02 10:05:39 -07008
Chris Masone8fe2c7e2011-06-09 15:51:19 -07009#include <base/logging.h>
Chris Masoned0ceb8c2011-06-02 10:05:39 -070010#include <dbus-c++/dbus.h>
11
Chris Masone889666b2011-07-03 12:58:50 -070012#include "shill/accessor_interface.h"
Chris Masoned0ceb8c2011-06-02 10:05:39 -070013#include "shill/dbus_adaptor.h"
Chris Masone8fe2c7e2011-06-09 15:51:19 -070014#include "shill/error.h"
mukesh agrawal7a4e4002011-09-06 11:26:05 -070015#include "shill/key_value_store.h"
Chris Masoneb925cc82011-06-22 15:39:57 -070016#include "shill/property_store.h"
Chris Masone8fe2c7e2011-06-09 15:51:19 -070017
18using std::map;
19using std::string;
20using std::vector;
Chris Masoned0ceb8c2011-06-02 10:05:39 -070021
22namespace shill {
23
Chris Masone8fe2c7e2011-06-09 15:51:19 -070024// static
Paul Stewartced6a0b2011-11-08 15:32:04 -080025const char DBusAdaptor::kByteArraysSig[] = "aay";
26// static
mukesh agrawal32399322011-09-01 10:53:43 -070027const char DBusAdaptor::kPathArraySig[] = "ao";
28// static
Chris Masone8fe2c7e2011-06-09 15:51:19 -070029const char DBusAdaptor::kStringmapSig[] = "a{ss}";
30// static
Chris Masone27c4aa52011-07-02 13:10:14 -070031const char DBusAdaptor::kStringmapsSig[] = "aa{ss}";
32// static
Chris Masone8fe2c7e2011-06-09 15:51:19 -070033const char DBusAdaptor::kStringsSig[] = "as";
34
35DBusAdaptor::DBusAdaptor(DBus::Connection* conn, const string &object_path)
Chris Masoned0ceb8c2011-06-02 10:05:39 -070036 : DBus::ObjectAdaptor(*conn, object_path) {
Darin Petkov67d8ecf2011-07-26 16:03:30 -070037 VLOG(2) << "DBusAdaptor: " << object_path;
Chris Masoned0ceb8c2011-06-02 10:05:39 -070038}
39
40DBusAdaptor::~DBusAdaptor() {}
41
42// static
Chris Masoneb925cc82011-06-22 15:39:57 -070043bool DBusAdaptor::DispatchOnType(PropertyStore *store,
Chris Masone8fe2c7e2011-06-09 15:51:19 -070044 const string &name,
45 const ::DBus::Variant &value,
Chris Masonea8a2c252011-06-27 22:16:30 -070046 ::DBus::Error *error) {
mukesh agrawalffa3d042011-10-06 15:26:10 -070047 Error e;
Chris Masone8fe2c7e2011-06-09 15:51:19 -070048
49 if (DBusAdaptor::IsBool(value.signature()))
mukesh agrawalffa3d042011-10-06 15:26:10 -070050 store->SetBoolProperty(name, value.reader().get_bool(), &e);
Chris Masone8fe2c7e2011-06-09 15:51:19 -070051 else if (DBusAdaptor::IsByte(value.signature()))
mukesh agrawalffa3d042011-10-06 15:26:10 -070052 store->SetUint8Property(name, value.reader().get_byte(), &e);
Chris Masone8fe2c7e2011-06-09 15:51:19 -070053 else if (DBusAdaptor::IsInt16(value.signature()))
mukesh agrawalffa3d042011-10-06 15:26:10 -070054 store->SetInt16Property(name, value.reader().get_int16(), &e);
Chris Masone8fe2c7e2011-06-09 15:51:19 -070055 else if (DBusAdaptor::IsInt32(value.signature()))
mukesh agrawalffa3d042011-10-06 15:26:10 -070056 store->SetInt32Property(name, value.reader().get_int32(), &e);
Chris Masone3bd3c8c2011-06-13 08:20:26 -070057 else if (DBusAdaptor::IsPath(value.signature()))
mukesh agrawalffa3d042011-10-06 15:26:10 -070058 store->SetStringProperty(name, value.reader().get_path(), &e);
Chris Masone8fe2c7e2011-06-09 15:51:19 -070059 else if (DBusAdaptor::IsString(value.signature()))
mukesh agrawalffa3d042011-10-06 15:26:10 -070060 store->SetStringProperty(name, value.reader().get_string(), &e);
Chris Masone8fe2c7e2011-06-09 15:51:19 -070061 else if (DBusAdaptor::IsStringmap(value.signature()))
mukesh agrawalffa3d042011-10-06 15:26:10 -070062 store->SetStringmapProperty(name,
63 value.operator map<string, string>(),
64 &e);
65 else if (DBusAdaptor::IsStringmaps(value.signature())) {
Chris Masone27c4aa52011-07-02 13:10:14 -070066 VLOG(1) << " can't yet handle setting type " << value.signature();
mukesh agrawalffa3d042011-10-06 15:26:10 -070067 e.Populate(Error::kInternalError);
68 } else if (DBusAdaptor::IsStrings(value.signature()))
69 store->SetStringsProperty(name, value.operator vector<string>(), &e);
Chris Masone8fe2c7e2011-06-09 15:51:19 -070070 else if (DBusAdaptor::IsUint16(value.signature()))
mukesh agrawalffa3d042011-10-06 15:26:10 -070071 store->SetUint16Property(name, value.reader().get_uint16(), &e);
Chris Masone8fe2c7e2011-06-09 15:51:19 -070072 else if (DBusAdaptor::IsUint32(value.signature()))
mukesh agrawalffa3d042011-10-06 15:26:10 -070073 store->SetUint32Property(name, value.reader().get_uint32(), &e);
74 else {
Chris Masone27c4aa52011-07-02 13:10:14 -070075 NOTREACHED() << " unknown type: " << value.signature();
mukesh agrawalffa3d042011-10-06 15:26:10 -070076 e.Populate(Error::kInternalError);
Chris Masone27c4aa52011-07-02 13:10:14 -070077 }
mukesh agrawalffa3d042011-10-06 15:26:10 -070078
79 if (error != NULL) {
80 e.ToDBusError(error);
81 }
82
83 return e.IsSuccess();
Chris Masone8fe2c7e2011-06-09 15:51:19 -070084}
85
86// static
mukesh agrawalde29fa82011-09-16 16:16:36 -070087bool DBusAdaptor::GetProperties(const PropertyStore &store,
Chris Masonea8a2c252011-06-27 22:16:30 -070088 map<string, ::DBus::Variant> *out,
mukesh agrawal1830fa12011-09-26 14:31:40 -070089 ::DBus::Error */*error*/) {
Gaurav Shah1b7a6162011-11-09 11:41:01 -080090 Error e;
Chris Masonea8a2c252011-06-27 22:16:30 -070091 {
Gaurav Shah1b7a6162011-11-09 11:41:01 -080092 ReadablePropertyConstIterator<bool> it = store.GetBoolPropertiesIter();
Chris Masonea8a2c252011-06-27 22:16:30 -070093 for ( ; !it.AtEnd(); it.Advance())
Gaurav Shah1b7a6162011-11-09 11:41:01 -080094 (*out)[it.Key()] = BoolToVariant(it.Value(&e));
Chris Masonea8a2c252011-06-27 22:16:30 -070095 }
96 {
Gaurav Shah1b7a6162011-11-09 11:41:01 -080097 ReadablePropertyConstIterator<int16> it = store.GetInt16PropertiesIter();
Chris Masonea8a2c252011-06-27 22:16:30 -070098 for ( ; !it.AtEnd(); it.Advance())
Gaurav Shah1b7a6162011-11-09 11:41:01 -080099 (*out)[it.Key()] = Int16ToVariant(it.Value(&e));
Chris Masonea8a2c252011-06-27 22:16:30 -0700100 }
101 {
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800102 ReadablePropertyConstIterator<int32> it = store.GetInt32PropertiesIter();
Chris Masonea8a2c252011-06-27 22:16:30 -0700103 for ( ; !it.AtEnd(); it.Advance())
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800104 (*out)[it.Key()] = Int32ToVariant(it.Value(&e));
Chris Masonea8a2c252011-06-27 22:16:30 -0700105 }
106 {
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800107 ReadablePropertyConstIterator<string> it = store.GetStringPropertiesIter();
Chris Masonea8a2c252011-06-27 22:16:30 -0700108 for ( ; !it.AtEnd(); it.Advance())
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800109 (*out)[it.Key()] = StringToVariant(it.Value(&e));
Chris Masonea8a2c252011-06-27 22:16:30 -0700110 }
111 {
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800112 ReadablePropertyConstIterator<Stringmap> it =
113 store.GetStringmapPropertiesIter();
Chris Masonea8a2c252011-06-27 22:16:30 -0700114 for ( ; !it.AtEnd(); it.Advance())
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800115 (*out)[it.Key()]= StringmapToVariant(it.Value(&e));
Chris Masonea8a2c252011-06-27 22:16:30 -0700116 }
117 {
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800118 ReadablePropertyConstIterator<Strings> it =
119 store.GetStringsPropertiesIter();
Chris Masonea8a2c252011-06-27 22:16:30 -0700120 for ( ; !it.AtEnd(); it.Advance())
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800121 (*out)[it.Key()] = StringsToVariant(it.Value(&e));
Chris Masonea8a2c252011-06-27 22:16:30 -0700122 }
123 {
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800124 ReadablePropertyConstIterator<uint8> it = store.GetUint8PropertiesIter();
Chris Masonea8a2c252011-06-27 22:16:30 -0700125 for ( ; !it.AtEnd(); it.Advance())
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800126 (*out)[it.Key()] = ByteToVariant(it.Value(&e));
Chris Masonea8a2c252011-06-27 22:16:30 -0700127 }
128 {
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800129 ReadablePropertyConstIterator<uint16> it = store.GetUint16PropertiesIter();
Chris Masonea8a2c252011-06-27 22:16:30 -0700130 for ( ; !it.AtEnd(); it.Advance())
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800131 (*out)[it.Key()] = Uint16ToVariant(it.Value(&e));
Chris Masonea8a2c252011-06-27 22:16:30 -0700132 }
133 {
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800134 ReadablePropertyConstIterator<uint32> it = store.GetUint32PropertiesIter();
Chris Masonea8a2c252011-06-27 22:16:30 -0700135 for ( ; !it.AtEnd(); it.Advance())
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800136 (*out)[it.Key()] = Uint32ToVariant(it.Value(&e));
Chris Masonea8a2c252011-06-27 22:16:30 -0700137 }
138 return true;
139}
140
141// static
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700142void DBusAdaptor::ArgsToKeyValueStore(
143 const map<string, ::DBus::Variant> &args,
144 KeyValueStore *out,
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800145 Error *error) { // TODO(quiche): Should be ::DBus::Error?
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700146 for (map<string, ::DBus::Variant>::const_iterator it = args.begin();
147 it != args.end();
148 ++it) {
149 DBus::type<string> string_type;
150 DBus::type<bool> bool_type;
151
152 if (it->second.signature() == string_type.sig()) {
153 out->SetString(it->first, it->second.reader().get_string());
154 } else if (it->second.signature() == bool_type.sig()) {
155 out->SetBool(it->first, it->second.reader().get_bool());
156 } else {
157 error->Populate(Error::kInternalError);
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800158 return; // Skip remaining args after error.
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700159 }
160 }
161}
162
163// static
Chris Masoned0ceb8c2011-06-02 10:05:39 -0700164::DBus::Variant DBusAdaptor::BoolToVariant(bool value) {
165 ::DBus::Variant v;
166 v.writer().append_bool(value);
167 return v;
168}
169
170// static
Paul Stewartced6a0b2011-11-08 15:32:04 -0800171::DBus::Variant DBusAdaptor::ByteArraysToVariant(const ByteArrays &value) {
172 ::DBus::MessageIter writer;
173 ::DBus::Variant v;
174
Gaurav Shah7ad8e532011-11-11 17:14:49 -0800175
176 // We have to use a local because the operator<< needs a reference
177 // to work on (the lhs) but writer() returns by-value. C++ prohibits
178 // initializing non-const references from a temporary.
179 // So:
180 // v.writer() << value;
181 // would NOT automagically promote the returned value of v.writer() to
182 // a non-const reference (if you think about it, that's almost always not what
183 // you'd want. see: http://gcc.gnu.org/ml/gcc-help/2006-04/msg00075.html).
184 //
185 // One could consider changing writer() to return a reference, but then it
186 // changes writer() semantics as it can not be a const reference. writer()
187 // currently doesn't modify the original object on which it's called.
Paul Stewartced6a0b2011-11-08 15:32:04 -0800188 writer = v.writer();
189 writer << value;
190 return v;
191}
192
193// static
Chris Masone8fe2c7e2011-06-09 15:51:19 -0700194::DBus::Variant DBusAdaptor::ByteToVariant(uint8 value) {
Chris Masoned0ceb8c2011-06-02 10:05:39 -0700195 ::DBus::Variant v;
Chris Masone8fe2c7e2011-06-09 15:51:19 -0700196 v.writer().append_byte(value);
Chris Masoned0ceb8c2011-06-02 10:05:39 -0700197 return v;
198}
199
200// static
Chris Masone8fe2c7e2011-06-09 15:51:19 -0700201::DBus::Variant DBusAdaptor::Int16ToVariant(int16 value) {
202 ::DBus::Variant v;
203 v.writer().append_int16(value);
204 return v;
205}
206
207// static
208::DBus::Variant DBusAdaptor::Int32ToVariant(int32 value) {
Chris Masoned0ceb8c2011-06-02 10:05:39 -0700209 ::DBus::Variant v;
210 v.writer().append_int32(value);
211 return v;
212}
213
214// static
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700215::DBus::Variant DBusAdaptor::PathToVariant(const ::DBus::Path &value) {
216 ::DBus::Variant v;
217 v.writer().append_path(value.c_str());
218 return v;
219}
220
221// static
mukesh agrawal32399322011-09-01 10:53:43 -0700222::DBus::Variant DBusAdaptor::PathArrayToVariant(
223 const vector< ::DBus::Path> &value) {
224 ::DBus::MessageIter writer;
225 ::DBus::Variant v;
226
Gaurav Shah7ad8e532011-11-11 17:14:49 -0800227 // See note above on why we need to use a local.
mukesh agrawal32399322011-09-01 10:53:43 -0700228 writer = v.writer();
229 writer << value;
230 return v;
231}
232
233// static
Chris Masone8fe2c7e2011-06-09 15:51:19 -0700234::DBus::Variant DBusAdaptor::StringToVariant(const string &value) {
Chris Masoned0ceb8c2011-06-02 10:05:39 -0700235 ::DBus::Variant v;
236 v.writer().append_string(value.c_str());
237 return v;
238}
239
Chris Masone8fe2c7e2011-06-09 15:51:19 -0700240// static
Chris Masone889666b2011-07-03 12:58:50 -0700241::DBus::Variant DBusAdaptor::StringmapToVariant(const Stringmap &value) {
Chris Masone8fe2c7e2011-06-09 15:51:19 -0700242 ::DBus::Variant v;
243 ::DBus::MessageIter writer = v.writer();
244 writer << value;
245 return v;
246}
247
248// static
Chris Masone889666b2011-07-03 12:58:50 -0700249::DBus::Variant DBusAdaptor::StringmapsToVariant(const Stringmaps &value) {
Chris Masoneb925cc82011-06-22 15:39:57 -0700250 ::DBus::Variant v;
251 ::DBus::MessageIter writer = v.writer();
252 writer << value;
253 return v;
254}
255
256// static
Chris Masone889666b2011-07-03 12:58:50 -0700257::DBus::Variant DBusAdaptor::StringsToVariant(const Strings &value) {
Chris Masone8fe2c7e2011-06-09 15:51:19 -0700258 ::DBus::Variant v;
259 ::DBus::MessageIter writer = v.writer();
260 writer << value;
261 return v;
262}
263
264// static
Chris Masone889666b2011-07-03 12:58:50 -0700265::DBus::Variant DBusAdaptor::StrIntPairToVariant(const StrIntPair &value) {
266 ::DBus::Variant v;
267 ::DBus::MessageIter writer = v.writer();
268 writer << value.string_property();
269 writer << value.uint_property();
270 return v;
271}
272
273// static
Chris Masone8fe2c7e2011-06-09 15:51:19 -0700274::DBus::Variant DBusAdaptor::Uint16ToVariant(uint16 value) {
275 ::DBus::Variant v;
276 v.writer().append_uint16(value);
277 return v;
278}
279
280// static
281::DBus::Variant DBusAdaptor::Uint32ToVariant(uint32 value) {
282 ::DBus::Variant v;
283 v.writer().append_uint32(value);
284 return v;
285}
286
287// static
288bool DBusAdaptor::IsBool(::DBus::Signature signature) {
289 return signature == ::DBus::type<bool>::sig();
290}
291
292// static
293bool DBusAdaptor::IsByte(::DBus::Signature signature) {
294 return signature == ::DBus::type<uint8>::sig();
295}
296
297// static
Paul Stewartced6a0b2011-11-08 15:32:04 -0800298bool DBusAdaptor::IsByteArrays(::DBus::Signature signature) {
299 return signature == DBusAdaptor::kByteArraysSig;
300}
301
302// static
Chris Masone8fe2c7e2011-06-09 15:51:19 -0700303bool DBusAdaptor::IsInt16(::DBus::Signature signature) {
304 return signature == ::DBus::type<int16>::sig();
305}
306
307// static
308bool DBusAdaptor::IsInt32(::DBus::Signature signature) {
309 return signature == ::DBus::type<int32>::sig();
310}
311
312// static
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700313bool DBusAdaptor::IsPath(::DBus::Signature signature) {
314 return signature == ::DBus::type< ::DBus::Path >::sig();
315}
316
317// static
mukesh agrawal32399322011-09-01 10:53:43 -0700318bool DBusAdaptor::IsPathArray(::DBus::Signature signature) {
319 return signature == DBusAdaptor::kPathArraySig;
320}
321
322// static
Chris Masone8fe2c7e2011-06-09 15:51:19 -0700323bool DBusAdaptor::IsString(::DBus::Signature signature) {
324 return signature == ::DBus::type<string>::sig();
325}
326
327// static
328bool DBusAdaptor::IsStringmap(::DBus::Signature signature) {
329 return signature == DBusAdaptor::kStringmapSig;
330}
331
332// static
Chris Masone27c4aa52011-07-02 13:10:14 -0700333bool DBusAdaptor::IsStringmaps(::DBus::Signature signature) {
334 return signature == DBusAdaptor::kStringmapsSig;
335}
336
337// static
Chris Masone8fe2c7e2011-06-09 15:51:19 -0700338bool DBusAdaptor::IsStrings(::DBus::Signature signature) {
339 return signature == DBusAdaptor::kStringsSig;
340}
341
342// static
343bool DBusAdaptor::IsUint16(::DBus::Signature signature) {
344 return signature == ::DBus::type<uint16>::sig();
345}
346
347// static
348bool DBusAdaptor::IsUint32(::DBus::Signature signature) {
349 return signature == ::DBus::type<uint32>::sig();
350}
351
Darin Petkove5bc2cb2011-12-07 14:47:32 +0100352// static
353DBusAdaptor::Returner *DBusAdaptor::Returner::Create(DBusAdaptor *adaptor) {
354 return new Returner(adaptor);
355}
356
357DBusAdaptor::Returner::Returner(DBusAdaptor *adaptor)
358 : adaptor_(adaptor),
359 state_(kStateInitialized) {
360 VLOG(2) << __func__ << " @ " << this;
361}
362
363DBusAdaptor::Returner::~Returner() {
364 CHECK(state_ != kStateDestroyed);
365 VLOG(2) << "Destroying returner @ " << this << " state: " << state_;
366 adaptor_ = NULL;
367 state_ = kStateDestroyed;
368}
369
370void DBusAdaptor::Returner::Return() {
371 VLOG(2) << __func__ << " @ " << this << " state: " << state_;
372 switch (state_) {
373 case kStateInitialized:
374 // Service method is returning right away, without any continuation.
375 state_ = kStateReturned;
376 return;
377 case kStateDelayed: {
378 // This return happens in the continuation.
379 DBus::ObjectAdaptor::Continuation *cont =
380 adaptor_->find_continuation(this);
381 CHECK(cont);
382 adaptor_->return_now(cont);
383 delete this;
384 return;
385 }
386 default:
387 NOTREACHED() << "Unexpected state: " << state_;
388 break;
389 }
390}
391
392void DBusAdaptor::Returner::ReturnError(const Error &error) {
393 VLOG(2) << __func__ << " @ " << this << " state: " << state_;
394 switch (state_) {
395 case kStateInitialized:
396 // Service method is returning right away, without any continuation.
397 error_.CopyFrom(error);
398 state_ = kStateReturned;
399 return;
400 case kStateDelayed: {
401 // This return happens in the continuation.
402 DBus::Error dbus_error;
403 error.ToDBusError(&dbus_error);
404 DBus::ObjectAdaptor::Continuation *cont =
405 adaptor_->find_continuation(this);
406 CHECK(cont);
407 adaptor_->return_error(cont, dbus_error);
408 delete this;
409 return;
410 }
411 default:
412 NOTREACHED() << "Unexpected state: " << state_;
413 break;
414 }
415}
416
417void DBusAdaptor::Returner::DelayOrReturn(DBus::Error *error) {
418 VLOG(2) << __func__ << " @ " << this << " state: " << state_;
419 switch (state_) {
420 case kStateInitialized:
421 // Service method needs continuation so delay the return.
422 state_ = kStateDelayed;
423
424 // return_later does not return. It unwinds the stack up to the dbus-c++
425 // message handler by throwing an exception.
426 adaptor_->return_later(this);
427 return;
428 case kStateReturned:
429 // Service method has returned right away, without any continuation.
430 error_.ToDBusError(error);
431 delete this;
432 return;
433 default:
434 NOTREACHED() << "Unexpected state: " << state_;
435 break;
436 }
437}
438
Chris Masoned0ceb8c2011-06-02 10:05:39 -0700439} // namespace shill