blob: d1832badd0251a93612ab92ddffda39bb77aff6e [file] [log] [blame]
// Copyright (c) 2009 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 <dlfcn.h>
#include <glib-object.h>
#include <map>
#include <vector>
#include <base/logging.h>
#include <base/values.h>
#include "chromeos_cros_api.h" // NOLINT
#include "chromeos_network.h" // NOLINT
// TODO(stevenjb): Remove testing of deprecated code; add new tests.
#include "chromeos_network_deprecated.h" // NOLINT
#include "chromeos/dbus/dbus.h" // NOLINT
#include "chromeos/glib/object.h" // NOLINT
#include "monitor_utils.h" //NOLINT
void DumpServices(const chromeos::SystemInfo* info);
void DumpDataPlans(const char* service_path,
const chromeos::CellularDataPlanList* data_plan_list);
void PrintProperty(const char* path,
const char* key,
const Value* value);
// Callback is an example of how to use the network monitoring functionality.
class CallbackMonitorNetwork {
public:
// You can store whatever state is needed in the function object.
explicit CallbackMonitorNetwork() :
count_(0) {
}
// Note, you MUST copy the service status struct since it will be freed
// the moment this function returns.
//
// DO NOT DO THIS
// Struct my_status = status;
//
// DO THIS INSTEAD
// Struct my_status = {};
// my_status = MakeACopyOf(status);
// ...
static void Run(void* object,
const char* path,
const char* key,
const Value* value) {
PrintProperty(path, key, value);
if (strcmp(key, "Services") == 0) {
chromeos::SystemInfo* info = chromeos::GetSystemInfo();
DumpServices(info);
chromeos::FreeSystemInfo(info);
}
CallbackMonitorNetwork* self = static_cast<CallbackMonitorNetwork*>(object);
++self->count_;
}
private:
int count_;
};
// CallbackMonitorDataPlan is an example of how to use the cellular
// data plan monitoring functionality.
class CallbackMonitorDataPlan {
public:
explicit CallbackMonitorDataPlan() :
count_(0) {
}
static void Run(void* object,
const char* path,
const chromeos::CellularDataPlanList* data) {
DumpDataPlans(path, data);
CallbackMonitorDataPlan* self =
static_cast<CallbackMonitorDataPlan*>(object);
++self->count_;
}
private:
int count_;
};
struct ServiceMonitor {
ServiceMonitor() : monitor(NULL), callback(NULL), last_scangen(0) { }
~ServiceMonitor() { delete callback; }
chromeos::PropertyChangeMonitor monitor;
CallbackMonitorNetwork *callback;
int last_scangen;
static int scangen;
};
int ServiceMonitor::scangen;
typedef std::map<std::string, ServiceMonitor*> MonitorMap;
MonitorMap monitor_map;
void PrintProperty(const char* path,
const char* key,
const Value* value) {
std::string prelude("PropertyChanged [");
prelude += path;
prelude += "] ";
prelude += key;
prelude += " : ";
if (value->IsType(Value::TYPE_STRING)) {
std::string strval;
value->GetAsString(&strval);
LOG(INFO) << prelude << "\"" << strval << "\"";
} else if (value->IsType(Value::TYPE_BOOLEAN)) {
bool boolval;
value->GetAsBoolean(&boolval);
LOG(INFO) << prelude << boolval;
} else if (value->IsType(Value::TYPE_INTEGER)) {
int intval;
value->GetAsInteger(&intval);
LOG(INFO) << prelude << intval;
} else if (value->IsType(Value::TYPE_LIST)) {
const ListValue* list = static_cast<const ListValue*>(value);
Value *itemval;
std::string liststr;
size_t index = 0;
while (list->Get(index, &itemval)) {
if (!itemval->IsType(Value::TYPE_STRING)) {
++index;
continue;
}
std::string itemstr;
itemval->GetAsString(&itemstr);
liststr += itemstr;
++index;
if (index < list->GetSize())
liststr += ", ";
}
LOG(INFO) << prelude << "\"" << liststr << "\"";
} else if (value->IsType(Value::TYPE_DICTIONARY)) {
const DictionaryValue* dict = static_cast<const DictionaryValue*>(value);
std::string items;
std::string itemval;
size_t n = 0;
DictionaryValue::key_iterator iter = dict->begin_keys();
while (iter != dict->end_keys()) {
std::string key = *iter;
items += "{'" + key + "': '";
if (dict->GetStringWithoutPathExpansion(key, &itemval))
items += itemval + "'}";
else
items += "<not-a-string>'}";
if (n < dict->size())
items += ", ";
++iter;
++n;
}
LOG(INFO) << prelude << items;
} else
LOG(INFO) << prelude << "<type " << value->GetType() << ">";
}
void DumpDeviceInfo(const chromeos::DeviceInfo& device,
chromeos::ConnectionType type) {
LOG(INFO) << " Name:" << device.name
<< ", Type:" << device.type
<< ", Scanning: " << device.scanning;
if (type == chromeos::TYPE_CELLULAR) {
LOG(INFO) << " Carrier:" << device.carrier;
LOG(INFO) << " MEID=" << device.MEID
<< ", IMEI=" << device.IMEI
<< ", IMSI=" << device.IMSI
<< ", ESN=" << device.ESN
<< ", MDN=" << device.MDN
<< ", MIN=" << device.MIN;
LOG(INFO) << " ModelID=" << device.model_id
<< ", Manufacturer=" << device.manufacturer;
LOG(INFO) << " Firmware=" << device.firmware_revision
<< ", Hardware=" << device.hardware_revision;
LOG(INFO) << " Last Update=" << device.last_update
<< ", PRL Version=" << device.PRL_version;
}
}
void DumpCarrierInfo(const chromeos::CarrierInfo& carrier) {
LOG(INFO) << " Operator:" << carrier.operator_name
<< ", Code=" << carrier.operator_code;
LOG(INFO) << " Payment URL:" << carrier.payment_url;
}
void DumpService(const chromeos::ServiceInfo& info) {
const char* passphrase;
if (info.passphrase != NULL && strlen(info.passphrase) != 0)
passphrase = "******";
else
passphrase = "\"\"";
LOG(INFO) << " \"" << info.name << "\"";
LOG(INFO) << " Service=" << info.service_path
<< ", Name=" << info.name;
LOG(INFO) << " Type=" << info.type
<< ", Active=" << info.is_active;
LOG(INFO) << " Mode=" << info.mode
<< ", Security=" << info.security
<< ", State=" << info.state
<< ", Error=" << info.error;
LOG(INFO) << " PassphraseRequired=" << info.passphrase_required
<< ", Passphrase=" << passphrase;
LOG(INFO) << " Identity=" << info.identity
<< ", CertPath=" << info.cert_path;
LOG(INFO) << " Strength=" << info.strength
<< ", Favorite=" << info.favorite
<< ", AutoConnect=" << info.auto_connect;
if (info.device_path)
LOG(INFO) << " Device=" << info.device_path;
if (info.device_info)
DumpDeviceInfo(*info.device_info, info.type);
if (info.type == chromeos::TYPE_CELLULAR)
LOG(INFO) << " Activation State=" << info.activation_state
<< ", Technology=" << info.network_technology
<< ", RoamingState=" << info.roaming_state
<< ", ConnectivityState=" << info.connectivity_state
<< ", (RestrictedPool=" << info.restricted_pool << ")";
if (info.carrier_info)
DumpCarrierInfo(*info.carrier_info);
}
// Dumps the contents of ServiceStatus to the log.
void DumpServices(const chromeos::SystemInfo* info) {
if (info == NULL)
return;
LOG(INFO) << "Network status:";
++ServiceMonitor::scangen;
for (int i = 0; i < info->service_size; i++) {
chromeos::ServiceInfo *sinfo = &info->services[i];
DumpService(*sinfo);
ServiceMonitor *servmon = monitor_map[sinfo->service_path];
if (servmon == NULL) {
LOG(INFO) << "New service " << sinfo->service_path;
servmon = new ServiceMonitor;
servmon->callback = new CallbackMonitorNetwork();
monitor_map[sinfo->service_path] = servmon;
}
servmon->last_scangen = ServiceMonitor::scangen;
// For any service that has just entered the ready (i..e, connected)
// state, start monitoring it for property changes. For any service
// that has just left the ready state, stop monitoring it. Also
// start monitoring if there is just one service.
if (sinfo->state == chromeos::STATE_READY ||
sinfo->type == chromeos::TYPE_CELLULAR) {
if (servmon->monitor == NULL) {
LOG(INFO) << "Start monitoring service " << sinfo->service_path;
servmon->monitor = chromeos::MonitorNetworkService(
&CallbackMonitorNetwork::Run,
sinfo->service_path,
servmon->callback);
}
} else if (servmon->monitor != NULL) {
LOG(INFO) << "Stop monitoring service " << sinfo->service_path;
chromeos::DisconnectPropertyChangeMonitor(servmon->monitor);
servmon->monitor = NULL;
}
}
// Go through monitor_map and remove mappings for
// services that are no longer in the service list.
LOG(INFO) << "Removing services.";
MonitorMap::iterator it;
for (it = monitor_map.begin(); it != monitor_map.end(); ++it) {
ServiceMonitor* servmon = it->second;
if (servmon->last_scangen != ServiceMonitor::scangen) {
if (servmon->monitor != NULL) {
LOG(INFO) << "Service " << it->first << " gone, stop monitoring";
chromeos::DisconnectPropertyChangeMonitor(servmon->monitor);
} else
LOG(INFO) << "Service " << it->first << " no longer present";
monitor_map.erase(it);
delete servmon;
}
}
}
void DumpDataPlans(const char* modem_service_path,
const chromeos::CellularDataPlanList* data_plan_list) {
LOG(INFO) << "Data Plans for: '" << modem_service_path;
for (unsigned int i = 0; i < data_plan_list->plans_size; i++) {
const chromeos::CellularDataPlanInfo* data =
data_plan_list->GetCellularDataPlan(i);
LOG(INFO) << "Plan Name: " << data->plan_name
<< ", Type=" << data->plan_type
<< ", Update Time=" << data->update_time
<< ", Start Time=" << data->plan_start_time
<< ", End Time=" << data->plan_end_time
<< ", Data Bytes=" << data->plan_data_bytes
<< ", Bytes Used=" << data->data_bytes_used;
}
}
// A simple example program demonstrating how to use the ChromeOS network API.
int main(int argc, const char** argv) {
::g_type_init();
GMainLoop* loop = ::g_main_loop_new(NULL, false);
DCHECK(loop) << "Failed to create main loop";
if (!LoadCrosLibrary(argv))
LOG(INFO) << "Failed to load cros .so";
// Synchronous request of network info.
LOG(INFO) << "Calling chromeos::GetSystemInfo()";
chromeos::SystemInfo* network_info = chromeos::GetSystemInfo();
DCHECK(network_info) << "Unable to get SystemInfo";
LOG(INFO) << "Enabled network devices:";
int technologies = network_info->enabled_technologies;
if (technologies & (1 << chromeos::TYPE_ETHERNET))
LOG(INFO) << " ethernet";
if (technologies & (1 << chromeos::TYPE_WIFI))
LOG(INFO) << " wifi";
if (technologies & (1 << chromeos::TYPE_WIMAX))
LOG(INFO) << " wimax";
if (technologies & (1 << chromeos::TYPE_BLUETOOTH))
LOG(INFO) << " bluetooth";
if (technologies & (1 << chromeos::TYPE_CELLULAR))
LOG(INFO) << " cellular";
DumpServices(network_info);
// Synchronous request of data plans.
LOG(INFO) << "Retrieving Cellular Data Plans:";
for (int i = 0; i < network_info->service_size; ++i) {
chromeos::ServiceInfo *sinfo = &network_info->services[i];
if (sinfo->type != chromeos::TYPE_CELLULAR) {
continue;
}
LOG(INFO) << " Retrieving Data Plans for: " << sinfo->service_path;
chromeos::CellularDataPlanList* data_plan_list;
data_plan_list = chromeos::RetrieveCellularDataPlans(sinfo->service_path);
if (data_plan_list) {
DumpDataPlans(sinfo->service_path, data_plan_list);
chromeos::FreeCellularDataPlanList(data_plan_list);
} else {
LOG(WARNING) << " RetrieveCellularDataPlans failed for: "
<< sinfo->service_path;
}
}
// Asynchronous network monitoring.
LOG(INFO) << "Starting Monitor Network:";
CallbackMonitorNetwork callback_network;
chromeos::PropertyChangeMonitor connection_network =
chromeos::MonitorNetworkManager(&CallbackMonitorNetwork::Run,
&callback_network);
// Asynchronous data plan monitoring.
LOG(INFO) << "Starting Monitor Data Plan:";
CallbackMonitorDataPlan callback_dataplan;
chromeos::DataPlanUpdateMonitor connection_dataplan =
chromeos::MonitorCellularDataPlan(&CallbackMonitorDataPlan::Run,
&callback_dataplan);
LOG(INFO) << "Requesting Cellular Data Plan Updates:";
for (int i = 0; i < network_info->service_size; i++) {
chromeos::ServiceInfo *sinfo = &network_info->services[i];
if (sinfo->type == chromeos::TYPE_CELLULAR) {
LOG(INFO) << " Requesting Data Plan Update for: " << sinfo->service_path;
chromeos::RequestCellularDataPlanUpdate(sinfo->service_path);
}
}
LOG(INFO) << "Starting g_main_loop.";
::g_main_loop_run(loop);
LOG(INFO) << "Shutting down.";
chromeos::FreeSystemInfo(network_info);
chromeos::DisconnectPropertyChangeMonitor(connection_network);
chromeos::DisconnectDataPlanUpdateMonitor(connection_dataplan);
return 0;
}