#!/usr/bin/python

# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Connect to a WiFi service and report the amount of time it took

This script initiates a connection to a WiFi service and reports
the time to major state changes (assoc, config).  If the connection
fails within the desired time, it outputs the contents of the log
files during that intervening time.

"""

import dbus
import gobject
import logging
import optparse
import sys
import time
import traceback
from site_wlan_wait_state import *

FLIMFLAM_ERROR = FLIMFLAM + '.Error'
FLIMFLAM_ERROR_INPROGRESS = FLIMFLAM_ERROR + '.InProgress'
FLIMFLAM_ERROR_UNKNOWNMETHOD = FLIMFLAM_ERROR + '.UnknownMethod'
FLIMFLAM_ERROR_ALREADYCONNECTED = FLIMFLAM_ERROR + '.AlreadyConnected'
connect_quirks = {}

def convert_dbus_value(value):
    if value.__class__ == dbus.Byte:
        return int(value)
    elif value.__class__ == dbus.Boolean:
        return bool(value)
    else:
        return value


class ConnectStateHandler(StateHandler):
  def __init__(self, dbus_bus, connection_settings, hidden, timeout,
               start_time=None, debug=False, scan_retry=8):
    self.connection_settings = connection_settings
    self.acquisition_time = None
    self.authentication_time = None
    self.configuration_time = None
    self.frequency = 0
    self.hidden = hidden
    self.phymode = None
    self.security = None
    self.service_handle = None
    self.scan_timeout = None
    self.scan_retry = scan_retry
    StateHandler.__init__(self, dbus_bus,
                          [(connection_settings['SSID'], 'State', 'ready',
                            False, True)],
                          timeout, None, timeout, debug)
    if start_time:
      self.run_start_time = start_time

    self.bus.add_signal_receiver(self.SupplicantChangeCallback,
                                 signal_name='PropertiesChanged',
                                 dbus_interface=SUPPLICANT+'.Interface')


  def _GetMatchedService(self, service_list):
    """Get a service matching the connection setting from a list of services.

    Args:
      service_list: An array of (1) DBus objects for Services with a specified
        ssid.

    Returns:
      The DBus object for the service that matches our connection_settings
      (None if nothing matched).
    """
    matched_service = None
    for svc in service_list:
      props = svc.GetProperties()
      set_props = {}
      for key, val in self.connection_settings.items():
        prop_val = convert_dbus_value(props.get(key))
        if key != 'SSID' and  prop_val != val:
          if key in ['Passphrase', 'SaveCredentials'] or key.startswith('EAP.'):
            set_props[key] = val
          else:
            self.Debug(
                'Service key mismatch: %s (desired "%s" != available "%s")' %
                (key, val, str(prop_val)))
            break
      else:
        for key, val in set_props.iteritems():
          try:
            self.Debug('Setting property %s to %s' % (key, val))
            svc.SetProperty(key, val)
          except dbus.exceptions.DBusException, e:
            self.failure = ('SetProperty: DBus exception %s for set of %s' %
                            (e, key))
            raise e

        matched_service = svc
        if self.scan_timeout is not None:
          gobject.source_remove(self.scan_timeout)
          self.scan_timeout = None
    return matched_service


  def FindService(self, path_list=None):
    service = None
    try:
      service = self._GetMatchedService(
         FindObjects('Service', 'SSID', self.service_name,
                      path_list=path_list))
    except dbus.exceptions.DBusException, e:
      # Failure reason must have been set by _GetMatchedService().
      return None

    if not service and self.hidden:
      try:
        path = manager.GetService(
            dbus.Dictionary(self.connection_settings, signature='sv'))
        service = dbus.Interface(
            self.bus.get_object(FLIMFLAM, path), FLIMFLAM + '.Service')
      except dbus.exceptions.DBusException, e:
        self.failure = ('GetService: DBus exception %s for settings %s' %
                        (e, self.connection_settings))
        return None
    elif not service:
      if not self.scan_timeout:
        self.DoScan()
        return None

    if not self.acquisition_time:
      self.acquisition_time = time.time()

    # If service isn't already connecting or connected, start now
    if (service.GetProperties()['State'] not in
        ('association', 'configuration', 'ready')):
      try:
        service.Connect()
      except dbus.exceptions.DBusException, e:
        if e.get_dbus_name() == FLIMFLAM_ERROR_INPROGRESS:
          self.Debug('Service was already in progress (state=%s)' %
                     service.GetProperties().get('State'))
          connect_quirks['in_progress'] = 1
        else:
          print 'FAIL(acquire): DBus exception in Connect() %s' % e
          ErrExit(2)
    else:
      self.Debug("skipping Connect call, service is in %s state" %
                 service.GetProperties()['State'])

    self.service_handle = service
    return service

  def DoScan(self):
    self.scan_timeout = None
    self.Debug('Service not found; requesting scan...')
    try:
      manager.RequestScan('wifi')
    except dbus.exceptions.DBusException, e:
      if e.get_dbus_name() != FLIMFLAM_ERROR_INPROGRESS:
        raise
    self.scan_timeout = gobject.timeout_add(int(self.scan_retry*1000),
                                                  self.DoScan)

  def StateChanged(self):
    # If we entered the "configuration" state, mark that down
    if self.svc_state == 'configuration':
      self.configuration_time = time.time()
    # NB: do this on all changes in case configuration is skipped
    props = self.service_handle.GetProperties()
    self.security = props.get('Security', None)
    self.frequency = props.get('WiFi.Frequency', 0)
    self.phymode = props.get('WiFi.PhyMode', None)

  def Stage(self):
    if not self.wait_path:
      return 'acquire'
    elif not self.configuration_time:
      return 'assoc'
    else:
      return 'config'

  def SupplicantChangeCallback(self, args, **kwargs):
    if 'State' in args:
      state = args['State']
      self.Debug('Supplicant state is \'%s\'' % state)
      if (not self.authentication_time and
          (state == 'authenticating' or state == 'associating')):
        self.authentication_time = time.time()
      elif state == 'inactive' or state == 'disconnected':
        self.authentication_time = None


def ErrExit(code):
  try:
    handler.service_handle.Disconnect()
  except:
    pass
  DumpLogs(logs)
  sys.exit(code)


def split_psk(settings, psk):
  cert_args = psk.split(':')
  for i in xrange(0, len(cert_args), 2):
    settings[cert_args[i]] = cert_args[i+1]


def main(argv):
  parser = optparse.OptionParser('Usage: %prog [options...] '
                                 'ssid security psk assoc_timeout cfg_timeout')
  parser.add_option('--hidden', dest='hidden', action='store_true',
                    help='This is a hidden network')
  parser.add_option('--debug', dest='debug', action='store_true',
                    help='Report state changes and other debug info')
  parser.add_option('--mode', dest='mode', default='managed',
                    help='AP mode')
  parser.add_option('--nosave', dest='save_creds', action='store_false',
                    default=True, help='Do not save credentials')
  (options, args) = parser.parse_args(argv[1:])

  if len(argv) <= 4:
    parser.error('Required arguments: ssid security psk assoc_timeount '
                 'config_timeout')

  ssid           = args[0]
  security       = args[1]
  psk            = args[2]
  assoc_timeout  = float(args[3])
  config_timeout = float(args[4])

  connection_settings = {
      'Type': 'wifi',
      'Mode': options.mode,
      'SSID': ssid,
      'SaveCredentials' : options.save_creds
  }

  if security:
    connection_settings['Security'] = security

  if security == '802_1x':
    split_psk(connection_settings, psk)
  elif security == '802_1x_wep':
    split_psk(connection_settings, psk)
    connection_settings['Security'] = 'wep'
  elif security in ['wep', 'wpa', 'rsn', 'psk']:
    connection_settings['Passphrase'] = psk

  global logs
  global handler
  logs = OpenLogs('/var/log/messages')

  assoc_start = time.time()
  handler = ConnectStateHandler(bus, connection_settings, options.hidden,
                                assoc_timeout, assoc_start, options.debug)
  try:
    if handler.NextState():
      handler.RunLoop()
  except dbus.exceptions.DBusException, e:
    if e.get_dbus_name() == FLIMFLAM_ERROR_INPROGRESS:
      connect_quirks['in_progress'] = 1
      print>>sys.stderr, 'Previous connect is still in progress!'
    if e.get_dbus_name() == FLIMFLAM_ERROR_UNKNOWNMETHOD:
      connect_quirks['lost_dbus_connect'] = 1
      print>>sys.stderr, 'Lost the service handle during Connect()!'
    if e.get_dbus_name() != FLIMFLAM_ERROR_ALREADYCONNECTED:
      print 'FAIL(%s): ssid %s DBus exception %s' % (handler.Stage(), ssid, e)
      ErrExit(2)
  except Exception, e:
    print 'FAIL(%s): ssid %s exception %s' % (handler.Stage(), ssid, e)
    traceback.print_exc(file=sys.stderr)
    ErrExit(2)
  if handler.Failure():
    print 'FAIL(%s): ssid %s %s' % (handler.Stage(), ssid, handler.Failure())
    ErrExit(2)

  end = time.time()
  config_start = handler.configuration_time
  acq_start = handler.acquisition_time
  if acq_start:
    acquire_time = acq_start - assoc_start
    assoc_start = acq_start
  else:
    acquire_time = 0.0
  auth_start = handler.authentication_time
  if auth_start:
    wpa_select_time = auth_start - assoc_start
    assoc_start = auth_start
  else:
    wpa_select_time = 0.0
  if config_start:
    config_time = end - config_start
    assoc_time = config_start - assoc_start
    if assoc_time < 0.0:
      assoc_time = 0.0
  else:
    config_time = 0.0
    assoc_time = end - assoc_start
  if not handler.Success():
    print ('TIMEOUT(%s): ssid %s acquire %3.3f wpa_select %3.3f assoc %3.3f '
           'config %3.3f secs state %s' %
           (handler.Stage(), ssid, acquire_time, wpa_select_time, assoc_time,
            config_time,
            handler.svc_state))
    ErrExit(3)

  print ('OK %3.3f %3.3f %3.3f %3.3f %d %s %s %s '
         '(acquire wpa_select assoc and config times in sec, quirks)' %
         (acquire_time, wpa_select_time, assoc_time, config_time,
          handler.frequency, handler.phymode, handler.security,
          str(connect_quirks.keys())))

  if connect_quirks:
    DumpLogs(logs)
  sys.exit(0)

if __name__ == '__main__':
  main(sys.argv)
