| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/service.h" | 5 #include "src/service.h" |
| 6 | 6 |
| 7 #include <glog/logging.h> | 7 #include <glog/logging.h> |
| 8 | 8 |
| 9 #include "src/data_plan_provider.h" | 9 #include "src/data_plan_provider.h" |
| 10 #include "src/device.h" | 10 #include "src/device.h" |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 // Chromium OS Usage API status values | 53 // Chromium OS Usage API status values |
| 54 // NOTE: add new values to IsValidCrosUsageStatus below also | 54 // NOTE: add new values to IsValidCrosUsageStatus below also |
| 55 static const char *kCrosUsageStatusOk = "OK"; | 55 static const char *kCrosUsageStatusOk = "OK"; |
| 56 static const char *kCrosUsageStatusError = "ERROR"; | 56 static const char *kCrosUsageStatusError = "ERROR"; |
| 57 static const char *kCrosUsageStatusMalformedRequest = "MALFORMED REQUEST"; | 57 static const char *kCrosUsageStatusMalformedRequest = "MALFORMED REQUEST"; |
| 58 static const char *kCrosUsageStatusInternalError = "INTERNAL ERROR"; | 58 static const char *kCrosUsageStatusInternalError = "INTERNAL ERROR"; |
| 59 static const char *kCrosUsageStatusServiceUnavailable = "SERVICE UNAVAILABLE"; | 59 static const char *kCrosUsageStatusServiceUnavailable = "SERVICE UNAVAILABLE"; |
| 60 static const char *kCrosUsageStatusRequestRefused = "REQUEST REFUSED"; | 60 static const char *kCrosUsageStatusRequestRefused = "REQUEST REFUSED"; |
| 61 static const char *kCrosUsageStatusUnknownDevice = "UNKNOWN DEVICE"; | 61 static const char *kCrosUsageStatusUnknownDevice = "UNKNOWN DEVICE"; |
| 62 | 62 |
| 63 // GetServiceProperties retry interval |
| 64 static const guint kSecondsPerMinute = 60; |
| 65 static const guint kGetServicePropertiesIntervalSeconds = 1 * kSecondsPerMinute; |
| 66 |
| 63 Service::Service(ServiceManager * const parent, | 67 Service::Service(ServiceManager * const parent, |
| 64 DBus::Connection& connection, // NOLINT | 68 DBus::Connection& connection, // NOLINT |
| 65 const DBus::Path& path) | 69 const DBus::Path& path) |
| 66 : DBus::ObjectProxy(connection, path, kFlimflamServiceName), | 70 : DBus::ObjectProxy(connection, path, kFlimflamServiceName), |
| 67 parent_(CHECK_NOTNULL(parent)), connection_(connection), path_(path), | 71 parent_(CHECK_NOTNULL(parent)), connection_(connection), path_(path), |
| 68 state_(kStateUnknown), type_(kTypeUnknown), device_(NULL), | 72 state_(kStateUnknown), type_(kTypeUnknown), device_(NULL), |
| 69 provider_(NULL), request_in_progress_(false), | 73 provider_(NULL), request_in_progress_(false), |
| 70 update_timeout_source_(NULL), policy_(NULL), | 74 update_timeout_source_(NULL), policy_(NULL), |
| 71 is_default_service_(false) { | 75 is_default_service_(false), get_properties_source_id_(0), |
| 72 // init our state with a GetProperties() call to our Flimflam service path | 76 retrying_get_properties_(false) { |
| 73 // we'll update this state by monitoring PropertyChanged signals | 77 // schedule a GetProperties() call to our Flimflam service path to init state |
| 74 GetServiceProperties(); | 78 // we'll keep trying periodically until we succeed |
| 79 // we'll subsequently update this state by monitoring PropertyChanged signals |
| 80 get_properties_source_id_ = |
| 81 g_idle_add(StaticGetServicePropertiesCallback, this); |
| 82 if (get_properties_source_id_ == 0) { |
| 83 LOG(ERROR) << path_ << ": ctor: g_idle_add failed"; |
| 84 } |
| 75 } | 85 } |
| 76 | 86 |
| 77 Service::~Service() { | 87 Service::~Service() { |
| 78 DeleteCarrierState(); | 88 DeleteCarrierState(); |
| 79 DeleteDataPlans(&data_plans_); | 89 DeleteDataPlans(&data_plans_); |
| 80 if (device_ != NULL) { | 90 if (device_ != NULL) { |
| 81 DLOG(INFO) << path_ << ": deleting device " << device_->GetPath(); | 91 DLOG(INFO) << path_ << ": deleting device " << device_->GetPath(); |
| 82 delete device_; | 92 delete device_; |
| 83 device_ = NULL; | 93 device_ = NULL; |
| 84 } | 94 } |
| 95 if (get_properties_source_id_ != 0 && |
| 96 !g_source_remove(get_properties_source_id_)) { |
| 97 DLOG(WARNING) << path_ << ": dtor: g_source_remove failed"; |
| 98 } |
| 85 } | 99 } |
| 86 | 100 |
| 87 const DBus::Path& Service::GetPath() const { | 101 const DBus::Path& Service::GetPath() const { |
| 88 return path_; | 102 return path_; |
| 89 } | 103 } |
| 90 | 104 |
| 91 Service::State Service::GetState() const { | 105 Service::State Service::GetState() const { |
| 92 return state_; | 106 return state_; |
| 93 } | 107 } |
| 94 | 108 |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 void Service::OnFlimflamOnline() { | 355 void Service::OnFlimflamOnline() { |
| 342 DLOG(INFO) << path_ << ": OnFlimflamOnline"; | 356 DLOG(INFO) << path_ << ": OnFlimflamOnline"; |
| 343 ReconsiderSendingUsageRequests(); | 357 ReconsiderSendingUsageRequests(); |
| 344 } | 358 } |
| 345 | 359 |
| 346 void Service::OnFlimflamOffline() { | 360 void Service::OnFlimflamOffline() { |
| 347 DLOG(INFO) << path_ << ": OnFlimflamOffline"; | 361 DLOG(INFO) << path_ << ": OnFlimflamOffline"; |
| 348 ReconsiderSendingUsageRequests(); | 362 ReconsiderSendingUsageRequests(); |
| 349 } | 363 } |
| 350 | 364 |
| 365 // glib integration interface |
| 366 |
| 367 guint Service::GetGetPropertiesSourceId() const { |
| 368 return get_properties_source_id_; |
| 369 } |
| 370 |
| 371 void Service::SetGetPropertiesSourceId(guint source_id) { |
| 372 get_properties_source_id_ = source_id; |
| 373 } |
| 374 |
| 375 bool Service::RetryingGetProperties() const { |
| 376 return retrying_get_properties_; |
| 377 } |
| 378 |
| 379 void Service::OnRetryingGetProperties(bool retrying) { |
| 380 retrying_get_properties_ = retrying; |
| 381 } |
| 382 |
| 351 // Private methods | 383 // Private methods |
| 352 | 384 |
| 353 Service::State Service::StateFromString(const std::string& state) const { | 385 Service::State Service::StateFromString(const std::string& state) const { |
| 354 if (state == kFlimflamServiceStateIdle) { | 386 if (state == kFlimflamServiceStateIdle) { |
| 355 return kStateIdle; | 387 return kStateIdle; |
| 356 } | 388 } |
| 357 if (state == kFlimflamServiceStateCarrier) { | 389 if (state == kFlimflamServiceStateCarrier) { |
| 358 return kStateCarrier; | 390 return kStateCarrier; |
| 359 } | 391 } |
| 360 if (state == kFlimflamServiceStateAssociation) { | 392 if (state == kFlimflamServiceStateAssociation) { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 } | 464 } |
| 433 usage_url_ = usage_url; | 465 usage_url_ = usage_url; |
| 434 if (provider_ != NULL) { | 466 if (provider_ != NULL) { |
| 435 DCHECK(usage_url_ != provider_->GetUsageUrl()); | 467 DCHECK(usage_url_ != provider_->GetUsageUrl()); |
| 436 StopSendingUsageRequests(); | 468 StopSendingUsageRequests(); |
| 437 provider_->SetUsageUrl(usage_url_); | 469 provider_->SetUsageUrl(usage_url_); |
| 438 ReconsiderSendingUsageRequests(); | 470 ReconsiderSendingUsageRequests(); |
| 439 } | 471 } |
| 440 } | 472 } |
| 441 | 473 |
| 442 void Service::GetServiceProperties() { | 474 // static |
| 475 gboolean Service::StaticGetServicePropertiesCallback(gpointer data) { |
| 476 Service *service = reinterpret_cast<Service*>(data); |
| 477 CHECK_NOTNULL(service); |
| 478 DCHECK_NE(service->GetGetPropertiesSourceId(), 0); |
| 479 if (!service->GetServiceProperties()) { |
| 480 // call failed, so try again later |
| 481 DLOG(WARNING) << service->GetPath() |
| 482 << ": StaticGetServicePropertiesCallback: " |
| 483 << "GetServiceProperties failed, will retry in " |
| 484 << kGetServicePropertiesIntervalSeconds << " secs"; |
| 485 // if we've arrived here from our first g_idle_add call, set up a timer |
| 486 if (!service->RetryingGetProperties()) { |
| 487 guint source_id = |
| 488 g_timeout_add_seconds(kGetServicePropertiesIntervalSeconds, |
| 489 StaticGetServicePropertiesCallback, service); |
| 490 service->SetGetPropertiesSourceId(source_id); |
| 491 if (source_id == 0) { |
| 492 LOG(ERROR) << service->GetPath() |
| 493 << ": StaticGetServicePropertiesCallback: " |
| 494 << "g_timeout_add_seconds failed"; |
| 495 return FALSE; // get rid of old glib source and give up |
| 496 } |
| 497 service->OnRetryingGetProperties(true); |
| 498 // get rid of our old glib source, but our new timer will call us |
| 499 return FALSE; |
| 500 } |
| 501 // otherwise, our timer is already set up |
| 502 // return TRUE to indicate that we want to be called again later |
| 503 return TRUE; |
| 504 } |
| 505 service->SetGetPropertiesSourceId(0); |
| 506 service->OnRetryingGetProperties(false); |
| 507 return FALSE; // we succeeded, so don't repeat |
| 508 } |
| 509 |
| 510 bool Service::GetServiceProperties() { |
| 443 DLOG(INFO) << path_ << ": GetServiceProperties"; | 511 DLOG(INFO) << path_ << ": GetServiceProperties"; |
| 444 PropertyMap properties; | 512 PropertyMap properties; |
| 445 // dbus-c++ throws exceptions | 513 // dbus-c++ throws exceptions |
| 446 // invoke the "Existing Non-conformant Code" clause of the style guide and | 514 // invoke the "Existing Non-conformant Code" clause of the style guide and |
| 447 // isolate the rest of the system from this | 515 // isolate the rest of the system from this |
| 448 try { | 516 try { |
| 449 // TODO(vlaviano): make this call asynchronous | 517 // TODO(vlaviano): make this call asynchronous |
| 450 properties = GetProperties(); | 518 properties = GetProperties(); |
| 451 } catch (DBus::Error& error) { // NOLINT | 519 } catch (DBus::Error& error) { // NOLINT |
| 452 LOG(WARNING) << path_ | 520 LOG(WARNING) << path_ |
| 453 << ": GetServiceProperties: GetProperties() -> Exception: " | 521 << ": GetServiceProperties: GetProperties() -> Exception: " |
| 454 << error.name() << ": " << error.message(); | 522 << error.name() << ": " << error.message(); |
| 455 // TODO(vlaviano): schedule another attempt later | 523 return false; |
| 456 return; | |
| 457 } catch (...) { // NOLINT | 524 } catch (...) { // NOLINT |
| 458 LOG(WARNING) << path_ | 525 LOG(WARNING) << path_ |
| 459 << ": GetServiceProperties: GetProperties() -> Exception"; | 526 << ": GetServiceProperties: GetProperties() -> Exception"; |
| 460 // TODO(vlaviano): schedule another attempt later | 527 return false; |
| 461 return; | |
| 462 } | 528 } |
| 463 DLOG(INFO) << path_ << ": GetServiceProperties: Received " | 529 DLOG(INFO) << path_ << ": GetServiceProperties: Received " |
| 464 << properties.size() << " properties"; | 530 << properties.size() << " properties"; |
| 465 | 531 |
| 466 // grab the properties in which we're interested | 532 // grab the properties in which we're interested |
| 467 PropertyMap::const_iterator it; | 533 PropertyMap::const_iterator it; |
| 468 it = properties.find(kFlimflamServiceDeviceProperty); | 534 it = properties.find(kFlimflamServiceDeviceProperty); |
| 469 if (it != properties.end()) { | 535 if (it != properties.end()) { |
| 470 const DBus::Variant& value = static_cast<DBus::Variant>(it->second); | 536 const DBus::Variant& value = static_cast<DBus::Variant>(it->second); |
| 471 OnDeviceUpdate(value.reader().get_path()); | 537 OnDeviceUpdate(value.reader().get_path()); |
| 472 } else { | 538 } else { |
| 473 DLOG(WARNING) << path_ << ": GetServiceProperties: no Device property"; | 539 DLOG(WARNING) << path_ << ": GetServiceProperties: no Device property"; |
| 474 } | 540 } |
| 475 it = properties.find(kFlimflamServiceStateProperty); | 541 it = properties.find(kFlimflamServiceStateProperty); |
| 476 if (it != properties.end()) { | 542 if (it != properties.end()) { |
| 477 const DBus::Variant& value = static_cast<DBus::Variant>(it->second); | 543 const DBus::Variant& value = static_cast<DBus::Variant>(it->second); |
| 478 OnStateUpdate(value.reader().get_string()); | 544 OnStateUpdate(value.reader().get_string()); |
| 479 } else { | 545 } else { |
| 480 DLOG(WARNING) << path_ << ": GetServiceProperties: no State property"; | 546 DLOG(WARNING) << path_ << ": GetServiceProperties: no State property"; |
| 481 } | 547 } |
| 482 it = properties.find(kFlimflamServiceTypeProperty); | 548 it = properties.find(kFlimflamServiceTypeProperty); |
| 483 if (it != properties.end()) { | 549 if (it != properties.end()) { |
| 484 const DBus::Variant& value = static_cast<DBus::Variant>(it->second); | 550 const DBus::Variant& value = static_cast<DBus::Variant>(it->second); |
| 485 OnTypeUpdate(value.reader().get_string()); | 551 OnTypeUpdate(value.reader().get_string()); |
| 486 } else { | 552 } else { |
| 487 DLOG(WARNING) << path_ << ": GetServiceProperties: no Type property"; | 553 DLOG(WARNING) << path_ << ": GetServiceProperties: no Type property"; |
| 488 } | 554 } |
| 489 // don't expect to find Cellular.* properties if we're not a cellular service | 555 // don't expect to find Cellular.* properties if we're not a cellular service |
| 490 if (type_ != kTypeCellular) { | 556 if (type_ != kTypeCellular) { |
| 491 return; | 557 return true; |
| 492 } | 558 } |
| 493 it = properties.find(kFlimflamServiceUsageUrlProperty); | 559 it = properties.find(kFlimflamServiceUsageUrlProperty); |
| 494 if (it != properties.end()) { | 560 if (it != properties.end()) { |
| 495 const DBus::Variant& value = static_cast<DBus::Variant>(it->second); | 561 const DBus::Variant& value = static_cast<DBus::Variant>(it->second); |
| 496 OnUsageUrlUpdate(value.reader().get_string()); | 562 OnUsageUrlUpdate(value.reader().get_string()); |
| 497 } else { | 563 } else { |
| 498 DLOG(WARNING) << path_ | 564 DLOG(WARNING) << path_ |
| 499 << ": GetServiceProperties: no Cellular.UsageUrl property"; | 565 << ": GetServiceProperties: no Cellular.UsageUrl property"; |
| 500 } | 566 } |
| 567 return true; |
| 501 } | 568 } |
| 502 | 569 |
| 503 void Service::DeleteDataPlans(DataPlanList *data_plans) { | 570 void Service::DeleteDataPlans(DataPlanList *data_plans) { |
| 504 DCHECK(data_plans != NULL); | 571 DCHECK(data_plans != NULL); |
| 505 while (!data_plans->empty()) { | 572 while (!data_plans->empty()) { |
| 506 DataPlan *plan = *data_plans->begin(); | 573 DataPlan *plan = *data_plans->begin(); |
| 507 DCHECK(plan != NULL); | 574 DCHECK(plan != NULL); |
| 508 DLOG(INFO) << path_ << ": DeleteDataPlans: deleting plan: " | 575 DLOG(INFO) << path_ << ": DeleteDataPlans: deleting plan: " |
| 509 << plan->GetName(); | 576 << plan->GetName(); |
| 510 delete plan; | 577 delete plan; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 } | 624 } |
| 558 | 625 |
| 559 gboolean Service::UpdateTimeoutCallback() { | 626 gboolean Service::UpdateTimeoutCallback() { |
| 560 DLOG(INFO) << path_ << ": UpdateTimeoutCallback"; | 627 DLOG(INFO) << path_ << ": UpdateTimeoutCallback"; |
| 561 RequestUsageUpdate(); | 628 RequestUsageUpdate(); |
| 562 return TRUE; | 629 return TRUE; |
| 563 } | 630 } |
| 564 | 631 |
| 565 // static | 632 // static |
| 566 gboolean Service::StaticUpdateTimeoutCallback(gpointer data) { | 633 gboolean Service::StaticUpdateTimeoutCallback(gpointer data) { |
| 567 CHECK_NOTNULL(data); | 634 Service *service = reinterpret_cast<Service*>(data); |
| 568 return reinterpret_cast<Service*>(data)->UpdateTimeoutCallback(); | 635 CHECK_NOTNULL(service); |
| 636 return service->UpdateTimeoutCallback(); |
| 569 } | 637 } |
| 570 | 638 |
| 571 bool Service::CreateUpdateTimer() { | 639 bool Service::CreateUpdateTimer() { |
| 572 DCHECK(provider_ != NULL); | 640 DCHECK(provider_ != NULL); |
| 573 DCHECK(policy_ != NULL); | 641 DCHECK(policy_ != NULL); |
| 574 guint idle_seconds = policy_->GetUpdateTimerIdleSecs(data_plans_); | 642 guint idle_seconds = policy_->GetUpdateTimerIdleSecs(data_plans_); |
| 575 DLOG(INFO) << path_ << ": CreateUpdateTimer: idle_seconds = " << idle_seconds; | 643 DLOG(INFO) << path_ << ": CreateUpdateTimer: idle_seconds = " << idle_seconds; |
| 576 if (update_timeout_source_ != NULL) { | 644 if (update_timeout_source_ != NULL) { |
| 577 DLOG(WARNING) << path_ << ": CreateUpdateTimer: timer already running"; | 645 DLOG(WARNING) << path_ << ": CreateUpdateTimer: timer already running"; |
| 578 return false; | 646 return false; |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 713 void Service::ReconsiderSendingUsageRequests() { | 781 void Service::ReconsiderSendingUsageRequests() { |
| 714 DLOG(INFO) << path_ << ": ReconsiderSendingUsageRequests"; | 782 DLOG(INFO) << path_ << ": ReconsiderSendingUsageRequests"; |
| 715 if (!IsSendingUsageRequests() && ShouldSendUsageRequests()) { | 783 if (!IsSendingUsageRequests() && ShouldSendUsageRequests()) { |
| 716 StartSendingUsageRequests(); | 784 StartSendingUsageRequests(); |
| 717 } else if (IsSendingUsageRequests() && !ShouldSendUsageRequests()) { | 785 } else if (IsSendingUsageRequests() && !ShouldSendUsageRequests()) { |
| 718 StopSendingUsageRequests(); | 786 StopSendingUsageRequests(); |
| 719 } | 787 } |
| 720 } | 788 } |
| 721 | 789 |
| 722 } // namespace cashew | 790 } // namespace cashew |
| OLD | NEW |