1# Lint as: python2, python3 2# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6import copy 7import logging 8import pprint 9import sys 10 11from autotest_lib.client.common_lib.cros import xmlrpc_types 12from autotest_lib.client.common_lib.cros.network import xmlrpc_security_types 13 14 15def deserialize(serialized): 16 """Deserialize an argument to the XmlRpc proxy. 17 18 @param serialized dict representing a serialized object. 19 @return the corresponding deserialized object. 20 21 """ 22 return xmlrpc_types.deserialize(serialized, module=sys.modules[__name__]) 23 24 25class AssociationParameters(xmlrpc_types.XmlRpcStruct): 26 """Describes parameters used in WiFi connection attempts.""" 27 28 DEFAULT_DISCOVERY_TIMEOUT = 15 29 DEFAULT_ASSOCIATION_TIMEOUT = 15 30 DEFAULT_CONFIGURATION_TIMEOUT = 15 31 # Mode for most routers and access points. 32 STATION_TYPE_MANAGED = 'managed' 33 # Mode for certain kinds of p2p networks like old Android phone hotspots. 34 STATION_TYPE_IBSS = 'ibss' 35 36 @property 37 def security(self): 38 """@return string security type for this network.""" 39 return self.security_config.security 40 41 42 @property 43 def security_parameters(self): 44 """@return dict of service property/value pairs related to security.""" 45 return self.security_config.get_shill_service_properties() 46 47 48 def __init__(self, ssid=None, security_config=None, 49 discovery_timeout=DEFAULT_DISCOVERY_TIMEOUT, 50 association_timeout=DEFAULT_ASSOCIATION_TIMEOUT, 51 configuration_timeout=DEFAULT_CONFIGURATION_TIMEOUT, 52 is_hidden=False, save_credentials=False, station_type=None, 53 expect_failure=False, guid=None, autoconnect=None, 54 bgscan_config=None): 55 """Construct an AssociationParameters. 56 57 @param ssid string the network to connect to (e.g. 'GoogleGuest'). 58 @param security_config SecurityConfig object or serialized version. 59 @param discovery_timeout int timeout for discovery in seconds. 60 @param association_timeout int timeout for association in seconds. 61 @param configuration_timeout int timeout for configuration in seconds. 62 @param is_hidden bool True iff this is a hidden service. 63 @param save_credentials True iff the credentials should be saved for 64 this service. 65 @param station_type string station type to connect with. Usually 66 left unfilled unless we're attempting to connect to a 67 non-managed BSS. One of STATION_TYPE_* above. 68 @param expect_failure bool True if we expect this connection attempt to 69 fail. 70 @param guid string unique identifier of this service. 71 @param autoconnect: bool or None. None indicates that this should not 72 be set one way or the other, while a boolean indicates a desired 73 value. 74 75 """ 76 super(AssociationParameters, self).__init__() 77 self.ssid = ssid 78 # The security config is a little tricky. When we're being deserialized 79 # this is passed to us in the form of a dictionary which also needs 80 # to be deserialized into a real object. 81 if isinstance(security_config, dict): 82 self.security_config = xmlrpc_security_types.deserialize( 83 security_config) 84 elif security_config is not None: 85 self.security_config = copy.copy(security_config) 86 else: 87 self.security_config = xmlrpc_security_types.SecurityConfig() 88 89 # The bgscan configuration is similar to the security configuration. 90 if isinstance(bgscan_config, dict): 91 self.bgscan_config = deserialize(bgscan_config) 92 elif bgscan_config is not None: 93 self.bgscan_config = copy.copy(bgscan_config) 94 else: 95 self.bgscan_config = BgscanConfiguration() 96 self.discovery_timeout = discovery_timeout 97 self.association_timeout = association_timeout 98 self.configuration_timeout = configuration_timeout 99 self.is_hidden = is_hidden 100 self.save_credentials = save_credentials 101 self.station_type = station_type 102 self.expect_failure = expect_failure 103 self.guid = guid 104 self.autoconnect = autoconnect 105 106 107 def __str__(self): 108 """Returns a formatted string of member parameters""" 109 return pprint.pformat(self.__dict__) 110 111 112class AssociationResult(xmlrpc_types.XmlRpcStruct): 113 """Describes the result of an association attempt.""" 114 115 def __init__(self, success=False, discovery_time=-1.0, 116 association_time=-1.0, configuration_time=-1.0, 117 failure_reason='unknown'): 118 """Construct an AssociationResult. 119 120 @param success bool True iff we were successful in connecting to 121 this WiFi network. 122 @param discovery_time int number of seconds it took to find and call 123 connect on a network from the time the proxy is told to connect. 124 This includes scanning time. 125 @param association_time int number of seconds it takes from the moment 126 that we call connect to the moment we're fully associated with 127 the BSS. This includes wpa handshakes. 128 @param configuration_time int number of seconds it takes from 129 association till we have an IP address and mark the network as 130 being either online or portalled. 131 @param failure_reason int holds a descriptive reason for why the 132 negotiation failed when |successs| is False. Undefined 133 otherwise. 134 135 """ 136 super(AssociationResult, self).__init__() 137 self.success = success 138 self.discovery_time = discovery_time 139 self.association_time = association_time 140 self.configuration_time = configuration_time 141 self.failure_reason = failure_reason 142 143 144 @staticmethod 145 def from_dbus_proxy_output(raw): 146 """Factory for AssociationResult. 147 148 The object which knows how to talk over DBus to shill is not part of 149 autotest and as a result can't return a AssociationResult. Instead, 150 it returns a similar looing tuple, which we'll parse. 151 152 @param raw tuple from ShillProxy. 153 @return AssociationResult parsed output from ShillProxy. 154 155 """ 156 return AssociationResult(success=raw[0], 157 discovery_time=raw[1], 158 association_time=raw[2], 159 configuration_time=raw[3], 160 failure_reason=raw[4]) 161 162 163class BgscanConfiguration(xmlrpc_types.XmlRpcStruct): 164 """Describes how to configure wpa_supplicant on a DUT.""" 165 166 # Clears shill's bgscan method property on the WiFi device. 167 # This causes shill to choose between simple and no bgscan 168 # depending on the number of visible BSS's for a network. 169 SCAN_METHOD_DEFAULT = 'default' 170 # Disables background scan entirely. 171 SCAN_METHOD_NONE = 'none' 172 # A periodic background scan based on signal strength. 173 SCAN_METHOD_SIMPLE = 'simple' 174 175 # These three parameters come out shill's wifi.cc. 176 # and refer to inputs to the simple scanning method. 177 DEFAULT_SHORT_INTERVAL_SECONDS = 64 178 DEFAULT_LONG_INTERVAL_SECONDS = 60 179 DEFAULT_SIGNAL_THRESHOLD = -72 180 181 def __init__(self, interface=None, signal=DEFAULT_SIGNAL_THRESHOLD, 182 short_interval=DEFAULT_SHORT_INTERVAL_SECONDS, 183 long_interval=DEFAULT_LONG_INTERVAL_SECONDS, 184 method=SCAN_METHOD_DEFAULT): 185 """Construct a BgscanConfiguration. 186 187 @param interface string interface to configure (e.g. wlan0). 188 @param signal int signal threshold to scan below. 189 @param short_interval int wpa_supplicant short scanning interval. 190 @param long_interval int wpa_supplicant normal scanning interval. 191 @param method string a valid wpa_supplicant scanning algorithm (e.g. 192 any of SCAN_METHOD_* above). 193 194 """ 195 super(BgscanConfiguration, self).__init__() 196 self.interface = interface 197 self.signal = signal 198 self.short_interval = short_interval 199 self.long_interval = long_interval 200 self.method = method 201 202 203 def set_auto_signal(self, signal_average, signal_offset=None, 204 signal_noise=None): 205 """Set the signal threshold automatically from observed parameters. 206 207 @param signal_average int average signal level. 208 @param signal_offset int amount to adjust the average by. 209 @param signal_noise int amount of background noise observed. 210 211 """ 212 signal = signal_average 213 if signal_offset: 214 signal += signal_offset 215 if signal_noise: 216 # Compensate for real noise vs standard estimate 217 signal -= 95 + signal_noise 218 logging.debug('Setting signal via auto configuration: ' 219 'avg=%d, offset=%r, noise=%r => signal=%d.', 220 signal_average, signal_offset, signal_noise, signal) 221 self.signal = signal 222 223 224class ConfigureServiceParameters(xmlrpc_types.XmlRpcStruct): 225 """Describes a group of optional settings for use with ConfigureService. 226 227 The Manager in shill has a method ConfigureService which takes a dictionary 228 of parameters, and uses some of them to look up a service, and sets the 229 remainder of the properties on the service. This struct represents 230 some of the optional parameters that can be set in this way. Current 231 consumers of this interface look up the service by GUID. 232 233 """ 234 235 def __init__(self, guid, passphrase=None, autoconnect=None): 236 """Construct a ConfigureServiceParameters. 237 238 @param guid string GUID of the service to configure. 239 @param passphrase string optional psk passphrase. 240 @param autoconnect: bool or None. None indicates that this should not 241 be set one way or the other, while a boolean indicates a desired 242 value. 243 244 """ 245 super(ConfigureServiceParameters, self).__init__() 246 self.guid = guid 247 self.passphrase = passphrase 248 self.autoconnect = autoconnect 249