Some work on the network devices

This commit is contained in:
Marco Pesenti Gritti 2007-02-25 02:00:40 +01:00
parent 89aa65d0f6
commit 755250947a
14 changed files with 990 additions and 15 deletions

View File

@ -1,4 +1,4 @@
SUBDIRS = data model view SUBDIRS = data hardware model view
bin_SCRIPTS = \ bin_SCRIPTS = \
sugar-activity \ sugar-activity \

View File

@ -1,4 +1,6 @@
sugardir = $(pkgdatadir)/shell/hardware sugardir = $(pkgdatadir)/shell/hardware
sugar_PYTHON = \ sugar_PYTHON = \
__init__.py \ __init__.py \
hardwaremanager.py hardwaremanager.py \
nmclient.py \
nminfo.py

View File

@ -18,6 +18,7 @@ import logging
import dbus import dbus
from hardware.nmclient import NMClient
from _sugar import AudioManager from _sugar import AudioManager
_HARDWARE_MANAGER_INTERFACE = 'org.laptop.HardwareManager' _HARDWARE_MANAGER_INTERFACE = 'org.laptop.HardwareManager'
@ -65,5 +66,9 @@ def get_hardware_manager():
def get_audio_manager(): def get_audio_manager():
return _audio_manager return _audio_manager
def get_network_manager():
return _network_manager
_hardware_manager = HardwareManager() _hardware_manager = HardwareManager()
_audio_manager = AudioManager() _audio_manager = AudioManager()
_network_manager = NMClient()

467
shell/hardware/nmclient.py Normal file
View File

@ -0,0 +1,467 @@
#
# Copyright (C) 2006, Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import logging
import os
import dbus
import dbus.glib
import dbus.decorators
import gobject
from hardware import nminfo
IW_AUTH_ALG_OPEN_SYSTEM = 0x00000001
IW_AUTH_ALG_SHARED_KEY = 0x00000002
NM_DEVICE_STAGE_STRINGS=("Unknown",
"Prepare",
"Config",
"Need Users Key",
"IP Config",
"IP Config Get",
"IP Config Commit",
"Activated",
"Failed",
"Cancled"
)
NM_SERVICE = 'org.freedesktop.NetworkManager'
NM_IFACE = 'org.freedesktop.NetworkManager'
NM_IFACE_DEVICES = 'org.freedesktop.NetworkManager.Devices'
NM_PATH = '/org/freedesktop/NetworkManager'
DEVICE_TYPE_UNKNOWN = 0
DEVICE_TYPE_802_3_ETHERNET = 1
DEVICE_TYPE_802_11_WIRELESS = 2
NM_DEVICE_CAP_NONE = 0x00000000
NM_DEVICE_CAP_NM_SUPPORTED = 0x00000001
NM_DEVICE_CAP_CARRIER_DETECT = 0x00000002
NM_DEVICE_CAP_WIRELESS_SCAN = 0x00000004
sys_bus = dbus.SystemBus()
NM_802_11_CAP_NONE = 0x00000000
NM_802_11_CAP_PROTO_NONE = 0x00000001
NM_802_11_CAP_PROTO_WEP = 0x00000002
NM_802_11_CAP_PROTO_WPA = 0x00000004
NM_802_11_CAP_PROTO_WPA2 = 0x00000008
NM_802_11_CAP_KEY_MGMT_PSK = 0x00000040
NM_802_11_CAP_KEY_MGMT_802_1X = 0x00000080
NM_802_11_CAP_CIPHER_WEP40 = 0x00001000
NM_802_11_CAP_CIPHER_WEP104 = 0x00002000
NM_802_11_CAP_CIPHER_TKIP = 0x00004000
NM_802_11_CAP_CIPHER_CCMP = 0x00008000
class Network(gobject.GObject):
__gsignals__ = {
'init-failed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([]))
}
def __init__(self, op):
gobject.GObject.__init__(self)
self._op = op
self._ssid = None
self._mode = None
self._strength = 0
self._valid = False
obj = sys_bus.get_object(NM_SERVICE, self._op)
net = dbus.Interface(obj, NM_IFACE_DEVICES)
net.getProperties(reply_handler=self._update_reply_cb,
error_handler=self._update_error_cb)
def _update_reply_cb(self, *props):
self._ssid = props[1]
self._strength = props[3]
self._mode = props[6]
caps = props[7]
if caps & NM_802_11_CAP_PROTO_WPA or caps & NM_802_11_CAP_PROTO_WPA2:
# We do not support WPA at this time, so don't show
# WPA-enabled access points in the menu
logging.debug("Net(%s): ssid '%s' dropping because WPA[2] unsupported" % (self._op,
self._ssid))
self._valid = False
self.emit('init-failed')
else:
self._valid = True
logging.debug("Net(%s): ssid '%s', mode %d, strength %d" % (self._op,
self._ssid, self._mode, self._strength))
def _update_error_cb(self, err):
logging.debug("Net(%s): failed to update. (%s)" % (self._op, err))
self._valid = False
self.emit('init-failed')
def get_ssid(self):
return self._ssid
def get_op(self):
return self._op
def get_strength(self):
return self._strength
def set_strength(self, strength):
self._strength = strength
def is_valid(self):
return self._valid
class Device(gobject.GObject):
__gsignals__ = {
'init-failed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
'activated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
'strength-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT]))
}
def __init__(self, op):
gobject.GObject.__init__(self)
self._op = op
self._iface = None
self._type = DEVICE_TYPE_UNKNOWN
self._udi = None
self._active = False
self._strength = 0
self._link = False
self._valid = False
self._networks = {}
self._active_net = None
self._caps = 0
obj = sys_bus.get_object(NM_SERVICE, self._op)
dev = dbus.Interface(obj, NM_IFACE_DEVICES)
dev.getProperties(reply_handler=self._update_reply_cb,
error_handler=self._update_error_cb)
def _update_reply_cb(self, *props):
self._iface = props[1]
self._type = props[2]
self._udi = props[3]
self._active = props[4]
if self._active:
self.emit('activated')
self._link = props[15]
self._caps = props[17]
if self._type == DEVICE_TYPE_802_11_WIRELESS:
old_strength = self._strength
self._strength = props[14]
if self._strength != old_strength:
self.emit('strength-changed', self._strength)
self._update_networks(props[20], props[19])
self._valid = True
def _update_networks(self, net_ops, active_op):
for op in net_ops:
net = Network(op)
self._networks[op] = net
net.connect('init-failed', self._net_init_failed)
if op == active_op:
self._active_net = op
def _update_error_cb(self, err):
logging.debug("Device(%s): failed to update. (%s)" % (self._op, err))
self._valid = False
self.emit('init-failed')
def _net_init_failed(self, net):
net_op = net.get_op()
if not self._networks.has_key(net_op):
return
if net_op == self._active_net:
self._active_net = None
del self._networks[net_op]
def get_op(self):
return self._op
def get_network(self, op):
if self._networks.has_key(op):
return self._networks[op]
return None
def get_network_ops(self):
return self._networks.keys()
def get_strength(self):
return self._strength
def set_strength(self, strength):
if strength == self._strength:
return False
if strength >= 0 and strength <= 100:
self._strength = strength
else:
self._strength = 0
self.emit('strength-changed', self._strength)
def network_appeared(self, network):
if self._networks.has_key(network):
return
net = Network(network)
self._networks[network] = net
net.connect('init-failed', self._net_init_failed)
def network_disappeared(self, network):
if not self._networks.has_key(network):
return
if network == self._active_net:
self._active_net = None
del self._networks[network]
def get_active(self):
return self._active
def set_active(self, active, ssid=None):
self._active = active
if self._type == DEVICE_TYPE_802_11_WIRELESS:
if not ssid:
self._active_net = None
else:
for (op, net) in self._networks.items():
if net.get_ssid() == ssid:
self._active_net = op
def get_type(self):
return self._type
def is_valid(self):
return self._valid
def set_carrier(self, on):
self._link = on
def get_capabilities(self):
return self._caps
NM_STATE_UNKNOWN = 0
NM_STATE_ASLEEP = 1
NM_STATE_CONNECTING = 2
NM_STATE_CONNECTED = 3
NM_STATE_DISCONNECTED = 4
class NMClient(object):
def __init__(self):
self.nminfo = None
self._nm_present = False
self._nm_state = NM_STATE_UNKNOWN
self._update_timer = 0
self._active_device = None
self._devices = {}
try:
self.nminfo = nminfo.NMInfo(self)
except RuntimeError:
pass
self._setup_dbus()
if self._nm_present:
self._get_nm_state()
self._get_initial_devices()
def get_devices(self):
return self._devices
def _get_nm_state(self):
# Grab NM's state
self._nm_obj.state(reply_handler=self._get_state_reply_cb, \
error_handler=self._get_state_error_cb)
def _get_state_reply_cb(self, state):
self._nm_state = state
def _get_state_error_cb(self, err):
logging.debug("Failed to get NetworkManager state! %s" % err)
def _get_initial_devices_reply_cb(self, ops):
for op in ops:
self._add_device(op)
def _dev_init_failed_cb(self, dev):
# Device failed to initialize, likely due to dbus errors or something
op = dev.get_op()
self._remove_device(op)
def _get_initial_devices_error_cb(self, err):
logging.debug("Error updating devices (%s)" % err)
def _get_initial_devices(self):
self._nm_obj.getDevices(reply_handler=self._get_initial_devices_reply_cb, \
error_handler=self._get_initial_devices_error_cb)
def _add_device(self, dev_op):
if self._devices.has_key(dev_op):
return
dev = Device(dev_op)
self._devices[dev_op] = dev
dev.connect('init-failed', self._dev_init_failed_cb)
dev.connect('activated', self._dev_activated_cb)
dev.connect('strength-changed', self._dev_strength_changed_cb)
def _remove_device(self, dev_op):
if not self._devices.has_key(dev_op):
return
if self._active_device == dev_op:
self._active_device = None
dev = self._devices[dev_op]
dev.disconnect('activated')
dev.disconnect('init-failed')
dev.disconnect('strength-changed')
del self._devices[dev_op]
def _dev_activated_cb(self, dev):
op = dev.get_op()
if not self._devices.has_key(op):
return
if not dev.get_active():
return
self._active_device = op
def _dev_strength_changed_cb(self, dev, strength):
op = dev.get_op()
if not self._devices.has_key(op):
return
if not dev.get_active():
return
def get_device(self, dev_op):
if not self._devices.has_key(dev_op):
return None
return self._devices[dev_op]
def _setup_dbus(self):
self._sig_handlers = {
'StateChange': self.state_change_sig_handler,
'DeviceAdded': self.device_added_sig_handler,
'DeviceRemoved': self.device_removed_sig_handler,
'DeviceActivationStage': self.device_activation_stage_sig_handler,
'DeviceActivating': self.device_activating_sig_handler,
'DeviceNowActive': self.device_now_active_sig_handler,
'DeviceNoLongerActive': self.device_no_longer_active_sig_handler,
'DeviceCarrierOn': self.device_carrier_on_sig_handler,
'DeviceCarrierOff': self.device_carrier_off_sig_handler,
'DeviceStrengthChanged': self.wireless_device_strength_changed_sig_handler,
'WirelessNetworkAppeared': self.wireless_network_appeared_sig_handler,
'WirelessNetworkDisappeared': self.wireless_network_disappeared_sig_handler,
'WirelessNetworkStrengthChanged': self.wireless_network_strength_changed_sig_handler
}
self._nm_proxy = sys_bus.get_object(NM_SERVICE, NM_PATH)
self._nm_obj = dbus.Interface(self._nm_proxy, NM_IFACE)
sys_bus.add_signal_receiver(self.name_owner_changed_sig_handler,
signal_name="NameOwnerChanged",
dbus_interface="org.freedesktop.DBus")
for (signal, handler) in self._sig_handlers.items():
sys_bus.add_signal_receiver(handler, signal_name=signal, dbus_interface=NM_IFACE)
# Find out whether or not NM is running
try:
bus_object = sys_bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
name = bus_object.GetNameOwner("org.freedesktop.NetworkManagerInfo", \
dbus_interface='org.freedesktop.DBus')
if name:
self._nm_present = True
except dbus.DBusException:
pass
def get_key_for_network(self, net, async_cb, async_err_cb):
pass
def device_activation_stage_sig_handler(self, device, stage):
logging.debug('Device Activation Stage "%s" for device %s' % (NM_DEVICE_STAGE_STRINGS[stage], device))
def state_change_sig_handler(self, state):
self._nm_state = state
def device_activating_sig_handler(self, device):
self._active_device = device
def device_now_active_sig_handler(self, device, ssid=None):
if not self._devices.has_key(device):
return
self._active_device = device
self._devices[device].set_active(True, ssid)
def device_no_longer_active_sig_handler(self, device):
if not self._devices.has_key(device):
return
if self._active_device == device:
self._active_device = None
self._devices[device].set_active(False)
def name_owner_changed_sig_handler(self, name, old, new):
if name != NM_SERVICE:
return
if (old and len(old)) and (not new and not len(new)):
# NM went away
self._nm_present = False
for op in self._devices.keys():
del self._devices[op]
self._devices = {}
self._active_device = None
self._nm_state = NM_STATE_UNKNOWN
elif (not old and not len(old)) and (new and len(new)):
# NM started up
self._nm_present = True
self._get_nm_state()
self._get_initial_devices()
def device_added_sig_handler(self, device):
self._add_device(device)
def device_removed_sig_handler(self, device):
self._remove_device(device)
def wireless_network_appeared_sig_handler(self, device, network):
if not self._devices.has_key(device):
return
self._devices[device].network_appeared(network)
def wireless_network_disappeared_sig_handler(self, device, network):
if not self._devices.has_key(device):
return
self._devices[device].network_disappeared(network)
def wireless_device_strength_changed_sig_handler(self, device, strength):
if not self._devices.has_key(device):
return
self._devices[device].set_strength(strength)
def wireless_network_strength_changed_sig_handler(self, device, network, strength):
if not self._devices.has_key(device):
return
net = self._devices[device].get_network(network)
if net:
net.set_strength(strength)
def device_carrier_on_sig_handler(self, device):
if not self._devices.has_key(device):
return
self._devices[device].set_carrier(True)
def device_carrier_off_sig_handler(self, device):
if not self._devices.has_key(device):
return
self._devices[device].set_carrier(False)

467
shell/hardware/nminfo.py Normal file
View File

@ -0,0 +1,467 @@
# vi: ts=4 ai noet
#
# Copyright (C) 2006, Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import dbus
import dbus.service
import time
import os
import binascii
import ConfigParser
import logging
import nmclient
try:
from sugar import env
except ImportError:
pass
NM_INFO_IFACE='org.freedesktop.NetworkManagerInfo'
NM_INFO_PATH='/org/freedesktop/NetworkManagerInfo'
class NoNetworks(dbus.DBusException):
def __init__(self):
dbus.DBusException.__init__(self)
self._dbus_error_name = NM_INFO_IFACE + '.NoNetworks'
class CanceledKeyRequestError(dbus.DBusException):
def __init__(self):
dbus.DBusException.__init__(self)
self._dbus_error_name = NM_INFO_IFACE + '.CanceledError'
class NetworkInvalidError(Exception):
pass
class NMConfig(ConfigParser.ConfigParser):
def get_bool(self, section, name):
opt = self.get(section, name)
if type(opt) == type(""):
if opt.lower() == 'yes' or opt.lower() == 'true':
return True
elif opt.lower() == 'no' or opt.lower() == 'false':
return False
raise ValueError("Invalid format for %s/%s. Should be one of [yes, no, true, false]." % (section, name))
def get_list(self, section, name):
opt = self.get(section, name)
if type(opt) == type(""):
if not len(opt):
return []
try:
return opt.split()
except Exception:
pass
raise ValueError("Invalid format for %s/%s. Should be a space-separate list." % (section, name))
def get_int(self, section, name):
opt = self.get(section, name)
try:
return int(opt)
except Exception:
pass
raise ValueError("Invalid format for %s/%s. Should be a valid integer." % (section, name))
def get_float(self, section, name):
opt = self.get(section, name)
try:
return float(opt)
except Exception:
pass
raise ValueError("Invalid format for %s/%s. Should be a valid float." % (section, name))
IW_AUTH_CIPHER_NONE = 0x00000001
IW_AUTH_CIPHER_WEP40 = 0x00000002
IW_AUTH_CIPHER_TKIP = 0x00000004
IW_AUTH_CIPHER_CCMP = 0x00000008
IW_AUTH_CIPHER_WEP104 = 0x00000010
IW_AUTH_ALG_OPEN_SYSTEM = 0x00000001
IW_AUTH_ALG_SHARED_KEY = 0x00000002
NETWORK_TYPE_UNKNOWN = 0
NETWORK_TYPE_ALLOWED = 1
NETWORK_TYPE_INVALID = 2
class Security(object):
def __init__(self, we_cipher):
self._we_cipher = we_cipher
def read_from_config(self, cfg, name):
pass
def read_from_args(self, args):
pass
def new_from_config(cfg, name):
security = None
try:
we_cipher = cfg.get_int(name, "we_cipher")
if we_cipher == IW_AUTH_CIPHER_NONE:
security = Security(we_cipher)
elif we_cipher == IW_AUTH_CIPHER_WEP40 or we_cipher == IW_AUTH_CIPHER_WEP104:
security = WEPSecurity(we_cipher)
else:
# FIXME: find a way to make WPA config option matrix not
# make you want to throw up
raise ValueError("Unsupported security combo")
security.read_from_config(cfg, name)
except (ConfigParser.NoOptionError, ValueError), e:
return None
return security
new_from_config = staticmethod(new_from_config)
def new_from_args(we_cipher, args):
security = None
try:
if we_cipher == IW_AUTH_CIPHER_NONE:
security = Security(we_cipher)
elif we_cipher == IW_AUTH_CIPHER_WEP40 or we_cipher == IW_AUTH_CIPHER_WEP104:
security = WEPSecurity(we_cipher)
else:
# FIXME: find a way to make WPA config option matrix not
# make you want to throw up
raise ValueError("Unsupported security combo")
security.read_from_args(args)
except ValueError, e:
logging.debug("Error reading security information: %s" % e)
del security
return None
return security
new_from_args = staticmethod(new_from_args)
def get_properties(self):
return [dbus.Int32(self._we_cipher)]
def write_to_config(self, section, config):
config.set(section, "we_cipher", self._we_cipher)
class WEPSecurity(Security):
def read_from_args(self, args):
if len(args) != 2:
raise ValueError("not enough arguments")
key = args[0]
auth_alg = args[1]
if isinstance(key, unicode):
key = key.encode()
if not isinstance(key, str):
raise ValueError("wrong argument type for key")
if not isinstance(auth_alg, int):
raise ValueError("wrong argument type for auth_alg")
self._key = key
self._auth_alg = auth_alg
def read_from_config(self, cfg, name):
# Key should be a hex encoded string
self._key = cfg.get(name, "key")
if self._we_cipher == IW_AUTH_CIPHER_WEP40 and len(self._key) != 10:
raise ValueError("Key length not right for 40-bit WEP")
if self._we_cipher == IW_AUTH_CIPHER_WEP104 and len(self._key) != 26:
raise ValueError("Key length not right for 104-bit WEP")
try:
a = binascii.a2b_hex(self._key)
except TypeError:
raise ValueError("Key was not a hexadecimal string.")
self._auth_alg = cfg.get_int(name, "auth_alg")
if self._auth_alg != IW_AUTH_ALG_OPEN_SYSTEM and self._auth_alg != IW_AUTH_ALG_SHARED_KEY:
raise ValueError("Invalid authentication algorithm %d" % self._auth_alg)
def get_properties(self):
args = Security.get_properties(self)
args.append(dbus.String(self._key))
args.append(dbus.Int32(self._auth_alg))
return args
def write_to_config(self, section, config):
Security.write_to_config(self, section, config)
config.set(section, "key", self._key)
config.set(section, "auth_alg", self._auth_alg)
class Network:
def __init__(self, ssid):
self.ssid = ssid
self.timestamp = int(time.time())
self.bssids = []
self.we_cipher = 0
self._security = None
def get_properties(self):
bssid_list = dbus.Array([], signature="s")
for item in self.bssids:
bssid_list.append(dbus.String(item))
args = [dbus.String(self.ssid), dbus.Int32(self.timestamp), dbus.Boolean(True), bssid_list]
args += self._security.get_properties()
return tuple(args)
def get_security(self):
return self._security.get_properties()
def set_security(self, security):
self._security = security
def read_from_args(self, auto, bssid, we_cipher, args):
if auto == False:
self.timestamp = int(time.time())
if not bssid in self.bssids:
self.bssids.append(bssid)
self._security = Security.new_from_args(we_cipher, args)
if not self._security:
raise NetworkInvalidError("Invalid security information")
def read_from_config(self, config):
try:
self.timestamp = config.get_int(self.ssid, "timestamp")
except (ConfigParser.NoOptionError, ValueError), e:
raise NetworkInvalidError(e)
self._security = Security.new_from_config(config, self.ssid)
if not self._security:
raise NetworkInvalidError(e)
# The following don't need to be present
try:
self.bssids = config.get_list(self.ssid, "bssids")
except (ConfigParser.NoOptionError, ValueError), e:
pass
def write_to_config(self, config):
try:
config.add_section(self.ssid)
config.set(self.ssid, "timestamp", self.timestamp)
if len(self.bssids) > 0:
opt = " "
opt.join(self.bssids)
config.set(self.ssid, "bssids", opt)
self._security.write_to_config(self.ssid, config)
except Exception, e:
logging.debug("Error writing '%s': %s" % (self.ssid, e))
class NotFoundError(dbus.DBusException):
pass
class UnsupportedError(dbus.DBusException):
pass
class NMInfoDBusServiceHelper(dbus.service.Object):
def __init__(self, parent):
self._parent = parent
bus = dbus.SystemBus()
# If NMI is already around, don't grab the NMI service
bus_object = bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
name = None
try:
name = bus_object.GetNameOwner("org.freedesktop.NetworkManagerInfo", \
dbus_interface='org.freedesktop.DBus')
except dbus.DBusException:
pass
if name:
logging.debug("NMI service already owned by %s, won't claim it." % name)
raise RuntimeError
bus_name = dbus.service.BusName(NM_INFO_IFACE, bus=bus)
dbus.service.Object.__init__(self, bus_name, NM_INFO_PATH)
@dbus.service.method(NM_INFO_IFACE, in_signature='i', out_signature='as')
def getNetworks(self, net_type):
ssids = self._parent.get_networks(net_type)
if len(ssids) > 0:
return dbus.Array(ssids)
raise NoNetworks()
@dbus.service.method(NM_INFO_IFACE, in_signature='si', async_callbacks=('async_cb', 'async_err_cb'))
def getNetworkProperties(self, ssid, net_type, async_cb, async_err_cb):
self._parent.get_network_properties(ssid, net_type, async_cb, async_err_cb)
@dbus.service.method(NM_INFO_IFACE)
def updateNetworkInfo(self, ssid, bauto, bssid, cipher, *args):
self._parent.update_network_info(ssid, bauto, bssid, cipher, args)
@dbus.service.method(NM_INFO_IFACE, async_callbacks=('async_cb', 'async_err_cb'))
def getKeyForNetwork(self, dev_path, net_path, ssid, attempt, new_key, async_cb, async_err_cb):
self._parent.get_key_for_network(dev_path, net_path, ssid,
attempt, new_key, async_cb, async_err_cb)
@dbus.service.method(NM_INFO_IFACE)
def cancelGetKeyForNetwork(self):
self._parent.cancel_get_key_for_network()
class NMInfo(object):
def __init__(self, client):
try:
profile_path = env.get_profile_path()
except NameError:
home = os.path.expanduser("~")
profile_path = os.path.join(home, ".sugar", "default")
self._cfg_file = os.path.join(profile_path, "nm", "networks.cfg")
self._nmclient = client
self._allowed_networks = self._read_config()
self._dbus_helper = NMInfoDBusServiceHelper(self)
def save_config(self):
self._write_config(self._allowed_networks)
def _read_config(self):
if not os.path.exists(os.path.dirname(self._cfg_file)):
os.makedirs(os.path.dirname(self._cfg_file), 0755)
if not os.path.exists(self._cfg_file):
self._write_config({})
return {}
config = NMConfig()
config.read(self._cfg_file)
networks = {}
for name in config.sections():
if not isinstance(name, unicode):
name = unicode(name)
net = Network(name)
try:
net.read_from_config(config)
networks[name] = net
except NetworkInvalidError, e:
logging.debug("Error: invalid stored network config: %s" % e)
del net
del config
return networks
def _write_config(self, networks):
fp = open(self._cfg_file, 'w')
config = NMConfig()
for net in networks.values():
net.write_to_config(config)
config.write(fp)
fp.close()
del config
def get_networks(self, net_type):
if net_type != NETWORK_TYPE_ALLOWED:
raise ValueError("Bad network type")
nets = []
for net in self._allowed_networks.values():
nets.append(net.ssid)
logging.debug("Returning networks: %s" % nets)
return nets
def get_network_properties(self, ssid, net_type, async_cb, async_err_cb):
if not isinstance(ssid, unicode):
async_err_cb(ValueError("Invalid arguments; ssid must be unicode."))
if net_type != NETWORK_TYPE_ALLOWED:
async_err_cb(ValueError("Bad network type"))
if not self._allowed_networks.has_key(ssid):
async_err_cb(NotFoundError("Network '%s' not found." % ssid))
network = self._allowed_networks[ssid]
props = network.get_properties()
# DBus workaround: the normal method return handler wraps
# the returned arguments in a tuple and then converts that to a
# struct, but NetworkManager expects a plain list of arguments.
# It turns out that the async callback method return code _doesn't_
# wrap the returned arguments in a tuple, so as a workaround use
# the async callback stuff here even though we're not doing it
# asynchronously.
async_cb(*props)
def update_network_info(self, ssid, auto, bssid, we_cipher, args):
if not isinstance(ssid, unicode):
raise ValueError("Invalid arguments; ssid must be unicode.")
if self._allowed_networks.has_key(ssid):
del self._allowed_networks[ssid]
net = Network(ssid)
try:
net.read_from_args(auto, bssid, we_cipher, args)
logging.debug("Updated network information for '%s'." % ssid)
self._allowed_networks[ssid] = net
self.save_config()
except NetworkInvalidError, e:
logging.debug("Error updating network information: %s" % e)
del net
def get_key_for_network(self, dev_op, net_op, ssid, attempt, new_key, async_cb, async_err_cb):
if not isinstance(ssid, unicode):
raise ValueError("Invalid arguments; ssid must be unicode.")
if self._allowed_networks.has_key(ssid) and not new_key:
# We've got the info already
net = self._allowed_networks[ssid]
async_cb(tuple(net.get_security()))
return
# Otherwise, ask the user for it
net = None
dev = self._nmclient.get_device(dev_op)
if not dev:
async_err_cb(NotFoundError("Device was unknown."))
return
if dev.get_type() == nmclient.DEVICE_TYPE_802_3_ETHERNET:
# We don't support wired 802.1x yet...
async_err_cb(UnsupportedError("Device type is unsupported by NMI."))
return
net = dev.get_network(net_op)
if not net:
async_err_cb(NotFoundError("Network was unknown."))
return
self._nmclient.get_key_for_network(net, async_cb, async_err_cb)
def get_key_for_network_cb(self, net, key, auth_alg, async_cb, async_err_cb, canceled=False):
"""
Called by the NMClient when the Wireless Network Key dialog
is closed.
"""
if canceled:
e = CanceledKeyRequestError("Request was canceled.")
# key dialog dialog was canceled; send the error back to NM
async_err_cb(e)
return
if not key or not auth_alg:
# no key returned, *** BUG ***; the key dialog
# should always return either a key + auth_alg, or a
#cancel error
raise RuntimeError("No key or auth alg given! Bug!")
we_cipher = None
if len(key) == 26:
we_cipher = IW_AUTH_CIPHER_WEP104
elif len(key) == 10:
we_cipher = IW_AUTH_CIPHER_WEP40
else:
raise RuntimeError("Invalid key length!")
# Stuff the returned key and auth algorithm into a security object
# and return it to NetworkManager
sec = Security.new_from_args(we_cipher, (key, auth_alg))
if not sec:
raise RuntimeError("Invalid security arguments.")
props = sec.get_properties()
a = tuple(props)
async_cb(*a)
def cancel_get_key_for_network(self):
# Tell the NMClient to close the key request dialog
self._nmclient.cancel_get_key_for_network()

View File

@ -4,4 +4,5 @@ sugar_PYTHON = \
device.py \ device.py \
devicesmodel.py \ devicesmodel.py \
battery.py \ battery.py \
network.py wirednetwork.py \
wirelessnetwork.py

View File

@ -5,7 +5,7 @@ class Device(device.Device):
device.Device.__init__(self) device.Device.__init__(self)
def get_type(self): def get_type(self):
return 'network' return 'battery'
def get_level(self): def get_level(self):
return 0 return 0

View File

@ -1,8 +1,10 @@
import gobject import gobject
from model.devices import device from model.devices import device
from model.devices import network from model.devices import wirednetwork
from model.devices import wirelessnetwork
from model.devices import battery from model.devices import battery
from hardware import hardwaremanager
class DevicesModel(gobject.GObject): class DevicesModel(gobject.GObject):
__gsignals__ = { __gsignals__ = {
@ -18,12 +20,26 @@ class DevicesModel(gobject.GObject):
gobject.GObject.__init__(self) gobject.GObject.__init__(self)
self._devices = [] self._devices = []
self.add_device(network.Device())
self.add_device(battery.Device()) self.add_device(battery.Device())
self._observe_network_manager()
def _observe_network_manager(self):
network_manager = hardwaremanager.get_network_manager()
for device in network_manager.get_devices():
self._check_network_device(device)
def _check_network_device(self, device):
if not device.is_valid():
return
if device.get_type() == DEVICE_TYPE_802_11_WIRELESS:
if device.get_active():
self._add_device(device)
def __iter__(self): def __iter__(self):
return iter(self._devices) return iter(self._devices)
def add_device(self, device): def add_device(self, device):
self._devices.append(device) self._devices.append(device)
self.emit('device-appeared', device)

View File

@ -1,11 +1,9 @@
from model.devices import device from model.devices import device
class Device(device.Device): class Device(device.Device):
def __init__(self): def __init__(self, nm_device):
device.Device.__init__(self) device.Device.__init__(self)
self._nm_device = device
def get_type(self): def get_type(self):
return 'network' return 'wirednetwork'
def get_level(self):
return 0

View File

@ -0,0 +1,12 @@
from model.devices import device
class Device(device.Device):
def __init__(self, nm_device):
device.Device.__init__(self)
self._nm_device = device
def get_type(self):
return 'wirelessnetwork'
def get_level(self):
return self._nm_device.get_strength()

View File

@ -3,4 +3,5 @@ sugar_PYTHON = \
__init__.py \ __init__.py \
battery.py \ battery.py \
deviceview.py \ deviceview.py \
network.py wirednetwork.py \
wirelessnetwork.py

View File

@ -1,6 +1,6 @@
from view.devices import deviceview from view.devices import deviceview
class DeviceView(deviceview.DeviceView) class DeviceView(deviceview.DeviceView):
def __init__(self, model): def __init__(self, model):
deviceview.DeviceView.__init__(self, model) deviceview.DeviceView.__init__(self, model)
self.props.icon_name = 'theme:stock-close' self.props.icon_name = 'theme:stock-close'

View File

@ -3,4 +3,4 @@ from view.devices import deviceview
class DeviceView(deviceview.DeviceView): class DeviceView(deviceview.DeviceView):
def __init__(self, model): def __init__(self, model):
deviceview.DeviceView.__init__(self, model) deviceview.DeviceView.__init__(self, model)
self.props.icon_name = 'theme:stock-close' self.props.icon_name = 'theme:stock-net-wired'

View File

@ -0,0 +1,6 @@
from view.devices import deviceview
class DeviceView(deviceview.DeviceView):
def __init__(self, model):
deviceview.DeviceView.__init__(self, model)
self.props.icon_name = 'theme:stock-net-wireless-00'