1 // Copyright 2014 The Chromium 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.
5 #include "chromeos/dbus/shill_third_party_vpn_driver_client.h"
8 #include "base/stl_util.h"
9 #include "chromeos/dbus/shill_third_party_vpn_observer.h"
11 #include "dbus/message.h"
12 #include "dbus/object_proxy.h"
13 #include "third_party/cros_system_api/dbus/service_constants.h"
19 const char* kSetParametersKeyList
[] = {
20 shill::kAddressParameterThirdPartyVpn
,
21 shill::kBroadcastAddressParameterThirdPartyVpn
,
22 shill::kExclusionListParameterThirdPartyVpn
,
23 shill::kInclusionListParameterThirdPartyVpn
,
24 shill::kSubnetPrefixParameterThirdPartyVpn
,
25 shill::kMtuParameterThirdPartyVpn
,
26 shill::kDomainSearchParameterThirdPartyVpn
,
27 shill::kDnsServersParameterThirdPartyVpn
};
29 // The ShillThirdPartyVpnDriverClient implementation.
30 class ShillThirdPartyVpnDriverClientImpl
31 : public ShillThirdPartyVpnDriverClient
{
33 ShillThirdPartyVpnDriverClientImpl();
34 ~ShillThirdPartyVpnDriverClientImpl() override
;
36 // ShillThirdPartyVpnDriverClient overrides
37 void AddShillThirdPartyVpnObserver(
38 const std::string
& object_path_value
,
39 ShillThirdPartyVpnObserver
* observer
) override
;
41 void RemoveShillThirdPartyVpnObserver(
42 const std::string
& object_path_value
) override
;
45 const std::string
& object_path_value
,
46 const base::DictionaryValue
& parameters
,
47 const ShillClientHelper::StringCallback
& callback
,
48 const ShillClientHelper::ErrorCallback
& error_callback
) override
;
50 void UpdateConnectionState(
51 const std::string
& object_path_value
,
52 const uint32_t connection_state
,
53 const base::Closure
& callback
,
54 const ShillClientHelper::ErrorCallback
& error_callback
) override
;
57 const std::string
& object_path_value
,
58 const std::vector
<char>& ip_packet
,
59 const base::Closure
& callback
,
60 const ShillClientHelper::ErrorCallback
& error_callback
) override
;
63 void Init(dbus::Bus
* bus
) override
{ bus_
= bus
; }
65 ShillThirdPartyVpnDriverClient::TestInterface
* GetTestInterface() override
{
72 explicit HelperInfo(dbus::ObjectProxy
* object_proxy
);
74 ShillClientHelper
* helper() { return &helper_
; }
75 ShillThirdPartyVpnObserver
* observer() { return observer_
; }
77 void set_observer(ShillThirdPartyVpnObserver
* observer
) {
81 base::WeakPtr
<HelperInfo
> GetWeakPtr() {
82 return weak_ptr_factory_
.GetWeakPtr();
86 ShillClientHelper helper_
;
87 ShillThirdPartyVpnObserver
* observer_
;
89 base::WeakPtrFactory
<HelperInfo
> weak_ptr_factory_
;
91 using HelperMap
= std::map
<std::string
, HelperInfo
*>;
93 static void OnPacketReceived(base::WeakPtr
<HelperInfo
> helper_info
,
94 dbus::Signal
* signal
);
95 static void OnPlatformMessage(base::WeakPtr
<HelperInfo
> helper_info
,
96 dbus::Signal
* signal
);
97 static void OnSignalConnected(const std::string
& interface
,
98 const std::string
& signal
,
101 // Returns or creates the corresponding ShillClientHelper for the
102 // |object_path_value|.
103 ShillClientHelper
* GetHelper(const std::string
& object_path_value
);
105 // Returns or creates the corresponding HelperInfo for the
106 // |object_path_value|.
107 HelperInfo
* GetHelperInfo(const std::string
& object_path_value
);
109 // Returns the corresponding HelperInfo for the |object_path| if exists,
111 HelperInfo
* FindHelperInfo(const dbus::ObjectPath
& object_path
);
113 // Deletes the helper object corresponding to |object_path|.
114 void DeleteHelper(const dbus::ObjectPath
& object_path
);
118 std::set
<std::string
> valid_keys_
;
120 DISALLOW_COPY_AND_ASSIGN(ShillThirdPartyVpnDriverClientImpl
);
123 ShillThirdPartyVpnDriverClientImpl::HelperInfo::HelperInfo(
124 dbus::ObjectProxy
* object_proxy
)
125 : helper_(object_proxy
), observer_(nullptr), weak_ptr_factory_(this) {
128 ShillThirdPartyVpnDriverClientImpl::ShillThirdPartyVpnDriverClientImpl()
130 for (uint32_t i
= 0; i
< arraysize(kSetParametersKeyList
); ++i
) {
131 valid_keys_
.insert(kSetParametersKeyList
[i
]);
135 ShillThirdPartyVpnDriverClientImpl::~ShillThirdPartyVpnDriverClientImpl() {
136 for (auto& iter
: helpers_
) {
137 HelperInfo
* helper_info
= iter
.second
;
138 bus_
->RemoveObjectProxy(
139 shill::kFlimflamServiceName
,
140 helper_info
->helper()->object_proxy()->object_path(),
141 base::Bind(&base::DoNothing
));
146 void ShillThirdPartyVpnDriverClientImpl::AddShillThirdPartyVpnObserver(
147 const std::string
& object_path_value
,
148 ShillThirdPartyVpnObserver
* observer
) {
149 HelperInfo
* helper_info
= GetHelperInfo(object_path_value
);
150 if (helper_info
->observer()) {
151 LOG(ERROR
) << "Observer exists for " << object_path_value
;
155 // TODO(kaliamoorthi): Remove the const_cast.
156 helper_info
->set_observer(observer
);
157 dbus::ObjectProxy
* proxy
=
158 const_cast<dbus::ObjectProxy
*>(helper_info
->helper()->object_proxy());
160 proxy
->ConnectToSignal(
161 shill::kFlimflamThirdPartyVpnInterface
, shill::kOnPlatformMessageFunction
,
162 base::Bind(&ShillThirdPartyVpnDriverClientImpl::OnPlatformMessage
,
163 helper_info
->GetWeakPtr()),
164 base::Bind(&ShillThirdPartyVpnDriverClientImpl::OnSignalConnected
));
166 proxy
->ConnectToSignal(
167 shill::kFlimflamThirdPartyVpnInterface
, shill::kOnPacketReceivedFunction
,
168 base::Bind(&ShillThirdPartyVpnDriverClientImpl::OnPacketReceived
,
169 helper_info
->GetWeakPtr()),
170 base::Bind(&ShillThirdPartyVpnDriverClientImpl::OnSignalConnected
));
173 void ShillThirdPartyVpnDriverClientImpl::RemoveShillThirdPartyVpnObserver(
174 const std::string
& object_path_value
) {
175 HelperInfo
* helper_info
= FindHelperInfo(dbus::ObjectPath(object_path_value
));
177 LOG(ERROR
) << "Unknown object_path_value " << object_path_value
;
181 CHECK(helper_info
->observer());
182 helper_info
->set_observer(nullptr);
183 DeleteHelper(dbus::ObjectPath(object_path_value
));
186 void ShillThirdPartyVpnDriverClientImpl::DeleteHelper(
187 const dbus::ObjectPath
& object_path
) {
188 HelperInfo
* helper_info
= FindHelperInfo(dbus::ObjectPath(object_path
));
190 LOG(ERROR
) << "Unknown object_path " << object_path
.value();
194 bus_
->RemoveObjectProxy(shill::kFlimflamServiceName
, object_path
,
195 base::Bind(&base::DoNothing
));
196 helpers_
.erase(helpers_
.find(object_path
.value()));
200 void ShillThirdPartyVpnDriverClientImpl::SetParameters(
201 const std::string
& object_path_value
,
202 const base::DictionaryValue
& parameters
,
203 const ShillClientHelper::StringCallback
& callback
,
204 const ShillClientHelper::ErrorCallback
& error_callback
) {
205 dbus::MethodCall
method_call(shill::kFlimflamThirdPartyVpnInterface
,
206 shill::kSetParametersFunction
);
207 dbus::MessageWriter
writer(&method_call
);
208 dbus::MessageWriter
array_writer(nullptr);
209 writer
.OpenArray("{ss}", &array_writer
);
210 for (base::DictionaryValue::Iterator
it(parameters
); !it
.IsAtEnd();
212 if (valid_keys_
.find(it
.key()) == valid_keys_
.end()) {
213 LOG(WARNING
) << "Unknown key " << it
.key();
217 if (!it
.value().GetAsString(&value
)) {
218 LOG(WARNING
) << "Non string value " << it
.value();
221 dbus::MessageWriter
entry_writer(nullptr);
222 array_writer
.OpenDictEntry(&entry_writer
);
223 entry_writer
.AppendString(it
.key());
224 entry_writer
.AppendString(value
);
225 array_writer
.CloseContainer(&entry_writer
);
227 writer
.CloseContainer(&array_writer
);
228 GetHelper(object_path_value
)
229 ->CallStringMethodWithErrorCallback(&method_call
, callback
,
233 void ShillThirdPartyVpnDriverClientImpl::UpdateConnectionState(
234 const std::string
& object_path_value
,
235 const uint32_t connection_state
,
236 const base::Closure
& callback
,
237 const ShillClientHelper::ErrorCallback
& error_callback
) {
238 dbus::MethodCall
method_call(shill::kFlimflamThirdPartyVpnInterface
,
239 shill::kUpdateConnectionStateFunction
);
240 dbus::MessageWriter
writer(&method_call
);
241 writer
.AppendUint32(connection_state
);
242 GetHelper(object_path_value
)
243 ->CallVoidMethodWithErrorCallback(&method_call
, callback
, error_callback
);
246 void ShillThirdPartyVpnDriverClientImpl::SendPacket(
247 const std::string
& object_path_value
,
248 const std::vector
<char>& ip_packet
,
249 const base::Closure
& callback
,
250 const ShillClientHelper::ErrorCallback
& error_callback
) {
251 dbus::MethodCall
method_call(shill::kFlimflamThirdPartyVpnInterface
,
252 shill::kSendPacketFunction
);
253 dbus::MessageWriter
writer(&method_call
);
254 static_assert(sizeof(uint8_t) == sizeof(char),
255 "Can't reinterpret ip_packet if char is not 8 bit large.");
256 writer
.AppendArrayOfBytes(
257 reinterpret_cast<const uint8_t*>(vector_as_array(&ip_packet
)),
259 GetHelper(object_path_value
)
260 ->CallVoidMethodWithErrorCallback(&method_call
, callback
, error_callback
);
264 void ShillThirdPartyVpnDriverClientImpl::OnPacketReceived(
265 base::WeakPtr
<HelperInfo
> helper_info
,
266 dbus::Signal
* signal
) {
267 if (!helper_info
|| !helper_info
->observer())
270 dbus::MessageReader
reader(signal
);
271 const uint8_t* data
= nullptr;
273 if (reader
.PopArrayOfBytes(&data
, &length
)) {
274 helper_info
->observer()->OnPacketReceived(
275 std::vector
<char>(data
, data
+ length
));
280 void ShillThirdPartyVpnDriverClientImpl::OnPlatformMessage(
281 base::WeakPtr
<HelperInfo
> helper_info
,
282 dbus::Signal
* signal
) {
283 if (!helper_info
|| !helper_info
->observer())
286 dbus::MessageReader
reader(signal
);
287 uint32_t platform_message
= 0;
288 if (reader
.PopUint32(&platform_message
))
289 helper_info
->observer()->OnPlatformMessage(platform_message
);
293 void ShillThirdPartyVpnDriverClientImpl::OnSignalConnected(
294 const std::string
& interface
,
295 const std::string
& signal
,
297 LOG_IF(ERROR
, !success
) << "Connect to " << interface
<< " " << signal
301 ShillClientHelper
* ShillThirdPartyVpnDriverClientImpl::GetHelper(
302 const std::string
& object_path_value
) {
303 return GetHelperInfo(object_path_value
)->helper();
306 ShillThirdPartyVpnDriverClientImpl::HelperInfo
*
307 ShillThirdPartyVpnDriverClientImpl::FindHelperInfo(
308 const dbus::ObjectPath
& object_path
) {
309 HelperMap::iterator it
= helpers_
.find(object_path
.value());
310 return (it
!= helpers_
.end()) ? it
->second
: nullptr;
313 ShillThirdPartyVpnDriverClientImpl::HelperInfo
*
314 ShillThirdPartyVpnDriverClientImpl::GetHelperInfo(
315 const std::string
& object_path_value
) {
316 dbus::ObjectPath
object_path(object_path_value
);
317 HelperInfo
* helper_info
= FindHelperInfo(object_path
);
321 // There is no helper for the profile, create it.
322 dbus::ObjectProxy
* object_proxy
=
323 bus_
->GetObjectProxy(shill::kFlimflamServiceName
, object_path
);
324 helper_info
= new HelperInfo(object_proxy
);
325 helpers_
[object_path_value
] = helper_info
;
331 ShillThirdPartyVpnDriverClient::ShillThirdPartyVpnDriverClient() {
334 ShillThirdPartyVpnDriverClient::~ShillThirdPartyVpnDriverClient() {
338 ShillThirdPartyVpnDriverClient
* ShillThirdPartyVpnDriverClient::Create() {
339 return new ShillThirdPartyVpnDriverClientImpl();
342 } // namespace chromeos