| Index: src/service.cc
|
| diff --git a/src/service.cc b/src/service.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a05f431705f3f92e7c81bf2e96d7eff053f5ab22
|
| --- /dev/null
|
| +++ b/src/service.cc
|
| @@ -0,0 +1,277 @@
|
| +// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "src/service.h"
|
| +
|
| +#include <glog/logging.h>
|
| +
|
| +#include "src/device.h"
|
| +
|
| +namespace cashew {
|
| +
|
| +// Flimflam Service D-Bus identifiers
|
| +static const char* kFlimflamServiceName = "org.chromium.flimflam";
|
| +
|
| +// Flimflam Service property names
|
| +static const char *kFlimflamServiceDeviceProperty = "Device";
|
| +static const char *kFlimflamServiceStateProperty = "State";
|
| +static const char* kFlimflamServiceTypeProperty = "Type";
|
| +
|
| +// Flimflam Service on-the-wire State values
|
| +static const char* kFlimflamServiceStateIdle = "idle";
|
| +static const char* kFlimflamServiceStateCarrier = "carrier";
|
| +static const char* kFlimflamServiceStateAssociation = "association";
|
| +static const char* kFlimflamServiceStateConfiguration = "configuration";
|
| +static const char* kFlimflamServiceStateReady = "ready";
|
| +static const char* kFlimflamServiceStateDisconnect = "disconnect";
|
| +static const char* kFlimflamServiceStateFailure = "failure";
|
| +static const char* kFlimflamServiceStateActivationFailure =
|
| + "activation-failure";
|
| +
|
| +// Flimflam Service on-the-wire Type values
|
| +static const char* kFlimflamServiceTypeEthernet = "ethernet";
|
| +static const char* kFlimflamServiceTypeWifi = "wifi";
|
| +static const char* kFlimflamServiceTypeWimax = "wimax";
|
| +static const char* kFlimflamServiceTypeBluetooth = "bluetooth";
|
| +static const char* kFlimflamServiceTypeCellular = "cellular";
|
| +
|
| +Service::Service(DBus::Connection& connection, // NOLINT
|
| + const DBus::Path& path)
|
| + : DBus::ObjectProxy(connection, path, kFlimflamServiceName),
|
| + connection_(connection), path_(path), state_(kStateUnknown),
|
| + type_(kTypeUnknown), device_(NULL) {
|
| + // init our state with a GetProperties() call to our Flimflam service path
|
| + // we'll update this state by monitoring PropertyChanged signals
|
| + GetServiceProperties();
|
| +
|
| + // init our data plans list with a hardcoded plan
|
| + // TODO(vlaviano): implement backend and return real data
|
| + AddHardcodedDataPlan();
|
| +}
|
| +
|
| +Service::~Service() {
|
| + DeleteDataPlans();
|
| + if (device_ != NULL) {
|
| + DLOG(INFO) << path_ << ": deleting device " << device_->GetPath();
|
| + delete device_;
|
| + device_ = NULL;
|
| + }
|
| +}
|
| +
|
| +const DBus::Path& Service::GetPath() const {
|
| + return path_;
|
| +}
|
| +
|
| +Service::State Service::GetState() const {
|
| + return state_;
|
| +}
|
| +
|
| +Service::Type Service::GetType() const {
|
| + return type_;
|
| +}
|
| +
|
| +Device* Service::GetDevice() const {
|
| + return device_;
|
| +}
|
| +
|
| +DBusDataPlanList Service::GetDBusDataPlans() const {
|
| + DBusDataPlanList dbus_data_plans;
|
| + DataPlanList::const_iterator it;
|
| + for (it = data_plans_.begin(); it != data_plans_.end(); ++it) {
|
| + DataPlan *plan = *it;
|
| + DCHECK(plan != NULL);
|
| + dbus_data_plans.push_back(plan->ToDBusFormat());
|
| + }
|
| + return dbus_data_plans;
|
| +}
|
| +
|
| +// Flimflam Service D-Bus Proxy methods
|
| +
|
| +void Service::PropertyChanged(const std::string& property_name,
|
| + const DBus::Variant& new_value) {
|
| + DLOG(INFO) << path_ << ": PropertyChanged: property_name = " << property_name;
|
| + if (property_name.compare(kFlimflamServiceDeviceProperty) == 0) {
|
| + OnDeviceUpdate(new_value.reader().get_path());
|
| + } else if (property_name.compare(kFlimflamServiceStateProperty) == 0) {
|
| + OnStateUpdate(new_value.reader().get_string());
|
| + } else if (property_name.compare(kFlimflamServiceTypeProperty) == 0) {
|
| + OnTypeUpdate(new_value.reader().get_string());
|
| + } else {
|
| + // we don't care about this property
|
| + }
|
| +}
|
| +
|
| +// Private methods
|
| +
|
| +Service::State Service::StateFromString(const std::string& state) const {
|
| + if (state.compare(kFlimflamServiceStateIdle) == 0) {
|
| + return kStateIdle;
|
| + }
|
| + if (state.compare(kFlimflamServiceStateCarrier) == 0) {
|
| + return kStateCarrier;
|
| + }
|
| + if (state.compare(kFlimflamServiceStateAssociation) == 0) {
|
| + return kStateAssociation;
|
| + }
|
| + if (state.compare(kFlimflamServiceStateConfiguration) == 0) {
|
| + return kStateConfiguration;
|
| + }
|
| + if (state.compare(kFlimflamServiceStateReady) == 0) {
|
| + return kStateReady;
|
| + }
|
| + if (state.compare(kFlimflamServiceStateDisconnect) == 0) {
|
| + return kStateDisconnect;
|
| + }
|
| + if (state.compare(kFlimflamServiceStateFailure) == 0) {
|
| + return kStateFailure;
|
| + }
|
| + if (state.compare(kFlimflamServiceStateActivationFailure) == 0) {
|
| + return kStateActivationFailure;
|
| + }
|
| + return kStateUnknown;
|
| +}
|
| +
|
| +Service::Type Service::TypeFromString(const std::string& type) const {
|
| + if (type.compare(kFlimflamServiceTypeEthernet) == 0) {
|
| + return kTypeEthernet;
|
| + }
|
| + if (type.compare(kFlimflamServiceTypeWifi) == 0) {
|
| + return kTypeWifi;
|
| + }
|
| + if (type.compare(kFlimflamServiceTypeWimax) == 0) {
|
| + return kTypeWimax;
|
| + }
|
| + if (type.compare(kFlimflamServiceTypeBluetooth) == 0) {
|
| + return kTypeBluetooth;
|
| + }
|
| + if (type.compare(kFlimflamServiceTypeCellular) == 0) {
|
| + return kTypeCellular;
|
| + }
|
| + return kTypeUnknown;
|
| +}
|
| +
|
| +void Service::OnDeviceUpdate(const DBus::Path& device_path) {
|
| + DLOG(INFO) << path_ << ": OnDeviceUpdate: device_path = " << device_path;
|
| +
|
| + // if there's an existing device with a non-matching path: destroy it and
|
| + // fall through to make a new one below.
|
| + if (device_ != NULL && device_->GetPath().compare(device_path)) {
|
| + LOG(WARNING) << path_ << ": OnDeviceUpdate: device path changed from "
|
| + << device_->GetPath() << " to " << device_path;
|
| + delete device_;
|
| + device_ = NULL;
|
| + }
|
| +
|
| + // if there's an existing device with matching path: all is well
|
| + if (device_ != NULL) {
|
| + return;
|
| + }
|
| +
|
| + // if there's no existing device: make one
|
| + device_ = new(std::nothrow) Device(connection_, device_path);
|
| + if (device_ == NULL) {
|
| + LOG(ERROR) << path_ << ": OnDeviceUpdate: couldn't create device for "
|
| + << device_path;
|
| + return;
|
| + }
|
| + DLOG(INFO) << path_ << ": OnDeviceUpdate: created device for "
|
| + << device_path;
|
| +}
|
| +
|
| +void Service::OnStateUpdate(const std::string& state) {
|
| + DLOG(INFO) << path_ << ": OnStateUpdate: state = " << state;
|
| + state_ = StateFromString(state);
|
| + // TODO(vlaviano): react to state changes
|
| + // note that ready does not necessarily mean that we're the default route
|
| +}
|
| +
|
| +void Service::OnTypeUpdate(const std::string& type) {
|
| + DLOG(INFO) << path_ << ": OnTypeUpdate: type = " << type;
|
| + type_ = TypeFromString(type);
|
| + if (type_ != kTypeCellular) {
|
| + LOG(WARNING) << path_ << ": OnTypeUpdate: type is not cellular!";
|
| + }
|
| +}
|
| +
|
| +void Service::GetServiceProperties() {
|
| + DLOG(INFO) << path_ << ": GetServiceProperties";
|
| + PropertyMap properties;
|
| + // dbus-c++ throws exceptions
|
| + // invoke the "Existing Non-conformant Code" clause of the style guide and
|
| + // isolate the rest of the system from this
|
| + try {
|
| + // TODO(vlaviano): make this call asynchronous
|
| + properties = GetProperties();
|
| + } catch (DBus::Error& error) { // NOLINT
|
| + LOG(WARNING) << path_
|
| + << ": GetServiceProperties: GetProperties() -> Exception: "
|
| + << error.name() << ": " << error.message();
|
| + // TODO(vlaviano): schedule another attempt later
|
| + return;
|
| + } catch (...) { // NOLINT
|
| + LOG(WARNING) << path_
|
| + << ": GetServiceProperties: GetProperties() -> Exception";
|
| + // TODO(vlaviano): schedule another attempt later
|
| + return;
|
| + }
|
| + DLOG(INFO) << "Received " << properties.size() << " properties";
|
| +
|
| + // grab the properties in which we're interested
|
| + PropertyMap::const_iterator it;
|
| + it = properties.find(kFlimflamServiceDeviceProperty);
|
| + if (it != properties.end()) {
|
| + const DBus::Variant& value = static_cast<DBus::Variant>(it->second);
|
| + OnDeviceUpdate(value.reader().get_path());
|
| + } else {
|
| + DLOG(WARNING) << path_ << ": GetServiceProperties: no Device property";
|
| + }
|
| + it = properties.find(kFlimflamServiceStateProperty);
|
| + if (it != properties.end()) {
|
| + const DBus::Variant& value = static_cast<DBus::Variant>(it->second);
|
| + OnStateUpdate(value.reader().get_string());
|
| + } else {
|
| + DLOG(WARNING) << path_ << ": GetServiceProperties: no State property";
|
| + }
|
| + it = properties.find(kFlimflamServiceTypeProperty);
|
| + if (it != properties.end()) {
|
| + const DBus::Variant& value = static_cast<DBus::Variant>(it->second);
|
| + OnTypeUpdate(value.reader().get_string());
|
| + } else {
|
| + DLOG(WARNING) << path_ << ": GetServiceProperties: no Type property";
|
| + }
|
| +}
|
| +
|
| +void Service::DeleteDataPlans() {
|
| + while (!data_plans_.empty()) {
|
| + DataPlan *plan = *data_plans_.begin();
|
| + DCHECK(plan != NULL);
|
| + DLOG(INFO) << path_ << ": DeleteDataPlans: deleting plan: "
|
| + << plan->GetName();
|
| + delete plan;
|
| + data_plans_.erase(data_plans_.begin());
|
| + }
|
| +}
|
| +
|
| +void Service::AddHardcodedDataPlan() {
|
| + const std::string name = "Chromium OS Test Plan";
|
| + DataPlan::Type type = DataPlan::kTypeMeteredPaid;
|
| + base::Time update_time = base::Time::Now();
|
| + base::TimeDelta twelve_hours = base::TimeDelta::FromHours(12);
|
| + base::Time start_time = base::Time::Now() - twelve_hours;
|
| + base::Time end_time = base::Time::Now() + twelve_hours;
|
| + Bytes data_bytes_max = 100*1024*1024; // 100 MB
|
| + Bytes data_bytes_used = 30*1024*1024; // 30 MB
|
| +
|
| + DataPlan *plan = new(std::nothrow) DataPlan(name, type, update_time,
|
| + start_time, end_time,
|
| + data_bytes_max, data_bytes_used);
|
| + if (plan == NULL) {
|
| + LOG(ERROR) << path_ << ": AddHardcodedDataPlan: could not create plan";
|
| + return;
|
| + }
|
| +
|
| + data_plans_.push_back(plan);
|
| +}
|
| +
|
| +} // namespace cashew
|
|
|