// // Copyright (C) 2015 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include #include "proxy_rpc_in_data_types.h" #include "proxy_rpc_out_data_types.h" #include "proxy_rpc_server.h" #include "proxy_util.h" namespace { // XmlRpc library verbosity level. static const int kDefaultXmlRpcVerbosity = 5; // Profile name to be used for all the tests. static const char kTestProfileName[] = "test"; bool ValidateNumOfElements(const XmlRpc::XmlRpcValue& value, int expected_num) { if (expected_num != 0) { return (value.valid() && value.size() == expected_num); } else { // |value| will be marked invalid when there are no elements. return !value.valid(); } } }// namespace /*************** RPC Method implementations **********/ XmlRpc::XmlRpcValue CreateProfile( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 1)) { return false; } const std::string& profile_name(params_in[0]); return shill_wifi_client->CreateProfile(profile_name); } XmlRpc::XmlRpcValue RemoveProfile( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 1)) { return false; } const std::string& profile_name(params_in[0]); return shill_wifi_client->RemoveProfile(profile_name); } XmlRpc::XmlRpcValue PushProfile( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 1)) { return false; } const std::string& profile_name(params_in[0]); return shill_wifi_client->PushProfile(profile_name); } XmlRpc::XmlRpcValue PopProfile( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 1)) { return false; } const std::string& profile_name(params_in[0]); return shill_wifi_client->PopProfile(profile_name); } XmlRpc::XmlRpcValue CleanProfiles( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 0)) { return false; } return shill_wifi_client->CleanProfiles(); } XmlRpc::XmlRpcValue ConfigureServiceByGuid( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 1)) { return false; } ConfigureServiceParameters config_params(¶ms_in[0]); return shill_wifi_client->ConfigureServiceByGuid( config_params.guid_, config_params.autoconnect_type_, config_params.passphrase_); } XmlRpc::XmlRpcValue ConfigureWifiService( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 1)) { return false; } AssociationParameters assoc_params(¶ms_in[0]); brillo::VariantDictionary security_params; assoc_params.security_config_->GetServiceProperties(&security_params); return shill_wifi_client->ConfigureWifiService( assoc_params.ssid_, assoc_params.security_config_->security_, security_params, assoc_params.save_credentials_, assoc_params.station_type_, assoc_params.is_hidden_, assoc_params.guid_, assoc_params.autoconnect_type_); } XmlRpc::XmlRpcValue ConnectWifi( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 1)) { return false; } AssociationParameters assoc_params(¶ms_in[0]); std::string wifi_interface = assoc_params.bgscan_config_->interface_; if (wifi_interface.empty()) { std::vector interfaces; if (!shill_wifi_client->ListControlledWifiInterfaces(&interfaces) || interfaces.empty()) { return false; } wifi_interface = interfaces[0]; } shill_wifi_client->ConfigureBgScan( wifi_interface, assoc_params.bgscan_config_->method_, assoc_params.bgscan_config_->short_interval_, assoc_params.bgscan_config_->long_interval_, assoc_params.bgscan_config_->signal_threshold_); brillo::VariantDictionary security_params; assoc_params.security_config_->GetServiceProperties(&security_params); long discovery_time, association_time, configuration_time; std::string failure_reason; bool is_success = shill_wifi_client->ConnectToWifiNetwork( assoc_params.ssid_, assoc_params.security_config_->security_, security_params, assoc_params.save_credentials_, assoc_params.station_type_, assoc_params.is_hidden_, assoc_params.guid_, assoc_params.autoconnect_type_, GetMillisecondsFromSeconds(assoc_params.discovery_timeout_seconds_), GetMillisecondsFromSeconds(assoc_params.association_timeout_seconds_), GetMillisecondsFromSeconds(assoc_params.configuration_timeout_seconds_), &discovery_time, &association_time, &configuration_time, &failure_reason); AssociationResult association_result( is_success, GetSecondsFromMilliseconds(discovery_time), GetSecondsFromMilliseconds(association_time), GetSecondsFromMilliseconds(configuration_time), failure_reason); return association_result.ConvertToXmlRpcValue(); } XmlRpc::XmlRpcValue DeleteEntriesForSsid( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 1)) { return false; } const std::string& ssid(params_in[0]); return shill_wifi_client->DeleteEntriesForSsid(ssid); } XmlRpc::XmlRpcValue InitTestNetworkState( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 0)) { return false; } shill_wifi_client->SetLogging(); shill_wifi_client->CleanProfiles(); shill_wifi_client->RemoveAllWifiEntries(); shill_wifi_client->RemoveProfile(kTestProfileName); bool is_success = shill_wifi_client->CreateProfile(kTestProfileName); if (is_success) { shill_wifi_client->PushProfile(kTestProfileName); } return is_success; } XmlRpc::XmlRpcValue ListControlledWifiInterfaces( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 0)) { return false; } std::vector interfaces; if (!shill_wifi_client->ListControlledWifiInterfaces(&interfaces)) { return false; } XmlRpc::XmlRpcValue result; int array_pos = 0; for (const auto& interface : interfaces) { result[array_pos++] = interface; } return result; } XmlRpc::XmlRpcValue Disconnect( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 1)) { return false; } const std::string& ssid = params_in[0]; return shill_wifi_client->Disconnect(ssid); } XmlRpc::XmlRpcValue WaitForServiceStates( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 3)) { return false; } const std::string& ssid(params_in[0]); XmlRpc::XmlRpcValue states_as_xmlrpcvalue(params_in[1]); int timeout(params_in[2]); int num_states = states_as_xmlrpcvalue.size(); std::vector states; for (int array_pos = 0; array_pos < num_states; array_pos++) { states.emplace_back(std::string(states_as_xmlrpcvalue[array_pos])); } std::string final_state; long wait_time; bool is_success = shill_wifi_client->WaitForServiceStates( ssid, states, GetMillisecondsFromSeconds(timeout), &final_state, &wait_time); XmlRpc::XmlRpcValue result; result[0] = is_success; result[1] = final_state; result[2] = GetSecondsFromMilliseconds(wait_time); return result; } XmlRpc::XmlRpcValue GetServiceOrder( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 0)) { return false; } std::string order; if (!shill_wifi_client->GetServiceOrder(&order)) { return false; } return order; } XmlRpc::XmlRpcValue SetServiceOrder( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 1)) { return false; } const std::string& order(params_in[0]); return shill_wifi_client->SetServiceOrder(order); } XmlRpc::XmlRpcValue GetServiceProperties( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 1)) { return false; } const std::string& ssid(params_in[0]); brillo::VariantDictionary properties; if (!shill_wifi_client->GetServiceProperties(ssid, &properties)) { return false; } XmlRpc::XmlRpcValue result; GetXmlRpcValueFromBrilloAnyValue(properties, &result); return result; } XmlRpc::XmlRpcValue GetActiveWifiSsids( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 0)) { return false; } std::vector ssids; if (!shill_wifi_client->GetActiveWifiSsids(&ssids)) { return false; } XmlRpc::XmlRpcValue result; int array_pos = 0; for (const auto& ssid : ssids) { result[array_pos++] = ssid; } return result; } XmlRpc::XmlRpcValue SetSchedScan( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 1)) { return false; } bool enable(params_in[0]); return shill_wifi_client->SetSchedScan(enable); } XmlRpc::XmlRpcValue GetDbusPropertyOnDevice( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 2)) { return false; } const std::string& interface_name(params_in[0]); const std::string& property_name(params_in[1]); brillo::Any property_value; if (!shill_wifi_client->GetPropertyOnDevice( interface_name, property_name, &property_value)) { return false; } XmlRpc::XmlRpcValue result; GetXmlRpcValueFromBrilloAnyValue(property_value, &result); return result; } XmlRpc::XmlRpcValue SetDbusPropertyOnDevice( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 3)) { return false; } const std::string& interface_name(params_in[0]); const std::string& property_name(params_in[1]); brillo::Any property_value; GetBrilloAnyValueFromXmlRpcValue(¶ms_in[2], &property_value); return shill_wifi_client->SetPropertyOnDevice( interface_name, property_name, property_value); } XmlRpc::XmlRpcValue RequestRoamDbus( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 2)) { return false; } const std::string& bssid(params_in[0]); const std::string& interface_name(params_in[1]); // |interface_name| is the first argument in ProxyShillWifiClient method // to keep it symmetric with other methods defined in the interface even // though it is reversed in the RPC call. return shill_wifi_client->RequestRoam(interface_name, bssid); } XmlRpc::XmlRpcValue SetDeviceEnabled( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 2)) { return false; } const std::string& interface_name(params_in[0]); bool enable(params_in[1]); return shill_wifi_client->SetDeviceEnabled(interface_name, enable); } XmlRpc::XmlRpcValue DiscoverTdlsLink( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 2)) { return false; } const std::string& interface_name(params_in[0]); const std::string& peer_mac_address(params_in[1]); return shill_wifi_client->DiscoverTdlsLink(interface_name, peer_mac_address); } XmlRpc::XmlRpcValue EstablishTdlsLink( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 2)) { return false; } const std::string& interface_name(params_in[0]); const std::string& peer_mac_address(params_in[1]); return shill_wifi_client->EstablishTdlsLink(interface_name, peer_mac_address); } XmlRpc::XmlRpcValue QueryTdlsLink( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 2)) { return false; } const std::string& interface_name(params_in[0]); const std::string& peer_mac_address(params_in[1]); std::string status; if (!shill_wifi_client->QueryTdlsLink( interface_name, peer_mac_address, &status)) { return false; } return status; } XmlRpc::XmlRpcValue AddWakePacketSource( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 2)) { return false; } const std::string& interface_name(params_in[0]); const std::string& source_ip(params_in[1]); return shill_wifi_client->AddWakePacketSource(interface_name, source_ip); } XmlRpc::XmlRpcValue RemoveWakePacketSource( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 2)) { return false; } const std::string& interface_name(params_in[0]); const std::string& source_ip(params_in[1]); return shill_wifi_client->RemoveWakePacketSource(interface_name, source_ip); } XmlRpc::XmlRpcValue RemoveAllWakePacketSources( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 1)) { return false; } const std::string& interface_name(params_in[0]); return shill_wifi_client->RemoveAllWakePacketSources(interface_name); } XmlRpc::XmlRpcValue SyncTimeTo( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { if (!ValidateNumOfElements(params_in, 1)) { return false; } double epoch_seconds(params_in[0]); double seconds; double microseconds = modf(epoch_seconds, &seconds) * 1000000; struct timeval tv; tv.tv_sec = seconds; tv.tv_usec = microseconds; return settimeofday(&tv, nullptr); } // Dummy method to be used for rpc methods not implemented yet. XmlRpc::XmlRpcValue NotImplementedRpcMethod( XmlRpc::XmlRpcValue params_in, ProxyShillWifiClient* shill_wifi_client) { LOG(ERROR) << "RPC Method not implemented."; return true; } ProxyRpcServerMethod::ProxyRpcServerMethod( const std::string& method_name, const RpcServerMethodHandler& handler, ProxyShillWifiClient* shill_wifi_client, ProxyRpcServer* server) : XmlRpcServerMethod(method_name, server), handler_(handler), shill_wifi_client_(shill_wifi_client) { } void ProxyRpcServerMethod::execute( XmlRpc::XmlRpcValue& params_in, XmlRpc::XmlRpcValue& value_out) { value_out = handler_.Run(params_in, shill_wifi_client_); } std::string ProxyRpcServerMethod::help(void) { // TODO: Lookup the method help using the |method_name| from // a text file. return "Shill Test Proxy RPC methods help."; } ProxyRpcServer::ProxyRpcServer( int server_port, std::unique_ptr shill_wifi_client) : XmlRpcServer(), server_port_(server_port), shill_wifi_client_(std::move(shill_wifi_client)) { } void ProxyRpcServer::RegisterRpcMethod( const std::string& method_name, const RpcServerMethodHandler& handler) { methods_.emplace_back( new ProxyRpcServerMethod( method_name, handler, shill_wifi_client_.get(), this)); } void ProxyRpcServer::Run() { XmlRpc::setVerbosity(kDefaultXmlRpcVerbosity); if (!XmlRpc::XmlRpcServer::bindAndListen(server_port_)) { LOG(ERROR) << "Failed to bind to port " << server_port_ << "."; return; } XmlRpc::XmlRpcServer::enableIntrospection(true); RegisterRpcMethod("create_profile", base::Bind(&CreateProfile)); RegisterRpcMethod("remove_profile", base::Bind(&RemoveProfile)); RegisterRpcMethod("push_profile", base::Bind(&PushProfile)); RegisterRpcMethod("pop_profile", base::Bind(&PopProfile)); RegisterRpcMethod("clean_profiles", base::Bind(&CleanProfiles)); RegisterRpcMethod("configure_service_by_guid", base::Bind(&ConfigureServiceByGuid)); RegisterRpcMethod("configure_wifi_service", base::Bind(&ConfigureWifiService)); RegisterRpcMethod("connect_wifi", base::Bind(&ConnectWifi)); RegisterRpcMethod("delete_entries_for_ssid", base::Bind(&DeleteEntriesForSsid)); RegisterRpcMethod("init_test_network_state", base::Bind(&InitTestNetworkState)); RegisterRpcMethod("list_controlled_wifi_interfaces", base::Bind(&ListControlledWifiInterfaces)); RegisterRpcMethod("disconnect", base::Bind(&Disconnect)); RegisterRpcMethod("wait_for_service_states", base::Bind(&WaitForServiceStates)); RegisterRpcMethod("get_service_order", base::Bind(&GetServiceOrder)); RegisterRpcMethod("set_service_order", base::Bind(&SetServiceOrder)); RegisterRpcMethod("get_service_properties", base::Bind(&GetServiceProperties)); RegisterRpcMethod("get_active_wifi_SSIDs", base::Bind(&GetActiveWifiSsids)); RegisterRpcMethod("set_sched_scan", base::Bind(&SetSchedScan)); RegisterRpcMethod("get_dbus_property_on_device", base::Bind(&GetDbusPropertyOnDevice)); RegisterRpcMethod("set_dbus_property_on_device", base::Bind(&SetDbusPropertyOnDevice)); RegisterRpcMethod("request_roam_dbus", base::Bind(&RequestRoamDbus)); RegisterRpcMethod("set_device_enabled", base::Bind(&SetDeviceEnabled)); RegisterRpcMethod("discover_tdls_link", base::Bind(&DiscoverTdlsLink)); RegisterRpcMethod("establish_tdls_link", base::Bind(&EstablishTdlsLink)); RegisterRpcMethod("query_tdls_link", base::Bind(&QueryTdlsLink)); RegisterRpcMethod("add_wake_packet_source", base::Bind(&AddWakePacketSource)); RegisterRpcMethod("remove_wake_packet_source", base::Bind(&RemoveWakePacketSource)); RegisterRpcMethod("remove_all_wake_packet_sources", base::Bind(&RemoveAllWakePacketSources)); RegisterRpcMethod("sync_time_to", base::Bind(&SyncTimeTo)); RegisterRpcMethod("request_roam", base::Bind(&NotImplementedRpcMethod)); RegisterRpcMethod("enable_ui", base::Bind(&NotImplementedRpcMethod)); RegisterRpcMethod("do_suspend", base::Bind(&NotImplementedRpcMethod)); RegisterRpcMethod("do_suspend_bg", base::Bind(&NotImplementedRpcMethod)); RegisterRpcMethod("clear_supplicant_blacklist", base::Bind(&NotImplementedRpcMethod)); RegisterRpcMethod("ready", base::Bind(&NotImplementedRpcMethod)); XmlRpc::XmlRpcServer::work(-1.0); }