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