1 // 2 // Copyright (C) 2015 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include <base/bind.h> 18 19 #include "proxy_rpc_in_data_types.h" 20 #include "proxy_rpc_out_data_types.h" 21 #include "proxy_rpc_server.h" 22 #include "proxy_util.h" 23 24 namespace { 25 // XmlRpc library verbosity level. 26 static const int kDefaultXmlRpcVerbosity = 5; 27 // Profile name to be used for all the tests. 28 static const char kTestProfileName[] = "test"; 29 30 bool ValidateNumOfElements(const XmlRpc::XmlRpcValue& value, int expected_num) { 31 if (expected_num != 0) { 32 return (value.valid() && value.size() == expected_num); 33 } else { 34 // |value| will be marked invalid when there are no elements. 35 return !value.valid(); 36 } 37 } 38 }// namespace 39 40 /*************** RPC Method implementations **********/ 41 XmlRpc::XmlRpcValue CreateProfile( 42 XmlRpc::XmlRpcValue params_in, 43 ProxyShillWifiClient* shill_wifi_client) { 44 if (!ValidateNumOfElements(params_in, 1)) { 45 return false; 46 } 47 const std::string& profile_name(params_in[0]); 48 return shill_wifi_client->CreateProfile(profile_name); 49 } 50 51 XmlRpc::XmlRpcValue RemoveProfile( 52 XmlRpc::XmlRpcValue params_in, 53 ProxyShillWifiClient* shill_wifi_client) { 54 if (!ValidateNumOfElements(params_in, 1)) { 55 return false; 56 } 57 const std::string& profile_name(params_in[0]); 58 return shill_wifi_client->RemoveProfile(profile_name); 59 } 60 61 XmlRpc::XmlRpcValue PushProfile( 62 XmlRpc::XmlRpcValue params_in, 63 ProxyShillWifiClient* shill_wifi_client) { 64 if (!ValidateNumOfElements(params_in, 1)) { 65 return false; 66 } 67 const std::string& profile_name(params_in[0]); 68 return shill_wifi_client->PushProfile(profile_name); 69 } 70 71 XmlRpc::XmlRpcValue PopProfile( 72 XmlRpc::XmlRpcValue params_in, 73 ProxyShillWifiClient* shill_wifi_client) { 74 if (!ValidateNumOfElements(params_in, 1)) { 75 return false; 76 } 77 const std::string& profile_name(params_in[0]); 78 return shill_wifi_client->PopProfile(profile_name); 79 } 80 81 XmlRpc::XmlRpcValue CleanProfiles( 82 XmlRpc::XmlRpcValue params_in, 83 ProxyShillWifiClient* shill_wifi_client) { 84 if (!ValidateNumOfElements(params_in, 0)) { 85 return false; 86 } 87 return shill_wifi_client->CleanProfiles(); 88 } 89 90 XmlRpc::XmlRpcValue ConfigureServiceByGuid( 91 XmlRpc::XmlRpcValue params_in, 92 ProxyShillWifiClient* shill_wifi_client) { 93 if (!ValidateNumOfElements(params_in, 1)) { 94 return false; 95 } 96 ConfigureServiceParameters config_params(¶ms_in[0]); 97 return shill_wifi_client->ConfigureServiceByGuid( 98 config_params.guid_, 99 config_params.autoconnect_type_, 100 config_params.passphrase_); 101 } 102 103 XmlRpc::XmlRpcValue ConfigureWifiService( 104 XmlRpc::XmlRpcValue params_in, 105 ProxyShillWifiClient* shill_wifi_client) { 106 if (!ValidateNumOfElements(params_in, 1)) { 107 return false; 108 } 109 AssociationParameters assoc_params(¶ms_in[0]); 110 brillo::VariantDictionary security_params; 111 assoc_params.security_config_->GetServiceProperties(&security_params); 112 return shill_wifi_client->ConfigureWifiService( 113 assoc_params.ssid_, 114 assoc_params.security_config_->security_, 115 security_params, 116 assoc_params.save_credentials_, 117 assoc_params.station_type_, 118 assoc_params.is_hidden_, 119 assoc_params.guid_, 120 assoc_params.autoconnect_type_); 121 } 122 123 XmlRpc::XmlRpcValue ConnectWifi( 124 XmlRpc::XmlRpcValue params_in, 125 ProxyShillWifiClient* shill_wifi_client) { 126 if (!ValidateNumOfElements(params_in, 1)) { 127 return false; 128 } 129 130 AssociationParameters assoc_params(¶ms_in[0]); 131 std::string wifi_interface = assoc_params.bgscan_config_->interface_; 132 if (wifi_interface.empty()) { 133 std::vector<std::string> interfaces; 134 if (!shill_wifi_client->ListControlledWifiInterfaces(&interfaces) || 135 interfaces.empty()) { 136 return false; 137 } 138 wifi_interface = interfaces[0]; 139 } 140 shill_wifi_client->ConfigureBgScan( 141 wifi_interface, 142 assoc_params.bgscan_config_->method_, 143 assoc_params.bgscan_config_->short_interval_, 144 assoc_params.bgscan_config_->long_interval_, 145 assoc_params.bgscan_config_->signal_threshold_); 146 147 brillo::VariantDictionary security_params; 148 assoc_params.security_config_->GetServiceProperties(&security_params); 149 150 long discovery_time, association_time, configuration_time; 151 std::string failure_reason; 152 bool is_success = shill_wifi_client->ConnectToWifiNetwork( 153 assoc_params.ssid_, 154 assoc_params.security_config_->security_, 155 security_params, 156 assoc_params.save_credentials_, 157 assoc_params.station_type_, 158 assoc_params.is_hidden_, 159 assoc_params.guid_, 160 assoc_params.autoconnect_type_, 161 GetMillisecondsFromSeconds(assoc_params.discovery_timeout_seconds_), 162 GetMillisecondsFromSeconds(assoc_params.association_timeout_seconds_), 163 GetMillisecondsFromSeconds(assoc_params.configuration_timeout_seconds_), 164 &discovery_time, 165 &association_time, 166 &configuration_time, 167 &failure_reason); 168 169 AssociationResult association_result( 170 is_success, 171 GetSecondsFromMilliseconds(discovery_time), 172 GetSecondsFromMilliseconds(association_time), 173 GetSecondsFromMilliseconds(configuration_time), 174 failure_reason); 175 return association_result.ConvertToXmlRpcValue(); 176 } 177 178 XmlRpc::XmlRpcValue DeleteEntriesForSsid( 179 XmlRpc::XmlRpcValue params_in, 180 ProxyShillWifiClient* shill_wifi_client) { 181 if (!ValidateNumOfElements(params_in, 1)) { 182 return false; 183 } 184 const std::string& ssid(params_in[0]); 185 return shill_wifi_client->DeleteEntriesForSsid(ssid); 186 } 187 188 XmlRpc::XmlRpcValue InitTestNetworkState( 189 XmlRpc::XmlRpcValue params_in, 190 ProxyShillWifiClient* shill_wifi_client) { 191 if (!ValidateNumOfElements(params_in, 0)) { 192 return false; 193 } 194 shill_wifi_client->SetLogging(); 195 shill_wifi_client->CleanProfiles(); 196 shill_wifi_client->RemoveAllWifiEntries(); 197 shill_wifi_client->RemoveProfile(kTestProfileName); 198 bool is_success = shill_wifi_client->CreateProfile(kTestProfileName); 199 if (is_success) { 200 shill_wifi_client->PushProfile(kTestProfileName); 201 } 202 return is_success; 203 } 204 205 XmlRpc::XmlRpcValue ListControlledWifiInterfaces( 206 XmlRpc::XmlRpcValue params_in, 207 ProxyShillWifiClient* shill_wifi_client) { 208 if (!ValidateNumOfElements(params_in, 0)) { 209 return false; 210 } 211 std::vector<std::string> interfaces; 212 if (!shill_wifi_client->ListControlledWifiInterfaces(&interfaces)) { 213 return false; 214 } 215 XmlRpc::XmlRpcValue result; 216 int array_pos = 0; 217 for (const auto& interface : interfaces) { 218 result[array_pos++] = interface; 219 } 220 return result; 221 } 222 223 XmlRpc::XmlRpcValue Disconnect( 224 XmlRpc::XmlRpcValue params_in, 225 ProxyShillWifiClient* shill_wifi_client) { 226 if (!ValidateNumOfElements(params_in, 1)) { 227 return false; 228 } 229 const std::string& ssid = params_in[0]; 230 return shill_wifi_client->Disconnect(ssid); 231 } 232 233 XmlRpc::XmlRpcValue WaitForServiceStates( 234 XmlRpc::XmlRpcValue params_in, 235 ProxyShillWifiClient* shill_wifi_client) { 236 if (!ValidateNumOfElements(params_in, 3)) { 237 return false; 238 } 239 const std::string& ssid(params_in[0]); 240 XmlRpc::XmlRpcValue states_as_xmlrpcvalue(params_in[1]); 241 int timeout(params_in[2]); 242 int num_states = states_as_xmlrpcvalue.size(); 243 std::vector<std::string> states; 244 for (int array_pos = 0; array_pos < num_states; array_pos++) { 245 states.emplace_back(std::string(states_as_xmlrpcvalue[array_pos])); 246 } 247 std::string final_state; 248 long wait_time; 249 bool is_success = shill_wifi_client->WaitForServiceStates( 250 ssid, states, GetMillisecondsFromSeconds(timeout), 251 &final_state, &wait_time); 252 XmlRpc::XmlRpcValue result; 253 result[0] = is_success; 254 result[1] = final_state; 255 result[2] = GetSecondsFromMilliseconds(wait_time); 256 return result; 257 } 258 259 XmlRpc::XmlRpcValue GetServiceOrder( 260 XmlRpc::XmlRpcValue params_in, 261 ProxyShillWifiClient* shill_wifi_client) { 262 if (!ValidateNumOfElements(params_in, 0)) { 263 return false; 264 } 265 std::string order; 266 if (!shill_wifi_client->GetServiceOrder(&order)) { 267 return false; 268 } 269 return order; 270 } 271 272 XmlRpc::XmlRpcValue SetServiceOrder( 273 XmlRpc::XmlRpcValue params_in, 274 ProxyShillWifiClient* shill_wifi_client) { 275 if (!ValidateNumOfElements(params_in, 1)) { 276 return false; 277 } 278 const std::string& order(params_in[0]); 279 return shill_wifi_client->SetServiceOrder(order); 280 } 281 282 XmlRpc::XmlRpcValue GetServiceProperties( 283 XmlRpc::XmlRpcValue params_in, 284 ProxyShillWifiClient* shill_wifi_client) { 285 if (!ValidateNumOfElements(params_in, 1)) { 286 return false; 287 } 288 const std::string& ssid(params_in[0]); 289 brillo::VariantDictionary properties; 290 if (!shill_wifi_client->GetServiceProperties(ssid, &properties)) { 291 return false; 292 } 293 XmlRpc::XmlRpcValue result; 294 GetXmlRpcValueFromBrilloAnyValue(properties, &result); 295 return result; 296 } 297 298 XmlRpc::XmlRpcValue GetActiveWifiSsids( 299 XmlRpc::XmlRpcValue params_in, 300 ProxyShillWifiClient* shill_wifi_client) { 301 if (!ValidateNumOfElements(params_in, 0)) { 302 return false; 303 } 304 std::vector<std::string> ssids; 305 if (!shill_wifi_client->GetActiveWifiSsids(&ssids)) { 306 return false; 307 } 308 XmlRpc::XmlRpcValue result; 309 int array_pos = 0; 310 for (const auto& ssid : ssids) { 311 result[array_pos++] = ssid; 312 } 313 return result; 314 } 315 316 XmlRpc::XmlRpcValue SetSchedScan( 317 XmlRpc::XmlRpcValue params_in, 318 ProxyShillWifiClient* shill_wifi_client) { 319 if (!ValidateNumOfElements(params_in, 1)) { 320 return false; 321 } 322 bool enable(params_in[0]); 323 return shill_wifi_client->SetSchedScan(enable); 324 } 325 326 XmlRpc::XmlRpcValue GetDbusPropertyOnDevice( 327 XmlRpc::XmlRpcValue params_in, 328 ProxyShillWifiClient* shill_wifi_client) { 329 if (!ValidateNumOfElements(params_in, 2)) { 330 return false; 331 } 332 const std::string& interface_name(params_in[0]); 333 const std::string& property_name(params_in[1]); 334 brillo::Any property_value; 335 if (!shill_wifi_client->GetPropertyOnDevice( 336 interface_name, property_name, &property_value)) { 337 return false; 338 } 339 XmlRpc::XmlRpcValue result; 340 GetXmlRpcValueFromBrilloAnyValue(property_value, &result); 341 return result; 342 } 343 344 XmlRpc::XmlRpcValue SetDbusPropertyOnDevice( 345 XmlRpc::XmlRpcValue params_in, 346 ProxyShillWifiClient* shill_wifi_client) { 347 if (!ValidateNumOfElements(params_in, 3)) { 348 return false; 349 } 350 const std::string& interface_name(params_in[0]); 351 const std::string& property_name(params_in[1]); 352 brillo::Any property_value; 353 GetBrilloAnyValueFromXmlRpcValue(¶ms_in[2], &property_value); 354 return shill_wifi_client->SetPropertyOnDevice( 355 interface_name, property_name, property_value); 356 } 357 358 XmlRpc::XmlRpcValue RequestRoamDbus( 359 XmlRpc::XmlRpcValue params_in, 360 ProxyShillWifiClient* shill_wifi_client) { 361 if (!ValidateNumOfElements(params_in, 2)) { 362 return false; 363 } 364 const std::string& bssid(params_in[0]); 365 const std::string& interface_name(params_in[1]); 366 // |interface_name| is the first argument in ProxyShillWifiClient method 367 // to keep it symmetric with other methods defined in the interface even 368 // though it is reversed in the RPC call. 369 return shill_wifi_client->RequestRoam(interface_name, bssid); 370 } 371 372 XmlRpc::XmlRpcValue SetDeviceEnabled( 373 XmlRpc::XmlRpcValue params_in, 374 ProxyShillWifiClient* shill_wifi_client) { 375 if (!ValidateNumOfElements(params_in, 2)) { 376 return false; 377 } 378 const std::string& interface_name(params_in[0]); 379 bool enable(params_in[1]); 380 return shill_wifi_client->SetDeviceEnabled(interface_name, enable); 381 } 382 383 XmlRpc::XmlRpcValue DiscoverTdlsLink( 384 XmlRpc::XmlRpcValue params_in, 385 ProxyShillWifiClient* shill_wifi_client) { 386 if (!ValidateNumOfElements(params_in, 2)) { 387 return false; 388 } 389 const std::string& interface_name(params_in[0]); 390 const std::string& peer_mac_address(params_in[1]); 391 return shill_wifi_client->DiscoverTdlsLink(interface_name, peer_mac_address); 392 } 393 394 XmlRpc::XmlRpcValue EstablishTdlsLink( 395 XmlRpc::XmlRpcValue params_in, 396 ProxyShillWifiClient* shill_wifi_client) { 397 if (!ValidateNumOfElements(params_in, 2)) { 398 return false; 399 } 400 const std::string& interface_name(params_in[0]); 401 const std::string& peer_mac_address(params_in[1]); 402 return shill_wifi_client->EstablishTdlsLink(interface_name, peer_mac_address); 403 } 404 405 XmlRpc::XmlRpcValue QueryTdlsLink( 406 XmlRpc::XmlRpcValue params_in, 407 ProxyShillWifiClient* shill_wifi_client) { 408 if (!ValidateNumOfElements(params_in, 2)) { 409 return false; 410 } 411 const std::string& interface_name(params_in[0]); 412 const std::string& peer_mac_address(params_in[1]); 413 std::string status; 414 if (!shill_wifi_client->QueryTdlsLink( 415 interface_name, peer_mac_address, &status)) { 416 return false; 417 } 418 return status; 419 } 420 421 XmlRpc::XmlRpcValue AddWakePacketSource( 422 XmlRpc::XmlRpcValue params_in, 423 ProxyShillWifiClient* shill_wifi_client) { 424 if (!ValidateNumOfElements(params_in, 2)) { 425 return false; 426 } 427 const std::string& interface_name(params_in[0]); 428 const std::string& source_ip(params_in[1]); 429 return shill_wifi_client->AddWakePacketSource(interface_name, source_ip); 430 } 431 432 XmlRpc::XmlRpcValue RemoveWakePacketSource( 433 XmlRpc::XmlRpcValue params_in, 434 ProxyShillWifiClient* shill_wifi_client) { 435 if (!ValidateNumOfElements(params_in, 2)) { 436 return false; 437 } 438 const std::string& interface_name(params_in[0]); 439 const std::string& source_ip(params_in[1]); 440 return shill_wifi_client->RemoveWakePacketSource(interface_name, source_ip); 441 } 442 443 XmlRpc::XmlRpcValue RemoveAllWakePacketSources( 444 XmlRpc::XmlRpcValue params_in, 445 ProxyShillWifiClient* shill_wifi_client) { 446 if (!ValidateNumOfElements(params_in, 1)) { 447 return false; 448 } 449 const std::string& interface_name(params_in[0]); 450 return shill_wifi_client->RemoveAllWakePacketSources(interface_name); 451 } 452 453 XmlRpc::XmlRpcValue SyncTimeTo( 454 XmlRpc::XmlRpcValue params_in, 455 ProxyShillWifiClient* shill_wifi_client) { 456 if (!ValidateNumOfElements(params_in, 1)) { 457 return false; 458 } 459 double epoch_seconds(params_in[0]); 460 double seconds; 461 double microseconds = modf(epoch_seconds, &seconds) * 1000000; 462 struct timeval tv; 463 tv.tv_sec = seconds; 464 tv.tv_usec = microseconds; 465 return settimeofday(&tv, nullptr); 466 } 467 468 // Dummy method to be used for rpc methods not implemented yet. 469 XmlRpc::XmlRpcValue NotImplementedRpcMethod( 470 XmlRpc::XmlRpcValue params_in, 471 ProxyShillWifiClient* shill_wifi_client) { 472 LOG(ERROR) << "RPC Method not implemented."; 473 return true; 474 } 475 476 ProxyRpcServerMethod::ProxyRpcServerMethod( 477 const std::string& method_name, 478 const RpcServerMethodHandler& handler, 479 ProxyShillWifiClient* shill_wifi_client, 480 ProxyRpcServer* server) 481 : XmlRpcServerMethod(method_name, server), 482 handler_(handler), 483 shill_wifi_client_(shill_wifi_client) { 484 } 485 486 void ProxyRpcServerMethod::execute( 487 XmlRpc::XmlRpcValue& params_in, 488 XmlRpc::XmlRpcValue& value_out) { 489 value_out = handler_.Run(params_in, shill_wifi_client_); 490 } 491 492 std::string ProxyRpcServerMethod::help(void) { 493 // TODO: Lookup the method help using the |method_name| from 494 // a text file. 495 return "Shill Test Proxy RPC methods help."; 496 } 497 498 ProxyRpcServer::ProxyRpcServer( 499 int server_port, 500 std::unique_ptr<ProxyShillWifiClient> shill_wifi_client) 501 : XmlRpcServer(), 502 server_port_(server_port), 503 shill_wifi_client_(std::move(shill_wifi_client)) { 504 } 505 506 void ProxyRpcServer::RegisterRpcMethod( 507 const std::string& method_name, 508 const RpcServerMethodHandler& handler) { 509 methods_.emplace_back( 510 new ProxyRpcServerMethod( 511 method_name, handler, shill_wifi_client_.get(), this)); 512 } 513 514 void ProxyRpcServer::Run() { 515 XmlRpc::setVerbosity(kDefaultXmlRpcVerbosity); 516 if (!XmlRpc::XmlRpcServer::bindAndListen(server_port_)) { 517 LOG(ERROR) << "Failed to bind to port " << server_port_ << "."; 518 return; 519 } 520 XmlRpc::XmlRpcServer::enableIntrospection(true); 521 522 RegisterRpcMethod("create_profile", base::Bind(&CreateProfile)); 523 RegisterRpcMethod("remove_profile", base::Bind(&RemoveProfile)); 524 RegisterRpcMethod("push_profile", base::Bind(&PushProfile)); 525 RegisterRpcMethod("pop_profile", base::Bind(&PopProfile)); 526 RegisterRpcMethod("clean_profiles", base::Bind(&CleanProfiles)); 527 RegisterRpcMethod("configure_service_by_guid", 528 base::Bind(&ConfigureServiceByGuid)); 529 RegisterRpcMethod("configure_wifi_service", base::Bind(&ConfigureWifiService)); 530 RegisterRpcMethod("connect_wifi", base::Bind(&ConnectWifi)); 531 RegisterRpcMethod("delete_entries_for_ssid", base::Bind(&DeleteEntriesForSsid)); 532 RegisterRpcMethod("init_test_network_state", base::Bind(&InitTestNetworkState)); 533 RegisterRpcMethod("list_controlled_wifi_interfaces", 534 base::Bind(&ListControlledWifiInterfaces)); 535 RegisterRpcMethod("disconnect", base::Bind(&Disconnect)); 536 RegisterRpcMethod("wait_for_service_states", 537 base::Bind(&WaitForServiceStates)); 538 RegisterRpcMethod("get_service_order", base::Bind(&GetServiceOrder)); 539 RegisterRpcMethod("set_service_order", base::Bind(&SetServiceOrder)); 540 RegisterRpcMethod("get_service_properties", base::Bind(&GetServiceProperties)); 541 RegisterRpcMethod("get_active_wifi_SSIDs", base::Bind(&GetActiveWifiSsids)); 542 RegisterRpcMethod("set_sched_scan", base::Bind(&SetSchedScan)); 543 RegisterRpcMethod("get_dbus_property_on_device", 544 base::Bind(&GetDbusPropertyOnDevice)); 545 RegisterRpcMethod("set_dbus_property_on_device", 546 base::Bind(&SetDbusPropertyOnDevice)); 547 RegisterRpcMethod("request_roam_dbus", base::Bind(&RequestRoamDbus)); 548 RegisterRpcMethod("set_device_enabled", base::Bind(&SetDeviceEnabled)); 549 RegisterRpcMethod("discover_tdls_link", base::Bind(&DiscoverTdlsLink)); 550 RegisterRpcMethod("establish_tdls_link", base::Bind(&EstablishTdlsLink)); 551 RegisterRpcMethod("query_tdls_link", base::Bind(&QueryTdlsLink)); 552 RegisterRpcMethod("add_wake_packet_source", base::Bind(&AddWakePacketSource)); 553 RegisterRpcMethod("remove_wake_packet_source", 554 base::Bind(&RemoveWakePacketSource)); 555 RegisterRpcMethod("remove_all_wake_packet_sources", 556 base::Bind(&RemoveAllWakePacketSources)); 557 RegisterRpcMethod("sync_time_to", 558 base::Bind(&SyncTimeTo)); 559 RegisterRpcMethod("request_roam", 560 base::Bind(&NotImplementedRpcMethod)); 561 RegisterRpcMethod("enable_ui", 562 base::Bind(&NotImplementedRpcMethod)); 563 RegisterRpcMethod("do_suspend", 564 base::Bind(&NotImplementedRpcMethod)); 565 RegisterRpcMethod("do_suspend_bg", 566 base::Bind(&NotImplementedRpcMethod)); 567 RegisterRpcMethod("clear_supplicant_blacklist", 568 base::Bind(&NotImplementedRpcMethod)); 569 RegisterRpcMethod("ready", 570 base::Bind(&NotImplementedRpcMethod)); 571 572 XmlRpc::XmlRpcServer::work(-1.0); 573 } 574