| Index: chromeos/dbus/shill_third_party_vpn_driver_client.cc
|
| diff --git a/chromeos/dbus/shill_third_party_vpn_driver_client.cc b/chromeos/dbus/shill_third_party_vpn_driver_client.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b1f3b731031e2410498db89471a6d387de7ce258
|
| --- /dev/null
|
| +++ b/chromeos/dbus/shill_third_party_vpn_driver_client.cc
|
| @@ -0,0 +1,335 @@
|
| +// Copyright 2014 The Chromium 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 "chromeos/dbus/shill_third_party_vpn_driver_client.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "chromeos/dbus/shill_third_party_vpn_observer.h"
|
| +#include "dbus/bus.h"
|
| +#include "dbus/message.h"
|
| +#include "dbus/object_proxy.h"
|
| +#include "third_party/cros_system_api/dbus/service_constants.h"
|
| +
|
| +namespace chromeos {
|
| +
|
| +namespace {
|
| +
|
| +const char* kSetParametersKeyList[] = {
|
| + shill::kAddressParameterThirdPartyVpn,
|
| + shill::kBroadcastAddressParameterThirdPartyVpn,
|
| + shill::kGatewayParameterThirdPartyVpn,
|
| + shill::kBypassTunnelForIpParameterThirdPartyVpn,
|
| + shill::kSubnetPrefixParameterThirdPartyVpn,
|
| + shill::kMtuParameterThirdPartyVpn,
|
| + shill::kDomainSearchParameterThirdPartyVpn,
|
| + shill::kDnsServersParameterThirdPartyVpn};
|
| +
|
| +// The ShillThirdPartyVpnDriverClient implementation.
|
| +class ShillThirdPartyVpnDriverClientImpl
|
| + : public ShillThirdPartyVpnDriverClient {
|
| + public:
|
| + ShillThirdPartyVpnDriverClientImpl();
|
| + ~ShillThirdPartyVpnDriverClientImpl() override;
|
| +
|
| + // ShillThirdPartyVpnDriverClient overrides
|
| + void AddShillThirdPartyVpnObserver(
|
| + const std::string& object_path_value,
|
| + ShillThirdPartyVpnObserver* observer) override;
|
| +
|
| + void RemoveShillThirdPartyVpnObserver(
|
| + const std::string& object_path_value) override;
|
| +
|
| + void SetParameters(
|
| + const std::string& object_path_value,
|
| + const base::DictionaryValue& parameters,
|
| + const base::Closure& callback,
|
| + const ShillClientHelper::ErrorCallback& error_callback) override;
|
| +
|
| + void UpdateConnectionState(
|
| + const std::string& object_path_value,
|
| + const uint32_t connection_state,
|
| + const base::Closure& callback,
|
| + const ShillClientHelper::ErrorCallback& error_callback) override;
|
| +
|
| + void SendPacket(
|
| + const std::string& object_path_value,
|
| + const std::string& ip_packet,
|
| + const base::Closure& callback,
|
| + const ShillClientHelper::ErrorCallback& error_callback) override;
|
| +
|
| + protected:
|
| + void Init(dbus::Bus* bus) override { bus_ = bus; }
|
| +
|
| + ShillThirdPartyVpnDriverClient::TestInterface* GetTestInterface() override {
|
| + return nullptr;
|
| + }
|
| +
|
| + private:
|
| + class HelperInfo {
|
| + public:
|
| + explicit HelperInfo(dbus::ObjectProxy* object_proxy);
|
| +
|
| + ShillClientHelper* helper() { return &helper_; }
|
| + ShillThirdPartyVpnObserver* observer() { return observer_; }
|
| +
|
| + void set_observer(ShillThirdPartyVpnObserver* observer) {
|
| + observer_ = observer;
|
| + }
|
| +
|
| + base::WeakPtr<HelperInfo> GetWeakPtr() {
|
| + return weak_ptr_factory_.GetWeakPtr();
|
| + }
|
| +
|
| + private:
|
| + ShillClientHelper helper_;
|
| + ShillThirdPartyVpnObserver* observer_;
|
| +
|
| + base::WeakPtrFactory<HelperInfo> weak_ptr_factory_;
|
| + };
|
| + using HelperMap = std::map<std::string, HelperInfo*>;
|
| +
|
| + static void OnPacketReceived(base::WeakPtr<HelperInfo> helper_info,
|
| + dbus::Signal* signal);
|
| + static void OnPlatformMessage(base::WeakPtr<HelperInfo> helper_info,
|
| + dbus::Signal* signal);
|
| + static void OnSignalConnected(const std::string& interface,
|
| + const std::string& signal,
|
| + bool success);
|
| +
|
| + // Returns or creates the corresponding ShillClientHelper for the
|
| + // |object_path_value|.
|
| + ShillClientHelper* GetHelper(const std::string& object_path_value);
|
| +
|
| + // Returns or creates the corresponding HelperInfo for the
|
| + // |object_path_value|.
|
| + HelperInfo* GetHelperInfo(const std::string& object_path_value);
|
| +
|
| + // Returns the corresponding HelperInfo for the |object_path| if exists,
|
| + // nullptr if not.
|
| + HelperInfo* FindHelperInfo(const dbus::ObjectPath& object_path);
|
| +
|
| + // Deletes the helper object corresponding to |object_path|.
|
| + void DeleteHelper(const dbus::ObjectPath& object_path);
|
| +
|
| + dbus::Bus* bus_;
|
| + HelperMap helpers_;
|
| + std::set<std::string> valid_keys_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ShillThirdPartyVpnDriverClientImpl);
|
| +};
|
| +
|
| +ShillThirdPartyVpnDriverClientImpl::HelperInfo::HelperInfo(
|
| + dbus::ObjectProxy* object_proxy)
|
| + : helper_(object_proxy), observer_(nullptr), weak_ptr_factory_(this) {
|
| +}
|
| +
|
| +ShillThirdPartyVpnDriverClientImpl::ShillThirdPartyVpnDriverClientImpl()
|
| + : bus_(nullptr) {
|
| + for (uint32_t i = 0; i < arraysize(kSetParametersKeyList); ++i) {
|
| + valid_keys_.insert(kSetParametersKeyList[i]);
|
| + }
|
| +}
|
| +
|
| +ShillThirdPartyVpnDriverClientImpl::~ShillThirdPartyVpnDriverClientImpl() {
|
| + for (auto& iter : helpers_) {
|
| + HelperInfo* helper_info = iter.second;
|
| + bus_->RemoveObjectProxy(
|
| + shill::kFlimflamServiceName,
|
| + helper_info->helper()->object_proxy()->object_path(),
|
| + base::Bind(&base::DoNothing));
|
| + delete helper_info;
|
| + }
|
| +}
|
| +
|
| +void ShillThirdPartyVpnDriverClientImpl::AddShillThirdPartyVpnObserver(
|
| + const std::string& object_path_value,
|
| + ShillThirdPartyVpnObserver* observer) {
|
| + HelperInfo* helper_info = GetHelperInfo(object_path_value);
|
| + if (helper_info->observer()) {
|
| + LOG(ERROR) << "Observer exists for " << object_path_value;
|
| + return;
|
| + }
|
| +
|
| + // TODO(kaliamoorthi): Remove the const_cast.
|
| + helper_info->set_observer(observer);
|
| + dbus::ObjectProxy* proxy =
|
| + const_cast<dbus::ObjectProxy*>(helper_info->helper()->object_proxy());
|
| +
|
| + proxy->ConnectToSignal(
|
| + shill::kFlimflamThirdPartyVpnInterface, shill::kOnPlatformMessageFunction,
|
| + base::Bind(&ShillThirdPartyVpnDriverClientImpl::OnPlatformMessage,
|
| + helper_info->GetWeakPtr()),
|
| + base::Bind(&ShillThirdPartyVpnDriverClientImpl::OnSignalConnected));
|
| +
|
| + proxy->ConnectToSignal(
|
| + shill::kFlimflamThirdPartyVpnInterface, shill::kOnPacketReceivedFunction,
|
| + base::Bind(&ShillThirdPartyVpnDriverClientImpl::OnPacketReceived,
|
| + helper_info->GetWeakPtr()),
|
| + base::Bind(&ShillThirdPartyVpnDriverClientImpl::OnSignalConnected));
|
| +}
|
| +
|
| +void ShillThirdPartyVpnDriverClientImpl::RemoveShillThirdPartyVpnObserver(
|
| + const std::string& object_path_value) {
|
| + HelperInfo* helper_info = FindHelperInfo(dbus::ObjectPath(object_path_value));
|
| + if (!helper_info) {
|
| + LOG(ERROR) << "Unknown object_path_value " << object_path_value;
|
| + return;
|
| + }
|
| +
|
| + CHECK(helper_info->observer());
|
| + helper_info->set_observer(nullptr);
|
| + DeleteHelper(dbus::ObjectPath(object_path_value));
|
| +}
|
| +
|
| +void ShillThirdPartyVpnDriverClientImpl::DeleteHelper(
|
| + const dbus::ObjectPath& object_path) {
|
| + HelperInfo* helper_info = FindHelperInfo(dbus::ObjectPath(object_path));
|
| + if (!helper_info) {
|
| + LOG(ERROR) << "Unknown object_path " << object_path.value();
|
| + return;
|
| + }
|
| +
|
| + bus_->RemoveObjectProxy(shill::kFlimflamServiceName, object_path,
|
| + base::Bind(&base::DoNothing));
|
| + helpers_.erase(helpers_.find(object_path.value()));
|
| + delete helper_info;
|
| +}
|
| +
|
| +void ShillThirdPartyVpnDriverClientImpl::SetParameters(
|
| + const std::string& object_path_value,
|
| + const base::DictionaryValue& parameters,
|
| + const base::Closure& callback,
|
| + const ShillClientHelper::ErrorCallback& error_callback) {
|
| + dbus::MethodCall method_call(shill::kFlimflamThirdPartyVpnInterface,
|
| + shill::kSetParametersFunction);
|
| + dbus::MessageWriter writer(&method_call);
|
| + dbus::MessageWriter array_writer(nullptr);
|
| + writer.OpenArray("{ss}", &array_writer);
|
| + for (base::DictionaryValue::Iterator it(parameters); !it.IsAtEnd();
|
| + it.Advance()) {
|
| + if (valid_keys_.find(it.key()) == valid_keys_.end()) {
|
| + LOG(WARNING) << "Unknown key " << it.key();
|
| + continue;
|
| + }
|
| + std::string value;
|
| + if (!it.value().GetAsString(&value)) {
|
| + LOG(WARNING) << "Non string value " << it.value();
|
| + continue;
|
| + }
|
| + dbus::MessageWriter entry_writer(nullptr);
|
| + array_writer.OpenDictEntry(&entry_writer);
|
| + entry_writer.AppendString(it.key());
|
| + entry_writer.AppendString(value);
|
| + array_writer.CloseContainer(&entry_writer);
|
| + }
|
| + writer.CloseContainer(&array_writer);
|
| + GetHelper(object_path_value)
|
| + ->CallVoidMethodWithErrorCallback(&method_call, callback, error_callback);
|
| +}
|
| +
|
| +void ShillThirdPartyVpnDriverClientImpl::UpdateConnectionState(
|
| + const std::string& object_path_value,
|
| + const uint32_t connection_state,
|
| + const base::Closure& callback,
|
| + const ShillClientHelper::ErrorCallback& error_callback) {
|
| + dbus::MethodCall method_call(shill::kFlimflamThirdPartyVpnInterface,
|
| + shill::kUpdateConnectionStateFunction);
|
| + dbus::MessageWriter writer(&method_call);
|
| + writer.AppendUint32(connection_state);
|
| + GetHelper(object_path_value)
|
| + ->CallVoidMethodWithErrorCallback(&method_call, callback, error_callback);
|
| +}
|
| +
|
| +void ShillThirdPartyVpnDriverClientImpl::SendPacket(
|
| + const std::string& object_path_value,
|
| + const std::string& ip_packet,
|
| + const base::Closure& callback,
|
| + const ShillClientHelper::ErrorCallback& error_callback) {
|
| + dbus::MethodCall method_call(shill::kFlimflamThirdPartyVpnInterface,
|
| + shill::kSendPacketFunction);
|
| + dbus::MessageWriter writer(&method_call);
|
| + writer.AppendArrayOfBytes(reinterpret_cast<const uint8_t*>(ip_packet.data()),
|
| + ip_packet.size());
|
| + GetHelper(object_path_value)
|
| + ->CallVoidMethodWithErrorCallback(&method_call, callback, error_callback);
|
| +}
|
| +
|
| +// static
|
| +void ShillThirdPartyVpnDriverClientImpl::OnPacketReceived(
|
| + base::WeakPtr<HelperInfo> helper_info,
|
| + dbus::Signal* signal) {
|
| + if (!helper_info || !helper_info->observer())
|
| + return;
|
| +
|
| + dbus::MessageReader reader(signal);
|
| + const uint8_t* data = nullptr;
|
| + size_t length = 0;
|
| + if (reader.PopArrayOfBytes(&data, &length))
|
| + helper_info->observer()->OnPacketReceived(data, length);
|
| +}
|
| +
|
| +// static
|
| +void ShillThirdPartyVpnDriverClientImpl::OnPlatformMessage(
|
| + base::WeakPtr<HelperInfo> helper_info,
|
| + dbus::Signal* signal) {
|
| + if (!helper_info || !helper_info->observer())
|
| + return;
|
| +
|
| + dbus::MessageReader reader(signal);
|
| + uint32_t platform_message = 0;
|
| + if (reader.PopUint32(&platform_message))
|
| + helper_info->observer()->OnPlatformMessage(platform_message);
|
| +}
|
| +
|
| +// static
|
| +void ShillThirdPartyVpnDriverClientImpl::OnSignalConnected(
|
| + const std::string& interface,
|
| + const std::string& signal,
|
| + bool success) {
|
| + LOG_IF(ERROR, !success) << "Connect to " << interface << " " << signal
|
| + << " failed.";
|
| +}
|
| +
|
| +ShillClientHelper* ShillThirdPartyVpnDriverClientImpl::GetHelper(
|
| + const std::string& object_path_value) {
|
| + return GetHelperInfo(object_path_value)->helper();
|
| +}
|
| +
|
| +ShillThirdPartyVpnDriverClientImpl::HelperInfo*
|
| +ShillThirdPartyVpnDriverClientImpl::FindHelperInfo(
|
| + const dbus::ObjectPath& object_path) {
|
| + HelperMap::iterator it = helpers_.find(object_path.value());
|
| + return (it != helpers_.end()) ? it->second : nullptr;
|
| +}
|
| +
|
| +ShillThirdPartyVpnDriverClientImpl::HelperInfo*
|
| +ShillThirdPartyVpnDriverClientImpl::GetHelperInfo(
|
| + const std::string& object_path_value) {
|
| + dbus::ObjectPath object_path(object_path_value);
|
| + HelperInfo* helper_info = FindHelperInfo(object_path);
|
| + if (helper_info)
|
| + return helper_info;
|
| +
|
| + // There is no helper for the profile, create it.
|
| + dbus::ObjectProxy* object_proxy =
|
| + bus_->GetObjectProxy(shill::kFlimflamServiceName, object_path);
|
| + helper_info = new HelperInfo(object_proxy);
|
| + helpers_[object_path_value] = helper_info;
|
| + return helper_info;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +ShillThirdPartyVpnDriverClient::ShillThirdPartyVpnDriverClient() {
|
| +}
|
| +
|
| +ShillThirdPartyVpnDriverClient::~ShillThirdPartyVpnDriverClient() {
|
| +}
|
| +
|
| +// static
|
| +ShillThirdPartyVpnDriverClient* ShillThirdPartyVpnDriverClient::Create() {
|
| + return new ShillThirdPartyVpnDriverClientImpl();
|
| +}
|
| +
|
| +} // namespace chromeos
|
|
|