blob: 51751872b4cadd4a74a81a4be60279a874ae809e [file] [log] [blame]
Darin Petkovb451d6e2012-04-23 11:56:41 +02001// Copyright (c) 2012 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
5#include "shill/vpn_driver.h"
6
7#include <base/string_util.h>
8#include <chromeos/dbus/service_constants.h>
9
Darin Petkov0e9735d2012-04-24 12:33:45 +020010#include "shill/connection.h"
Darin Petkov602303f2012-06-06 12:15:59 +020011#include "shill/event_dispatcher.h"
Christopher Wileyb691efd2012-08-09 13:51:51 -070012#include "shill/logging.h"
Darin Petkov0e9735d2012-04-24 12:33:45 +020013#include "shill/manager.h"
Darin Petkovb451d6e2012-04-23 11:56:41 +020014#include "shill/property_accessor.h"
15#include "shill/property_store.h"
Darin Petkovb451d6e2012-04-23 11:56:41 +020016#include "shill/store_interface.h"
17
18using std::string;
19
20namespace shill {
21
Darin Petkov602303f2012-06-06 12:15:59 +020022// static
23const int VPNDriver::kDefaultConnectTimeoutSeconds = 60;
24
25VPNDriver::VPNDriver(EventDispatcher *dispatcher,
26 Manager *manager,
Darin Petkov0e9735d2012-04-24 12:33:45 +020027 const Property *properties,
28 size_t property_count)
Darin Petkov602303f2012-06-06 12:15:59 +020029 : weak_ptr_factory_(this),
30 dispatcher_(dispatcher),
31 manager_(manager),
Darin Petkov0e9735d2012-04-24 12:33:45 +020032 properties_(properties),
Darin Petkov602303f2012-06-06 12:15:59 +020033 property_count_(property_count),
34 connect_timeout_seconds_(kDefaultConnectTimeoutSeconds) {}
Darin Petkovb451d6e2012-04-23 11:56:41 +020035
36VPNDriver::~VPNDriver() {}
37
38bool VPNDriver::Load(StoreInterface *storage, const string &storage_id) {
39 SLOG(VPN, 2) << __func__;
40 for (size_t i = 0; i < property_count_; i++) {
41 if ((properties_[i].flags & Property::kEphemeral)) {
42 continue;
43 }
44 const string property = properties_[i].property;
45 string value;
Darin Petkovcb715292012-04-25 13:04:37 +020046 bool loaded = (properties_[i].flags & Property::kCredential) ?
Darin Petkovb451d6e2012-04-23 11:56:41 +020047 storage->GetCryptedString(storage_id, property, &value) :
48 storage->GetString(storage_id, property, &value);
49 if (loaded) {
50 args_.SetString(property, value);
51 } else {
52 args_.RemoveString(property);
53 }
54 }
55 return true;
56}
57
Darin Petkovcb715292012-04-25 13:04:37 +020058bool VPNDriver::Save(StoreInterface *storage,
59 const string &storage_id,
60 bool save_credentials) {
Darin Petkovb451d6e2012-04-23 11:56:41 +020061 SLOG(VPN, 2) << __func__;
62 for (size_t i = 0; i < property_count_; i++) {
63 if ((properties_[i].flags & Property::kEphemeral)) {
64 continue;
65 }
Darin Petkovcb715292012-04-25 13:04:37 +020066 bool credential = (properties_[i].flags & Property::kCredential);
Darin Petkovb451d6e2012-04-23 11:56:41 +020067 const string property = properties_[i].property;
Darin Petkov4e9066f2012-06-11 13:17:06 +020068 if (!args_.ContainsString(property) || (credential && !save_credentials)) {
Darin Petkovb451d6e2012-04-23 11:56:41 +020069 storage->DeleteKey(storage_id, property);
Darin Petkov4e9066f2012-06-11 13:17:06 +020070 continue;
71 }
72 string value = args_.GetString(property);
73 if (credential) {
Darin Petkovb451d6e2012-04-23 11:56:41 +020074 storage->SetCryptedString(storage_id, property, value);
75 } else {
76 storage->SetString(storage_id, property, value);
77 }
78 }
79 return true;
80}
81
Darin Petkovcb715292012-04-25 13:04:37 +020082void VPNDriver::UnloadCredentials() {
83 SLOG(VPN, 2) << __func__;
84 for (size_t i = 0; i < property_count_; i++) {
85 if ((properties_[i].flags &
86 (Property::kEphemeral | Property::kCredential))) {
87 args_.RemoveString(properties_[i].property);
88 }
89 }
90}
91
Darin Petkovb451d6e2012-04-23 11:56:41 +020092void VPNDriver::InitPropertyStore(PropertyStore *store) {
93 SLOG(VPN, 2) << __func__;
94 for (size_t i = 0; i < property_count_; i++) {
95 store->RegisterDerivedString(
96 properties_[i].property,
97 StringAccessor(
98 new CustomMappedAccessor<VPNDriver, string, size_t>(
99 this,
100 &VPNDriver::ClearMappedProperty,
101 &VPNDriver::GetMappedProperty,
102 &VPNDriver::SetMappedProperty,
103 i)));
104 }
105
Darin Petkovb536a742012-04-26 11:31:28 +0200106 store->RegisterDerivedKeyValueStore(
Darin Petkovb451d6e2012-04-23 11:56:41 +0200107 flimflam::kProviderProperty,
Darin Petkovb536a742012-04-26 11:31:28 +0200108 KeyValueStoreAccessor(
109 new CustomAccessor<VPNDriver, KeyValueStore>(
Darin Petkovb451d6e2012-04-23 11:56:41 +0200110 this, &VPNDriver::GetProvider, NULL)));
111}
112
113void VPNDriver::ClearMappedProperty(const size_t &index, Error *error) {
114 CHECK(index < property_count_);
115 if (args_.ContainsString(properties_[index].property)) {
116 args_.RemoveString(properties_[index].property);
117 } else {
118 error->Populate(Error::kNotFound, "Property is not set");
119 }
120}
121
122string VPNDriver::GetMappedProperty(const size_t &index, Error *error) {
123 // Provider properties are set via SetProperty calls to "Provider.XXX",
124 // however, they are retrieved via a GetProperty call, which returns all
125 // properties in a single "Provider" dict. Therefore, none of the individual
126 // properties in the kProperties are available for enumeration in
127 // GetProperties. Instead, they are retrieved via GetProvider below.
128 error->Populate(Error::kInvalidArguments,
129 "Provider properties are not read back in this manner");
130 return string();
131}
132
133void VPNDriver::SetMappedProperty(
134 const size_t &index, const string &value, Error *error) {
135 CHECK(index < property_count_);
136 args_.SetString(properties_[index].property, value);
137}
138
Darin Petkovb536a742012-04-26 11:31:28 +0200139KeyValueStore VPNDriver::GetProvider(Error *error) {
Darin Petkovb451d6e2012-04-23 11:56:41 +0200140 SLOG(VPN, 2) << __func__;
141 string provider_prefix = string(flimflam::kProviderProperty) + ".";
Darin Petkovb536a742012-04-26 11:31:28 +0200142 KeyValueStore provider_properties;
Darin Petkovb451d6e2012-04-23 11:56:41 +0200143
144 for (size_t i = 0; i < property_count_; i++) {
Darin Petkovcb715292012-04-25 13:04:37 +0200145 if ((properties_[i].flags & Property::kWriteOnly)) {
Darin Petkovb451d6e2012-04-23 11:56:41 +0200146 continue;
147 }
Darin Petkov4e9066f2012-06-11 13:17:06 +0200148 string prop = properties_[i].property;
149 if (!args_.ContainsString(prop)) {
150 continue;
Darin Petkovb451d6e2012-04-23 11:56:41 +0200151 }
Darin Petkov4e9066f2012-06-11 13:17:06 +0200152 string value = args_.GetString(prop);
153 // Chomp off leading "Provider." from properties that have this prefix.
154 if (StartsWithASCII(prop, provider_prefix, false)) {
155 prop = prop.substr(provider_prefix.length());
156 }
157 provider_properties.SetString(prop, value);
Darin Petkovb451d6e2012-04-23 11:56:41 +0200158 }
159
160 return provider_properties;
161}
162
Darin Petkov602303f2012-06-06 12:15:59 +0200163void VPNDriver::StartConnectTimeout() {
164 SLOG(VPN, 2) << __func__;
165 if (IsConnectTimeoutStarted()) {
166 return;
167 }
168 connect_timeout_callback_.Reset(
169 Bind(&VPNDriver::OnConnectTimeout, weak_ptr_factory_.GetWeakPtr()));
170 dispatcher_->PostDelayedTask(
171 connect_timeout_callback_.callback(), connect_timeout_seconds_ * 1000);
172}
173
174void VPNDriver::StopConnectTimeout() {
175 SLOG(VPN, 2) << __func__;
176 connect_timeout_callback_.Cancel();
177}
178
179bool VPNDriver::IsConnectTimeoutStarted() const {
180 return !connect_timeout_callback_.IsCancelled();
181}
182
183void VPNDriver::OnConnectTimeout() {
184 LOG(ERROR) << "VPN connection timeout.";
185 StopConnectTimeout();
186 OnConnectionDisconnected();
187}
188
Darin Petkovb451d6e2012-04-23 11:56:41 +0200189} // namespace shill