shill: vpn: Disconnect VPN service when underlying connection disconnects.
BUG=chromium-os:30737,chromium-os:30774
TEST=unit tests, tested on device with 000OpenVPNGenesis
Change-Id: Ib350cb23edd3e68b3bd5390378789a6b60857b80
Reviewed-on: https://gerrit.chromium.org/gerrit/22461
Tested-by: Darin Petkov <petkov@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Commit-Ready: Darin Petkov <petkov@chromium.org>
diff --git a/vpn_service.cc b/vpn_service.cc
index a97bddf..1d0c89e 100644
--- a/vpn_service.cc
+++ b/vpn_service.cc
@@ -12,10 +12,13 @@
#include "shill/key_value_store.h"
#include "shill/manager.h"
+#include "shill/scope_logger.h"
#include "shill/technology.h"
#include "shill/vpn_driver.h"
+using base::Bind;
using base::StringPrintf;
+using base::Unretained;
using std::replace_if;
using std::string;
@@ -40,6 +43,7 @@
}
void VPNService::Connect(Error *error) {
+ SLOG(VPN, 2) << __func__ << " @ " << friendly_name();
if (IsConnected() || IsConnecting()) {
Error::PopulateAndLog(
error, Error::kAlreadyConnected, "VPN service already connected.");
@@ -50,6 +54,7 @@
}
void VPNService::Disconnect(Error *error) {
+ SLOG(VPN, 2) << __func__ << " @ " << friendly_name();
Service::Disconnect(error);
driver_->Disconnect();
}
@@ -119,4 +124,27 @@
set_favorite(true);
}
+void VPNService::SetConnection(const ConnectionRefPtr &connection) {
+ // Construct the connection binder here rather than in the constructor because
+ // this service's |friendly_name_| (which will be used for binder logging) may
+ // be initialized late. Also, there's really no reason to construct a binder
+ // if we never connect to this service. It's safe to use an unretained
+ // callback to driver's method because both the binder and the driver will be
+ // destroyed when this service is destructed.
+ if (!connection_binder_.get()) {
+ connection_binder_.reset(
+ new Connection::Binder(friendly_name(),
+ Bind(&VPNDriver::OnConnectionDisconnected,
+ Unretained(driver_.get()))));
+ }
+ // Note that |connection_| is a reference-counted pointer and is always set
+ // through this method. This means that the connection binder will not be
+ // notified when the connection is destructed (because we will unbind it first
+ // here when it's set to NULL, or because the binder will already be destroyed
+ // by ~VPNService) -- it will be notified only if the connection disconnects
+ // (e.g., because an underlying connection is destructed).
+ connection_binder_->Attach(connection);
+ Service::SetConnection(connection);
+}
+
} // namespace shill