diff options
-rw-r--r-- | data/sugar.schemas.in | 24 | ||||
-rwxr-xr-x | extensions/cpsection/modemconfiguration/model.py | 107 | ||||
-rw-r--r-- | extensions/cpsection/modemconfiguration/view.py | 206 | ||||
-rw-r--r-- | extensions/cpsection/network/model.py | 16 | ||||
-rw-r--r-- | extensions/deviceicon/network.py | 178 | ||||
-rw-r--r-- | src/jarabe/desktop/keydialog.py | 32 | ||||
-rw-r--r-- | src/jarabe/desktop/meshbox.py | 63 | ||||
-rw-r--r-- | src/jarabe/desktop/networkviews.py | 167 | ||||
-rw-r--r-- | src/jarabe/model/adhoc.py | 115 | ||||
-rw-r--r-- | src/jarabe/model/network.py | 763 | ||||
-rw-r--r-- | src/jarabe/model/olpcmesh.py | 158 |
11 files changed, 859 insertions, 970 deletions
diff --git a/data/sugar.schemas.in b/data/sugar.schemas.in index 8b3e1ad..aaef381 100644 --- a/data/sugar.schemas.in +++ b/data/sugar.schemas.in @@ -280,8 +280,8 @@ <type>string</type> <default></default> <locale name="C"> - <short>GSM network username</short> - <long>GSM network username configuration</long> + <short>GSM network username (DEPRECATED/UNUSED)</short> + <long>GSM network username configuration (DEPRECATED/UNUSED)</long> </locale> </schema> <schema> @@ -291,8 +291,8 @@ <type>string</type> <default></default> <locale name="C"> - <short>GSM network password</short> - <long>GSM network password configuration</long> + <short>GSM network password (DEPRECATED/UNUSED)</short> + <long>GSM network password configuration (DEPRECATED/UNUSED)</long> </locale> </schema> <schema> @@ -302,8 +302,8 @@ <type>string</type> <default>*99#</default> <locale name="C"> - <short>GSM network number</short> - <long>GSM network telephone number configuration</long> + <short>GSM network number (DEPRECATED/UNUSED)</short> + <long>GSM network telephone number configuration (DEPRECATED/UNUSED)</long> </locale> </schema> <schema> @@ -313,8 +313,8 @@ <type>string</type> <default></default> <locale name="C"> - <short>GSM network APN</short> - <long>GSM network access point name configuration</long> + <short>GSM network APN (DEPRECATED/UNUSED)</short> + <long>GSM network access point name configuration (DEPRECATED/UNUSED)</long> </locale> </schema> <schema> @@ -324,8 +324,8 @@ <type>string</type> <default></default> <locale name="C"> - <short>GSM network PIN</short> - <long>GSM network personal identification number configuration</long> + <short>GSM network PIN (DEPRECATED/UNUSED)</short> + <long>GSM network personal identification number configuration (DEPRECATED/UNUSED)</long> </locale> </schema> <schema> @@ -335,8 +335,8 @@ <type>string</type> <default></default> <locale name="C"> - <short>GSM network PUK</short> - <long>GSM network personal unlock key configuration</long> + <short>GSM network PUK (DEPRECATED/UNUSED)</short> + <long>GSM network personal unlock key configuration (DEPRECATED/UNUSED)</long> </locale> </schema> diff --git a/extensions/cpsection/modemconfiguration/model.py b/extensions/cpsection/modemconfiguration/model.py index 1e83c44..969b5d9 100755 --- a/extensions/cpsection/modemconfiguration/model.py +++ b/extensions/cpsection/modemconfiguration/model.py @@ -14,68 +14,87 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 US -import gconf +import logging -from jarabe.model.network import GSM_USERNAME_PATH, GSM_PASSWORD_PATH, \ - GSM_NUMBER_PATH, GSM_APN_PATH, GSM_PIN_PATH, \ - GSM_PUK_PATH +import dbus +import gtk +from jarabe.model import network -def get_username(): - client = gconf.client_get_default() - return client.get_string(GSM_USERNAME_PATH) or '' +def get_connection(): + return network.find_gsm_connection() -def get_password(): - client = gconf.client_get_default() - return client.get_string(GSM_PASSWORD_PATH) or '' +def get_modem_settings(): + modem_settings = {} + connection = get_connection() + if not connection: + return modem_settings -def get_number(): - client = gconf.client_get_default() - return client.get_string(GSM_NUMBER_PATH) or '' + settings = connection.get_settings('gsm') + for setting in ('username', 'number', 'apn'): + modem_settings[setting] = settings.get(setting, '') + # use mutable container for nested function control variable + secrets_call_done = [False] -def get_apn(): - client = gconf.client_get_default() - return client.get_string(GSM_APN_PATH) or '' + def _secrets_cb(secrets): + secrets_call_done[0] = True + if not secrets or not 'gsm' in secrets: + return + gsm_secrets = secrets['gsm'] + modem_settings['password'] = gsm_secrets.get('password', '') + modem_settings['pin'] = gsm_secrets.get('pin', '') -def get_pin(): - client = gconf.client_get_default() - return client.get_string(GSM_PIN_PATH) or '' + def _secrets_err_cb(err): + secrets_call_done[0] = True + if isinstance(err, dbus.exceptions.DBusException) and \ + err.get_dbus_name() == network.NM_AGENT_MANAGER_ERR_NO_SECRETS: + logging.debug('No GSM secrets present') + else: + logging.error('Error retrieving GSM secrets: %s', err) + # must be called asynchronously as this re-enters the GTK main loop + connection.get_secrets('gsm', _secrets_cb, _secrets_err_cb) -def get_puk(): - client = gconf.client_get_default() - return client.get_string(GSM_PUK_PATH) or '' + # wait til asynchronous execution completes + while not secrets_call_done[0]: + gtk.main_iteration() + return modem_settings -def set_username(username): - client = gconf.client_get_default() - client.set_string(GSM_USERNAME_PATH, username) +def _set_or_clear(_dict, key, value): + """Update a dictionary value for a specific key. If value is None or + zero-length, but the key is present in the dictionary, delete that + dictionary entry.""" + if value: + _dict[key] = value + return -def set_password(password): - client = gconf.client_get_default() - client.set_string(GSM_PASSWORD_PATH, password) + if key in _dict: + del _dict[key] -def set_number(number): - client = gconf.client_get_default() - client.set_string(GSM_NUMBER_PATH, number) +def set_modem_settings(modem_settings): + username = modem_settings.get('username', '') + password = modem_settings.get('password', '') + number = modem_settings.get('number', '') + apn = modem_settings.get('apn', '') + pin = modem_settings.get('pin', '') + connection = get_connection() + if not connection: + network.create_gsm_connection(username, password, number, apn, pin) + return -def set_apn(apn): - client = gconf.client_get_default() - client.set_string(GSM_APN_PATH, apn) - - -def set_pin(pin): - client = gconf.client_get_default() - client.set_string(GSM_PIN_PATH, pin) - - -def set_puk(puk): - client = gconf.client_get_default() - client.set_string(GSM_PUK_PATH, puk) + settings = connection.get_settings() + gsm_settings = settings['gsm'] + _set_or_clear(gsm_settings, 'username', username) + _set_or_clear(gsm_settings, 'password', password) + _set_or_clear(gsm_settings, 'number', number) + _set_or_clear(gsm_settings, 'apn', apn) + _set_or_clear(gsm_settings, 'pin', pin) + connection.update_settings(settings) diff --git a/extensions/cpsection/modemconfiguration/view.py b/extensions/cpsection/modemconfiguration/view.py index c31edba..4ce6c0d 100644 --- a/extensions/cpsection/modemconfiguration/view.py +++ b/extensions/cpsection/modemconfiguration/view.py @@ -14,9 +14,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 US -import os -import logging from gettext import gettext as _ +import logging import gtk import gobject @@ -35,10 +34,6 @@ class EntryWithLabel(gtk.HBox): def __init__(self, label_text): gtk.HBox.__init__(self, spacing=style.DEFAULT_SPACING) - self._timeout_sid = 0 - self._changed_handler = None - self._is_valid = True - self.label = gtk.Label(label_text) self.label.modify_fg(gtk.STATE_NORMAL, style.COLOR_SELECTION_GREY.get_gdk_color()) @@ -47,118 +42,14 @@ class EntryWithLabel(gtk.HBox): self.label.show() self._entry = gtk.Entry(25) - self._entry.connect('changed', self.__entry_changed_cb) self._entry.set_width_chars(25) self.pack_start(self._entry, expand=False) self._entry.show() - def __entry_changed_cb(self, widget, data=None): - if self._timeout_sid: - gobject.source_remove(self._timeout_sid) - self._timeout_sid = gobject.timeout_add(APPLY_TIMEOUT, - self.__timeout_cb) - - def __timeout_cb(self): - self._timeout_sid = 0 - - if self._entry.get_text() == self.get_value(): - return False - - try: - self.set_value(self._entry.get_text()) - except ValueError: - self._is_valid = False - else: - self._is_valid = True - - self.notify('is-valid') - - return False - - def set_text_from_model(self): - self._entry.set_text(self.get_value()) - - def get_value(self): - raise NotImplementedError - - def set_value(self): - raise NotImplementedError - - def _get_is_valid(self): - return self._is_valid - is_valid = gobject.property(type=bool, getter=_get_is_valid, default=True) - - -class UsernameEntry(EntryWithLabel): - def __init__(self, model): - EntryWithLabel.__init__(self, _('Username:')) - self._model = model - - def get_value(self): - return self._model.get_username() - - def set_value(self, username): - self._model.set_username(username) - - -class PasswordEntry(EntryWithLabel): - def __init__(self, model): - EntryWithLabel.__init__(self, _('Password:')) - self._model = model - - def get_value(self): - return self._model.get_password() - - def set_value(self, password): - self._model.set_password(password) - - -class NumberEntry(EntryWithLabel): - def __init__(self, model): - EntryWithLabel.__init__(self, _('Number:')) - self._model = model - - def get_value(self): - return self._model.get_number() - - def set_value(self, number): - self._model.set_number(number) - - -class ApnEntry(EntryWithLabel): - def __init__(self, model): - EntryWithLabel.__init__(self, _('Access Point Name (APN):')) - self._model = model - - def get_value(self): - return self._model.get_apn() - - def set_value(self, apn): - self._model.set_apn(apn) - - -class PinEntry(EntryWithLabel): - def __init__(self, model): - EntryWithLabel.__init__(self, _('Personal Identity Number (PIN):')) - self._model = model - - def get_value(self): - return self._model.get_pin() - - def set_value(self, pin): - self._model.set_pin(pin) - - -class PukEntry(EntryWithLabel): - def __init__(self, model): - EntryWithLabel.__init__(self, _('Personal Unblocking Key (PUK):')) - self._model = model + def get_entry(self): + return self._entry - def get_value(self): - return self._model.get_puk() - - def set_value(self, puk): - self._model.set_puk(puk) + entry = gobject.property(type=object, getter=get_entry) class ModemConfiguration(SectionView): @@ -167,6 +58,7 @@ class ModemConfiguration(SectionView): self._model = model self.restart_alerts = alerts + self._timeout_sid = 0 self.set_border_width(style.DEFAULT_SPACING) self.set_spacing(style.DEFAULT_SPACING) @@ -182,75 +74,71 @@ class ModemConfiguration(SectionView): self.pack_start(self._text, False) self._text.show() - self._username_entry = UsernameEntry(model) - self._username_entry.connect('notify::is-valid', - self.__notify_is_valid_cb) + self._username_entry = EntryWithLabel(_('Username:')) + self._username_entry.entry.connect('changed', self.__entry_changed_cb) self._group.add_widget(self._username_entry.label) self.pack_start(self._username_entry, expand=False) self._username_entry.show() - self._password_entry = PasswordEntry(model) - self._password_entry.connect('notify::is-valid', - self.__notify_is_valid_cb) + self._password_entry = EntryWithLabel(_('Password:')) + self._password_entry.entry.connect('changed', self.__entry_changed_cb) self._group.add_widget(self._password_entry.label) self.pack_start(self._password_entry, expand=False) self._password_entry.show() - self._number_entry = NumberEntry(model) - self._number_entry.connect('notify::is-valid', - self.__notify_is_valid_cb) + self._number_entry = EntryWithLabel(_('Number:')) + self._number_entry.entry.connect('changed', self.__entry_changed_cb) self._group.add_widget(self._number_entry.label) self.pack_start(self._number_entry, expand=False) self._number_entry.show() - self._apn_entry = ApnEntry(model) - self._apn_entry.connect('notify::is-valid', - self.__notify_is_valid_cb) + self._apn_entry = EntryWithLabel(_('Access Point Name (APN):')) + self._apn_entry.entry.connect('changed', self.__entry_changed_cb) self._group.add_widget(self._apn_entry.label) self.pack_start(self._apn_entry, expand=False) self._apn_entry.show() - self._pin_entry = PinEntry(model) - self._pin_entry.connect('notify::is-valid', - self.__notify_is_valid_cb) + self._pin_entry = EntryWithLabel(_('Personal Identity Number (PIN):')) + self._pin_entry.entry.connect('changed', self.__entry_changed_cb) self._group.add_widget(self._pin_entry.label) self.pack_start(self._pin_entry, expand=False) self._pin_entry.show() - self._puk_entry = PukEntry(model) - self._puk_entry.connect('notify::is-valid', - self.__notify_is_valid_cb) - self._group.add_widget(self._puk_entry.label) - self.pack_start(self._puk_entry, expand=False) - self._puk_entry.show() - self.setup() - def setup(self): - self._username_entry.set_text_from_model() - self._password_entry.set_text_from_model() - self._number_entry.set_text_from_model() - self._apn_entry.set_text_from_model() - self._pin_entry.set_text_from_model() - self._puk_entry.set_text_from_model() - - self.needs_restart = False - def undo(self): self._model.undo() - def _validate(self): - if self._username_entry.is_valid and \ - self._password_entry.is_valid and \ - self._number_entry.is_valid and \ - self._apn_entry.is_valid and \ - self._pin_entry.is_valid and \ - self._puk_entry.is_valid: - self.props.is_valid = True - else: - self.props.is_valid = False + def _populate_entry(self, entrywithlabel, text): + """Populate an entry with text, without triggering its 'changed' + handler.""" + entry = entrywithlabel.entry + entry.handler_block_by_func(self.__entry_changed_cb) + entry.set_text(text) + entry.handler_unblock_by_func(self.__entry_changed_cb) + + def setup(self): + settings = self._model.get_modem_settings() + self._populate_entry(self._username_entry, + settings.get('username', '')) + self._populate_entry(self._number_entry, settings.get('number', '')) + self._populate_entry(self._apn_entry, settings.get('apn', '')) + self._populate_entry(self._password_entry, + settings.get('password', '')) + self._populate_entry(self._pin_entry, settings.get('pin', '')) + + def __entry_changed_cb(self, widget, data=None): + if self._timeout_sid: + gobject.source_remove(self._timeout_sid) + self._timeout_sid = gobject.timeout_add(APPLY_TIMEOUT, + self.__timeout_cb) - def __notify_is_valid_cb(self, entry, pspec): - if entry.is_valid: - self.needs_restart = True - self._validate() + def __timeout_cb(self): + self._timeout_sid = 0 + settings = {} + settings['username'] = self._username_entry.entry.get_text() + settings['password'] = self._password_entry.entry.get_text() + settings['number'] = self._number_entry.entry.get_text() + settings['apn'] = self._apn_entry.entry.get_text() + settings['pin'] = self._pin_entry.entry.get_text() + self._model.set_modem_settings(settings) diff --git a/extensions/cpsection/network/model.py b/extensions/cpsection/network/model.py index 916ce8c..4ddab35 100644 --- a/extensions/cpsection/network/model.py +++ b/extensions/cpsection/network/model.py @@ -15,6 +15,8 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # +import logging + import dbus from gettext import gettext as _ import gconf @@ -112,11 +114,21 @@ def clear_registration(): def clear_networks(): """Clear saved passwords and network configurations. """ - network.clear_wifi_connections() + try: + connections = network.get_connections() + except dbus.DBusException: + logging.debug('NetworkManager not available') + return + connections.clear() def have_networks(): - return network.have_wifi_connections() + try: + connections = network.get_connections() + return len(connections.get_list()) > 0 + except dbus.DBusException: + logging.debug('NetworkManager not available') + return False def get_publish_information(): diff --git a/extensions/deviceicon/network.py b/extensions/deviceicon/network.py index 789ea13..213fa41 100644 --- a/extensions/deviceicon/network.py +++ b/extensions/deviceicon/network.py @@ -48,17 +48,6 @@ from jarabe.view.pulsingicon import PulsingIcon IP_ADDRESS_TEXT_TEMPLATE = _('IP address: %s') -_NM_SERVICE = 'org.freedesktop.NetworkManager' -_NM_IFACE = 'org.freedesktop.NetworkManager' -_NM_PATH = '/org/freedesktop/NetworkManager' -_NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device' -_NM_WIRED_IFACE = 'org.freedesktop.NetworkManager.Device.Wired' -_NM_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless' -_NM_SERIAL_IFACE = 'org.freedesktop.NetworkManager.Device.Serial' -_NM_OLPC_MESH_IFACE = 'org.freedesktop.NetworkManager.Device.OlpcMesh' -_NM_ACCESSPOINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint' -_NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active' - _GSM_STATE_NOT_READY = 0 _GSM_STATE_DISCONNECTED = 1 _GSM_STATE_CONNECTING = 2 @@ -413,24 +402,24 @@ class WirelessDeviceView(ToolButton): self._device_props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) - self._device_props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True, + self._device_props.GetAll(network.NM_DEVICE_IFACE, byte_arrays=True, reply_handler=self.__get_device_props_reply_cb, error_handler=self.__get_device_props_error_cb) - self._device_props.Get(_NM_WIRELESS_IFACE, 'ActiveAccessPoint', + self._device_props.Get(network.NM_WIRELESS_IFACE, 'ActiveAccessPoint', reply_handler=self.__get_active_ap_reply_cb, error_handler=self.__get_active_ap_error_cb) self._bus.add_signal_receiver(self.__state_changed_cb, signal_name='StateChanged', path=self._device.object_path, - dbus_interface=_NM_DEVICE_IFACE) + dbus_interface=network.NM_DEVICE_IFACE) def disconnect(self): self._bus.remove_signal_receiver(self.__state_changed_cb, signal_name='StateChanged', path=self._device.object_path, - dbus_interface=_NM_DEVICE_IFACE) + dbus_interface=network.NM_DEVICE_IFACE) def __get_device_props_reply_cb(self, properties): if 'State' in properties: @@ -447,22 +436,22 @@ class WirelessDeviceView(ToolButton): self.__ap_properties_changed_cb, signal_name='PropertiesChanged', path=self._active_ap_op, - dbus_interface=_NM_ACCESSPOINT_IFACE) + dbus_interface=network.NM_ACCESSPOINT_IFACE) if active_ap_op == '/': self._active_ap_op = None return self._active_ap_op = active_ap_op - active_ap = self._bus.get_object(_NM_SERVICE, active_ap_op) + active_ap = self._bus.get_object(network.NM_SERVICE, active_ap_op) props = dbus.Interface(active_ap, dbus.PROPERTIES_IFACE) - props.GetAll(_NM_ACCESSPOINT_IFACE, byte_arrays=True, + props.GetAll(network.NM_ACCESSPOINT_IFACE, byte_arrays=True, reply_handler=self.__get_all_ap_props_reply_cb, error_handler=self.__get_all_ap_props_error_cb) self._bus.add_signal_receiver(self.__ap_properties_changed_cb, signal_name='PropertiesChanged', path=self._active_ap_op, - dbus_interface=_NM_ACCESSPOINT_IFACE) + dbus_interface=network.NM_ACCESSPOINT_IFACE) def __get_active_ap_error_cb(self, err): logging.error('Error getting the active access point: %s', err) @@ -470,7 +459,7 @@ class WirelessDeviceView(ToolButton): def __state_changed_cb(self, new_state, old_state, reason): self._device_state = new_state self._update_state() - self._device_props.Get(_NM_WIRELESS_IFACE, 'ActiveAccessPoint', + self._device_props.Get(network.NM_WIRELESS_IFACE, 'ActiveAccessPoint', reply_handler=self.__get_active_ap_reply_cb, error_handler=self.__get_active_ap_error_cb) @@ -528,11 +517,11 @@ class WirelessDeviceView(ToolButton): if self._active_ap_op is not None: state = self._device_state else: - state = network.DEVICE_STATE_UNKNOWN + state = network.NM_DEVICE_STATE_UNKNOWN if self._mode != network.NM_802_11_MODE_ADHOC and \ network.is_sugar_adhoc_network(self._name) == False: - if state == network.DEVICE_STATE_ACTIVATED: + if state == network.NM_DEVICE_STATE_ACTIVATED: icon_name = '%s-connected' % 'network-wireless' else: icon_name = 'network-wireless' @@ -542,21 +531,19 @@ class WirelessDeviceView(ToolButton): self._icon.props.icon_name = icon_name else: channel = network.frequency_to_channel(self._frequency) - if state == network.DEVICE_STATE_ACTIVATED: + if state == network.NM_DEVICE_STATE_ACTIVATED: self._icon.props.icon_name = 'network-adhoc-%s-connected' \ % channel else: self._icon.props.icon_name = 'network-adhoc-%s' % channel self._icon.props.base_color = profile.get_color() - if state == network.DEVICE_STATE_PREPARE or \ - state == network.DEVICE_STATE_CONFIG or \ - state == network.DEVICE_STATE_NEED_AUTH or \ - state == network.DEVICE_STATE_IP_CONFIG: + if (state >= network.NM_DEVICE_STATE_PREPARE) and \ + (state <= network.NM_DEVICE_STATE_IP_CONFIG): self._palette.set_connecting() self._icon.props.pulsing = True - elif state == network.DEVICE_STATE_ACTIVATED: - address = self._device_props.Get(_NM_DEVICE_IFACE, 'Ip4Address') + elif state == network.NM_DEVICE_STATE_ACTIVATED: + address = self._device_props.Get(network.NM_DEVICE_IFACE, 'Ip4Address') self._palette.set_connected_with_frequency(self._frequency, address) self._icon.props.pulsing = False @@ -571,11 +558,6 @@ class WirelessDeviceView(ToolButton): self._icon.props.base_color = self._color def __deactivate_connection_cb(self, palette, data=None): - if self._mode == network.NM_802_11_MODE_INFRA: - connection = network.find_connection_by_ssid(self._name) - if connection: - connection.disable_autoconnect() - network.disconnect_access_points([self._active_ap_op]) def __activate_reply_cb(self, connection): @@ -620,20 +602,20 @@ class OlpcMeshDeviceView(ToolButton): self._device_props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) - self._device_props.Get(_NM_OLPC_MESH_IFACE, 'ActiveChannel', + self._device_props.Get(network.NM_OLPC_MESH_IFACE, 'ActiveChannel', reply_handler=self.__get_active_channel_reply_cb, error_handler=self.__get_active_channel_error_cb) self._bus.add_signal_receiver(self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=device.object_path, - dbus_interface=_NM_OLPC_MESH_IFACE) + dbus_interface=network.NM_OLPC_MESH_IFACE) def disconnect(self): self._bus.remove_signal_receiver(self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=self._device.object_path, - dbus_interface=_NM_OLPC_MESH_IFACE) + dbus_interface=network.NM_OLPC_MESH_IFACE) def __get_active_channel_reply_cb(self, channel): self._channel = channel @@ -659,16 +641,14 @@ class OlpcMeshDeviceView(ToolButton): def _update(self): state = self._device_state - if state in [network.DEVICE_STATE_PREPARE, - network.DEVICE_STATE_CONFIG, - network.DEVICE_STATE_NEED_AUTH, - network.DEVICE_STATE_IP_CONFIG]: + if (state >= network.NM_DEVICE_STATE_PREPARE) and \ + (state <= network.NM_DEVICE_STATE_IP_CONFIG): self._icon.props.base_color = self._inactive_color self._icon.props.pulse_color = profile.get_color() self._palette.set_connecting() self._icon.props.pulsing = True - elif state == network.DEVICE_STATE_ACTIVATED: - address = self._device_props.Get(_NM_DEVICE_IFACE, 'Ip4Address') + elif state == network.NM_DEVICE_STATE_ACTIVATED: + address = self._device_props.Get(network.NM_DEVICE_IFACE, 'Ip4Address') self._palette.set_connected_with_channel(self._channel, address) self._icon.props.base_color = profile.get_color() self._icon.props.pulsing = False @@ -679,23 +659,23 @@ class OlpcMeshDeviceView(ToolButton): self._update() def __deactivate_connection(self, palette, data=None): - obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) - netmgr = dbus.Interface(obj, _NM_IFACE) + obj = self._bus.get_object(network.NM_SERVICE, network.NM_PATH) + netmgr = dbus.Interface(obj, network.NM_IFACE) netmgr_props = dbus.Interface(netmgr, dbus.PROPERTIES_IFACE) - active_connections_o = netmgr_props.Get(_NM_IFACE, + active_connections_o = netmgr_props.Get(network.NM_IFACE, 'ActiveConnections') for conn_o in active_connections_o: # The connection path for a mesh connection is the device itself. - obj = self._bus.get_object(_NM_IFACE, conn_o) + obj = self._bus.get_object(network.NM_IFACE, conn_o) props = dbus.Interface(obj, dbus.PROPERTIES_IFACE) - ap_op = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject') + ap_op = props.Get(network.NM_ACTIVE_CONN_IFACE, 'SpecificObject') try: - obj = self._bus.get_object(_NM_IFACE, ap_op) + obj = self._bus.get_object(network.NM_IFACE, ap_op) props = dbus.Interface(obj, dbus.PROPERTIES_IFACE) - device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType') - if device_type == network.DEVICE_TYPE_802_11_OLPC_MESH: + device_type = props.Get(network.NM_DEVICE_IFACE, 'DeviceType') + if device_type == network.NM_DEVICE_TYPE_OLPC_MESH: netmgr.DeactivateConnection(conn_o) break except dbus.exceptions.DBusException: @@ -742,11 +722,11 @@ class GsmDeviceView(TrayIcon): self._bus.add_signal_receiver(self.__state_changed_cb, signal_name='StateChanged', path=self._device.object_path, - dbus_interface=_NM_DEVICE_IFACE) + dbus_interface=network.NM_DEVICE_IFACE) self._bus.add_signal_receiver(self.__ppp_stats_changed_cb, signal_name='PppStats', path=self._device.object_path, - dbus_interface=_NM_SERIAL_IFACE) + dbus_interface=network.NM_MODEM_IFACE) def create_palette(self): palette = GsmPalette() @@ -758,7 +738,7 @@ class GsmDeviceView(TrayIcon): self._palette = palette props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) - props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True, + props.GetAll(network.NM_DEVICE_IFACE, byte_arrays=True, reply_handler=self.__current_state_check_cb, error_handler=self.__current_state_check_error_cb) @@ -767,14 +747,9 @@ class GsmDeviceView(TrayIcon): def __gsm_connect_cb(self, palette, data=None): connection = network.find_gsm_connection() if connection is not None: - obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) - netmgr = dbus.Interface(obj, _NM_IFACE) - netmgr.ActivateConnection(network.SETTINGS_SERVICE, - connection.path, - self._device.object_path, - '/', - reply_handler=self.__connect_cb, - error_handler=self.__connect_error_cb) + connection.activate(self._device.object_path, + reply_handler=self.__connect_cb, + error_handler=self.__connect_error_cb) else: self._palette.add_alert(_('No GSM connection available.'), \ _('Create a connection in the ' \ @@ -788,15 +763,15 @@ class GsmDeviceView(TrayIcon): raise RuntimeError('Error when connecting to gsm device, %s' % error) def __gsm_disconnect_cb(self, palette, data=None): - obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) - netmgr = dbus.Interface(obj, _NM_IFACE) + obj = self._bus.get_object(network.NM_SERVICE, network.NM_PATH) + netmgr = dbus.Interface(obj, network.NM_IFACE) netmgr_props = dbus.Interface(netmgr, dbus.PROPERTIES_IFACE) - active_connections_o = netmgr_props.Get(_NM_IFACE, 'ActiveConnections') + active_connections_o = netmgr_props.Get(network.NM_IFACE, 'ActiveConnections') for conn_o in active_connections_o: - obj = self._bus.get_object(_NM_IFACE, conn_o) + obj = self._bus.get_object(network.NM_IFACE, conn_o) props = dbus.Interface(obj, dbus.PROPERTIES_IFACE) - devices = props.Get(_NM_ACTIVE_CONN_IFACE, 'Devices') + devices = props.Get(network.NM_ACTIVE_CONN_IFACE, 'Devices') if self._device.object_path in devices: netmgr.DeactivateConnection( conn_o, @@ -824,13 +799,12 @@ class GsmDeviceView(TrayIcon): def _update_state(self, state, old_state, reason): gsm_state = None - if state is network.DEVICE_STATE_ACTIVATED: + if state is network.NM_DEVICE_STATE_ACTIVATED: gsm_state = _GSM_STATE_CONNECTED connection = network.find_gsm_connection() if connection is not None: - connection.set_connected() self._connection_timestamp = time.time() - \ - connection.get_settings().connection.timestamp + connection.get_settings('connection')['timestamp'] self._connection_time_handler = gobject.timeout_add_seconds( \ 1, self.__connection_timecount_cb) self._palette.update_connection_time() @@ -838,7 +812,7 @@ class GsmDeviceView(TrayIcon): if self._palette is not None: self._palette.connection_info_box.show() - elif state is network.DEVICE_STATE_DISCONNECTED: + elif state is network.NM_DEVICE_STATE_DISCONNECTED: gsm_state = _GSM_STATE_DISCONNECTED self._connection_timestamp = 0 if self._connection_time_handler is not None: @@ -846,18 +820,16 @@ class GsmDeviceView(TrayIcon): if self._palette is not None: self._palette.connection_info_box.hide() - elif state in [network.DEVICE_STATE_UNMANAGED, - network.DEVICE_STATE_UNAVAILABLE, - network.DEVICE_STATE_UNKNOWN]: + elif state in [network.NM_DEVICE_STATE_UNMANAGED, + network.NM_DEVICE_STATE_UNAVAILABLE, + network.NM_DEVICE_STATE_UNKNOWN]: gsm_state = _GSM_STATE_NOT_READY - elif state in [network.DEVICE_STATE_PREPARE, - network.DEVICE_STATE_CONFIG, - network.DEVICE_STATE_IP_CONFIG, - network.DEVICE_STATE_NEED_AUTH]: + elif (state >= network.NM_DEVICE_STATE_PREPARE) and \ + (state <= network.NM_DEVICE_STATE_IP_CONFIG): gsm_state = _GSM_STATE_CONNECTING - elif state == network.DEVICE_STATE_FAILED: + elif state == network.NM_DEVICE_STATE_FAILED: gsm_state = _GSM_STATE_FAILED if self._palette is not None: @@ -867,7 +839,7 @@ class GsmDeviceView(TrayIcon): self._bus.remove_signal_receiver(self.__state_changed_cb, signal_name='StateChanged', path=self._device.object_path, - dbus_interface=_NM_DEVICE_IFACE) + dbus_interface=network.NM_DEVICE_IFACE) def __ppp_stats_changed_cb(self, in_bytes, out_bytes): self._palette.update_stats(in_bytes, out_bytes) @@ -903,14 +875,14 @@ class MeshDeviceObserver(object): self._tray = tray props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) - props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True, + props.GetAll(network.NM_DEVICE_IFACE, byte_arrays=True, reply_handler=self.__get_device_props_reply_cb, error_handler=self.__get_device_props_error_cb) self._bus.add_signal_receiver(self.__state_changed_cb, signal_name='StateChanged', path=self._device.object_path, - dbus_interface=_NM_DEVICE_IFACE) + dbus_interface=network.NM_DEVICE_IFACE) def _remove_device_view(self): self._device_view.disconnect() @@ -924,7 +896,7 @@ class MeshDeviceObserver(object): self._bus.remove_signal_receiver(self.__state_changed_cb, signal_name='StateChanged', path=self._device.object_path, - dbus_interface=_NM_DEVICE_IFACE) + dbus_interface=network.NM_DEVICE_IFACE) def __get_device_props_reply_cb(self, properties): if 'State' in properties: @@ -937,10 +909,8 @@ class MeshDeviceObserver(object): self._update_state(new_state) def _update_state(self, state): - if state in (network.DEVICE_STATE_PREPARE, network.DEVICE_STATE_CONFIG, - network.DEVICE_STATE_NEED_AUTH, - network.DEVICE_STATE_IP_CONFIG, - network.DEVICE_STATE_ACTIVATED): + if (state >= network.NM_DEVICE_STATE_PREPARE) and \ + (state <= network.NM_DEVICE_STATE_ACTIVATED): if self._device_view is not None: self._device_view.update_state(state) return @@ -961,20 +931,20 @@ class WiredDeviceObserver(object): self._tray = tray props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) - props.GetAll(_NM_DEVICE_IFACE, byte_arrays=True, + props.GetAll(network.NM_DEVICE_IFACE, byte_arrays=True, reply_handler=self.__get_device_props_reply_cb, error_handler=self.__get_device_props_error_cb) self._bus.add_signal_receiver(self.__state_changed_cb, signal_name='StateChanged', path=self._device.object_path, - dbus_interface=_NM_DEVICE_IFACE) + dbus_interface=network.NM_DEVICE_IFACE) def disconnect(self): self._bus.remove_signal_receiver(self.__state_changed_cb, signal_name='StateChanged', path=self._device.object_path, - dbus_interface=_NM_DEVICE_IFACE) + dbus_interface=network.NM_DEVICE_IFACE) def __get_device_props_reply_cb(self, properties): if 'State' in properties: @@ -987,10 +957,10 @@ class WiredDeviceObserver(object): self._update_state(new_state) def _update_state(self, state): - if state == network.DEVICE_STATE_ACTIVATED: + if state == network.NM_DEVICE_STATE_ACTIVATED: props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) - address = props.Get(_NM_DEVICE_IFACE, 'Ip4Address') - speed = props.Get(_NM_WIRED_IFACE, 'Speed') + address = props.Get(network.NM_DEVICE_IFACE, 'Ip4Address') + speed = props.Get(network.NM_WIRED_IFACE, 'Speed') self._device_view = WiredDeviceView(speed, address) self._tray.add_device(self._device_view) else: @@ -1023,10 +993,10 @@ class NetworkManagerObserver(object): self._tray = tray try: - obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) - self._netmgr = dbus.Interface(obj, _NM_IFACE) + obj = self._bus.get_object(network.NM_SERVICE, network.NM_PATH) + self._netmgr = dbus.Interface(obj, network.NM_IFACE) except dbus.DBusException: - logging.error('%s service not available', _NM_SERVICE) + logging.error('%s service not available', network.NM_SERVICE) return self._netmgr.GetDevices(reply_handler=self.__get_devices_reply_cb, @@ -1034,10 +1004,10 @@ class NetworkManagerObserver(object): self._bus.add_signal_receiver(self.__device_added_cb, signal_name='DeviceAdded', - dbus_interface=_NM_IFACE) + dbus_interface=network.NM_IFACE) self._bus.add_signal_receiver(self.__device_removed_cb, signal_name='DeviceRemoved', - dbus_interface=_NM_IFACE) + dbus_interface=network.NM_IFACE) def __get_devices_reply_cb(self, devices): for device_op in devices: @@ -1047,20 +1017,20 @@ class NetworkManagerObserver(object): logging.error('Failed to get devices: %s', err) def _check_device(self, device_op): - nm_device = self._bus.get_object(_NM_SERVICE, device_op) + nm_device = self._bus.get_object(network.NM_SERVICE, device_op) props = dbus.Interface(nm_device, dbus.PROPERTIES_IFACE) - device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType') - if device_type == network.DEVICE_TYPE_802_3_ETHERNET: + device_type = props.Get(network.NM_DEVICE_IFACE, 'DeviceType') + if device_type == network.NM_DEVICE_TYPE_ETHERNET: device = WiredDeviceObserver(nm_device, self._tray) self._devices[device_op] = device - elif device_type == network.DEVICE_TYPE_802_11_WIRELESS: + elif device_type == network.NM_DEVICE_TYPE_WIFI: device = WirelessDeviceObserver(nm_device, self._tray) self._devices[device_op] = device - elif device_type == network.DEVICE_TYPE_802_11_OLPC_MESH: + elif device_type == network.NM_DEVICE_TYPE_OLPC_MESH: device = MeshDeviceObserver(nm_device, self._tray) self._devices[device_op] = device - elif device_type == network.DEVICE_TYPE_GSM_MODEM: + elif device_type == network.NM_DEVICE_TYPE_MODEM: device = GsmDeviceObserver(nm_device, self._tray) self._devices[device_op] = device diff --git a/src/jarabe/desktop/keydialog.py b/src/jarabe/desktop/keydialog.py index c72f498..17ff6bd 100644 --- a/src/jarabe/desktop/keydialog.py +++ b/src/jarabe/desktop/keydialog.py @@ -22,7 +22,6 @@ import gtk import dbus from jarabe.model import network -from jarabe.model.network import Secrets IW_AUTH_ALG_OPEN_SYSTEM = 'open' @@ -74,12 +73,10 @@ class CanceledKeyRequestError(dbus.DBusException): class KeyDialog(gtk.Dialog): - def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, settings, - response): + def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, response): gtk.Dialog.__init__(self, flags=gtk.DIALOG_MODAL) self.set_title('Wireless Key Required') - self._settings = settings self._response = response self._entry = None self._ssid = ssid @@ -121,10 +118,9 @@ class KeyDialog(gtk.Dialog): class WEPKeyDialog(KeyDialog): - def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, settings, - response): + def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, response): KeyDialog.__init__(self, ssid, flags, wpa_flags, rsn_flags, - dev_caps, settings, response) + dev_caps, response) # WEP key type self.key_store = gtk.ListStore(str, int) @@ -192,10 +188,8 @@ class WEPKeyDialog(KeyDialog): def create_security(self): (key, auth_alg) = self._get_security() - secrets = Secrets(self._settings) - secrets.wep_key = key - secrets.auth_alg = auth_alg - return secrets + wsec = {'wep-key0': key, 'auth-alg': auth_alg} + return {'802-11-wireless-security': wsec} def _update_response_sensitivity(self, ignored=None): key = self._entry.get_text() @@ -219,10 +213,9 @@ class WEPKeyDialog(KeyDialog): class WPAKeyDialog(KeyDialog): - def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, settings, - response): + def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, response): KeyDialog.__init__(self, ssid, flags, wpa_flags, rsn_flags, - dev_caps, settings, response) + dev_caps, response) self.add_key_entry() self.store = gtk.ListStore(str) @@ -272,9 +265,8 @@ class WPAKeyDialog(KeyDialog): print 'Key: %s' % key def create_security(self): - secrets = Secrets(self._settings) - secrets.psk = self._get_security() - return secrets + wsec = {'psk': self._get_security()} + return {'802-11-wireless-security': wsec} def _update_response_sensitivity(self, ignored=None): key = self._entry.get_text() @@ -291,14 +283,14 @@ class WPAKeyDialog(KeyDialog): return False -def create(ssid, flags, wpa_flags, rsn_flags, dev_caps, settings, response): +def create(ssid, flags, wpa_flags, rsn_flags, dev_caps, response): if wpa_flags == network.NM_802_11_AP_SEC_NONE and \ rsn_flags == network.NM_802_11_AP_SEC_NONE: key_dialog = WEPKeyDialog(ssid, flags, wpa_flags, rsn_flags, - dev_caps, settings, response) + dev_caps, response) else: key_dialog = WPAKeyDialog(ssid, flags, wpa_flags, rsn_flags, - dev_caps, settings, response) + dev_caps, response) key_dialog.connect('response', _key_dialog_response_cb) key_dialog.show_all() diff --git a/src/jarabe/desktop/meshbox.py b/src/jarabe/desktop/meshbox.py index 6d5bb48..2ce6163 100644 --- a/src/jarabe/desktop/meshbox.py +++ b/src/jarabe/desktop/meshbox.py @@ -48,15 +48,6 @@ from jarabe.model.adhoc import get_adhoc_manager_instance from jarabe.journal import misc -_NM_SERVICE = 'org.freedesktop.NetworkManager' -_NM_IFACE = 'org.freedesktop.NetworkManager' -_NM_PATH = '/org/freedesktop/NetworkManager' -_NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device' -_NM_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless' -_NM_OLPC_MESH_IFACE = 'org.freedesktop.NetworkManager.Device.OlpcMesh' -_NM_ACCESSPOINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint' -_NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active' - _AP_ICON_NAME = 'network-wireless' _OLPC_MESH_ICON_NAME = 'network-mesh' @@ -244,7 +235,7 @@ class DeviceObserver(gobject.GObject): self._bus = dbus.SystemBus() self.device = device - wireless = dbus.Interface(device, _NM_WIRELESS_IFACE) + wireless = dbus.Interface(device, network.NM_WIRELESS_IFACE) wireless.GetAccessPoints( reply_handler=self._get_access_points_reply_cb, error_handler=self._get_access_points_error_cb) @@ -252,22 +243,22 @@ class DeviceObserver(gobject.GObject): self._bus.add_signal_receiver(self.__access_point_added_cb, signal_name='AccessPointAdded', path=device.object_path, - dbus_interface=_NM_WIRELESS_IFACE) + dbus_interface=network.NM_WIRELESS_IFACE) self._bus.add_signal_receiver(self.__access_point_removed_cb, signal_name='AccessPointRemoved', path=device.object_path, - dbus_interface=_NM_WIRELESS_IFACE) + dbus_interface=network.NM_WIRELESS_IFACE) def _get_access_points_reply_cb(self, access_points_o): for ap_o in access_points_o: - ap = self._bus.get_object(_NM_SERVICE, ap_o) + ap = self._bus.get_object(network.NM_SERVICE, ap_o) self.emit('access-point-added', ap) def _get_access_points_error_cb(self, err): logging.error('Failed to get access points: %s', err) def __access_point_added_cb(self, access_point_o): - ap = self._bus.get_object(_NM_SERVICE, access_point_o) + ap = self._bus.get_object(network.NM_SERVICE, access_point_o) self.emit('access-point-added', ap) def __access_point_removed_cb(self, access_point_o): @@ -277,11 +268,11 @@ class DeviceObserver(gobject.GObject): self._bus.remove_signal_receiver(self.__access_point_added_cb, signal_name='AccessPointAdded', path=self.device.object_path, - dbus_interface=_NM_WIRELESS_IFACE) + dbus_interface=network.NM_WIRELESS_IFACE) self._bus.remove_signal_receiver(self.__access_point_removed_cb, signal_name='AccessPointRemoved', path=self.device.object_path, - dbus_interface=_NM_WIRELESS_IFACE) + dbus_interface=network.NM_WIRELESS_IFACE) class NetworkManagerObserver(object): @@ -301,10 +292,9 @@ class NetworkManagerObserver(object): def listen(self): try: self._bus = dbus.SystemBus() - obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) - self._netmgr = dbus.Interface(obj, _NM_IFACE) + self._netmgr = network.get_manager() except dbus.DBusException: - logging.debug('%s service not available', _NM_SERVICE) + logging.debug('NetworkManager not available') return self._netmgr.GetDevices(reply_handler=self.__get_devices_reply_cb, @@ -312,41 +302,40 @@ class NetworkManagerObserver(object): self._bus.add_signal_receiver(self.__device_added_cb, signal_name='DeviceAdded', - dbus_interface=_NM_IFACE) + dbus_interface=network.NM_IFACE) self._bus.add_signal_receiver(self.__device_removed_cb, signal_name='DeviceRemoved', - dbus_interface=_NM_IFACE) + dbus_interface=network.NM_IFACE) self._bus.add_signal_receiver(self.__properties_changed_cb, signal_name='PropertiesChanged', - dbus_interface=_NM_IFACE) + dbus_interface=network.NM_IFACE) - settings = network.get_settings() - if settings is not None: - settings.secrets_request.connect(self.__secrets_request_cb) + secret_agent = network.get_secret_agent() + if secret_agent is not None: + secret_agent.secrets_request.connect(self.__secrets_request_cb) def __secrets_request_cb(self, **kwargs): # FIXME It would be better to do all of this async, but I cannot think # of a good way to. NM could really use some love here. netmgr_props = dbus.Interface(self._netmgr, dbus.PROPERTIES_IFACE) - active_connections_o = netmgr_props.Get(_NM_IFACE, 'ActiveConnections') + active_connections_o = netmgr_props.Get(network.NM_IFACE, 'ActiveConnections') for conn_o in active_connections_o: - obj = self._bus.get_object(_NM_IFACE, conn_o) + obj = self._bus.get_object(network.NM_IFACE, conn_o) props = dbus.Interface(obj, dbus.PROPERTIES_IFACE) - state = props.Get(_NM_ACTIVE_CONN_IFACE, 'State') + state = props.Get(network.NM_ACTIVE_CONN_IFACE, 'State') if state == network.NM_ACTIVE_CONNECTION_STATE_ACTIVATING: - ap_o = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject') + ap_o = props.Get(network.NM_ACTIVE_CONN_IFACE, 'SpecificObject') found = False if ap_o != '/': for net in self._box.wireless_networks.values(): if net.find_ap(ap_o) is not None: found = True - settings = kwargs['connection'].get_settings() - net.create_keydialog(settings, kwargs['response']) + net.create_keydialog(kwargs['response']) if not found: - logging.error('Could not determine AP for specific object' - ' %s', conn_o) + raise Exception('Could not determine AP for specific object' + ' %s' % conn_o) def __get_devices_reply_cb(self, devices_o): for dev_o in devices_o: @@ -356,11 +345,11 @@ class NetworkManagerObserver(object): logging.error('Failed to get devices: %s', err) def _check_device(self, device_o): - device = self._bus.get_object(_NM_SERVICE, device_o) + device = self._bus.get_object(network.NM_SERVICE, device_o) props = dbus.Interface(device, dbus.PROPERTIES_IFACE) - device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType') - if device_type == network.DEVICE_TYPE_802_11_WIRELESS: + device_type = props.Get(network.NM_DEVICE_IFACE, 'DeviceType') + if device_type == network.NM_DEVICE_TYPE_WIFI: self._devices[device_o] = DeviceObserver(device) self._devices[device_o].connect('access-point-added', self.__ap_added_cb) @@ -368,7 +357,7 @@ class NetworkManagerObserver(object): self.__ap_removed_cb) if self._have_adhoc_networks: self._box.add_adhoc_networks(device) - elif device_type == network.DEVICE_TYPE_802_11_OLPC_MESH: + elif device_type == network.NM_DEVICE_TYPE_OLPC_MESH: self._olpc_mesh_device_o = device_o self._box.enable_olpc_mesh(device) diff --git a/src/jarabe/desktop/networkviews.py b/src/jarabe/desktop/networkviews.py index 677452d..31a366c 100644 --- a/src/jarabe/desktop/networkviews.py +++ b/src/jarabe/desktop/networkviews.py @@ -42,15 +42,6 @@ from jarabe.model.network import WirelessSecurity from jarabe.model.adhoc import get_adhoc_manager_instance -_NM_SERVICE = 'org.freedesktop.NetworkManager' -_NM_IFACE = 'org.freedesktop.NetworkManager' -_NM_PATH = '/org/freedesktop/NetworkManager' -_NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device' -_NM_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless' -_NM_OLPC_MESH_IFACE = 'org.freedesktop.NetworkManager.Device.OlpcMesh' -_NM_ACCESSPOINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint' -_NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active' - _AP_ICON_NAME = 'network-wireless' _OLPC_MESH_ICON_NAME = 'network-mesh' @@ -105,24 +96,21 @@ class WirelessNetworkView(CanvasPulsingIcon): self._update_badge() interface_props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) - interface_props.Get(_NM_DEVICE_IFACE, 'State', - reply_handler=self.__get_device_state_reply_cb, - error_handler=self.__get_device_state_error_cb) - interface_props.Get(_NM_WIRELESS_IFACE, 'WirelessCapabilities', + interface_props.Get(network.NM_WIRELESS_IFACE, 'WirelessCapabilities', reply_handler=self.__get_device_caps_reply_cb, error_handler=self.__get_device_caps_error_cb) - interface_props.Get(_NM_WIRELESS_IFACE, 'ActiveAccessPoint', + interface_props.Get(network.NM_WIRELESS_IFACE, 'ActiveAccessPoint', reply_handler=self.__get_active_ap_reply_cb, error_handler=self.__get_active_ap_error_cb) self._bus.add_signal_receiver(self.__device_state_changed_cb, signal_name='StateChanged', path=self._device.object_path, - dbus_interface=_NM_DEVICE_IFACE) + dbus_interface=network.NM_DEVICE_IFACE) self._bus.add_signal_receiver(self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=self._device.object_path, - dbus_interface=_NM_WIRELESS_IFACE) + dbus_interface=network.NM_WIRELESS_IFACE) def _create_palette(self): icon_name = get_icon_state(_AP_ICON_NAME, self._strength) @@ -168,6 +156,10 @@ class WirelessNetworkView(CanvasPulsingIcon): def __get_active_ap_reply_cb(self, ap_path): self.__update_active_ap(ap_path) + interface_props = dbus.Interface(self._device, dbus.PROPERTIES_IFACE) + interface_props.Get(network.NM_DEVICE_IFACE, 'State', + reply_handler=self.__get_device_state_reply_cb, + error_handler=self.__get_device_state_error_cb) def __get_active_ap_error_cb(self, err): logging.error('Error getting the active access point: %s', err) @@ -182,6 +174,7 @@ class WirelessNetworkView(CanvasPulsingIcon): self._device_state = state self._update_state() self._update_color() + self._update_icon() self._update_badge() def __get_device_state_error_cb(self, err): @@ -192,7 +185,7 @@ class WirelessNetworkView(CanvasPulsingIcon): network.is_sugar_adhoc_network(self._name): channel = max([1] + [ap.channel for ap in self._access_points.values()]) - if self._device_state == network.DEVICE_STATE_ACTIVATED and \ + if self._device_state == network.NM_DEVICE_STATE_ACTIVATED and \ self._active_ap is not None: icon_name = 'network-adhoc-%s-connected' % channel else: @@ -201,7 +194,7 @@ class WirelessNetworkView(CanvasPulsingIcon): icon = self._palette.props.icon icon.props.icon_name = icon_name else: - if self._device_state == network.DEVICE_STATE_ACTIVATED and \ + if self._device_state == network.NM_DEVICE_STATE_ACTIVATED and \ self._active_ap is not None: icon_name = '%s-connected' % _AP_ICON_NAME else: @@ -232,22 +225,19 @@ class WirelessNetworkView(CanvasPulsingIcon): if self._active_ap is not None: state = self._device_state else: - state = network.DEVICE_STATE_UNKNOWN + state = network.NM_DEVICE_STATE_UNKNOWN - if state == network.DEVICE_STATE_PREPARE or \ - state == network.DEVICE_STATE_CONFIG or \ - state == network.DEVICE_STATE_NEED_AUTH or \ - state == network.DEVICE_STATE_IP_CONFIG: + if state == network.NM_DEVICE_STATE_PREPARE or \ + state == network.NM_DEVICE_STATE_CONFIG or \ + state == network.NM_DEVICE_STATE_NEED_AUTH or \ + state == network.NM_DEVICE_STATE_IP_CONFIG: if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() self._palette.props.secondary_text = _('Connecting...') self.props.pulsing = True - elif state == network.DEVICE_STATE_ACTIVATED: - connection = network.find_connection_by_ssid(self._name) - if connection is not None: - if self._mode == network.NM_802_11_MODE_INFRA: - connection.set_connected() + elif state == network.NM_DEVICE_STATE_ACTIVATED: + network.set_connected() if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() @@ -269,11 +259,6 @@ class WirelessNetworkView(CanvasPulsingIcon): self.alpha = 1.0 def _disconnect_activate_cb(self, item): - if self._mode == network.NM_802_11_MODE_INFRA: - connection = network.find_connection_by_ssid(self._name) - if connection: - connection.disable_autoconnect() - ap_paths = self._access_points.keys() network.disconnect_access_points(ap_paths) @@ -317,7 +302,7 @@ class WirelessNetworkView(CanvasPulsingIcon): return None if (self._rsn_flags & network.NM_802_11_AP_SEC_KEY_MGMT_PSK) and \ - (self._device_caps & network.NM_802_11_DEVICE_CAP_RSN): + (self._device_caps & network.NM_WIFI_DEVICE_CAP_RSN): # WPA2 PSK first pairwise = self._add_ciphers_from_flags(self._rsn_flags, True) group = self._add_ciphers_from_flags(self._rsn_flags, False) @@ -329,7 +314,7 @@ class WirelessNetworkView(CanvasPulsingIcon): return wireless_security if (self._wpa_flags & network.NM_802_11_AP_SEC_KEY_MGMT_PSK) and \ - (self._device_caps & network.NM_802_11_DEVICE_CAP_WPA): + (self._device_caps & network.NM_WIFI_DEVICE_CAP_WPA): # WPA PSK pairwise = self._add_ciphers_from_flags(self._wpa_flags, True) group = self._add_ciphers_from_flags(self._wpa_flags, False) @@ -347,54 +332,47 @@ class WirelessNetworkView(CanvasPulsingIcon): self._connect() def _connect(self): + # Activate existing connection, if there is one connection = network.find_connection_by_ssid(self._name) - if connection is None: - settings = Settings() - settings.connection.id = 'Auto ' + self._name - uuid = settings.connection.uuid = unique_id() - settings.connection.type = '802-11-wireless' - settings.wireless.ssid = self._name - - if self._mode == network.NM_802_11_MODE_INFRA: - settings.wireless.mode = 'infrastructure' - elif self._mode == network.NM_802_11_MODE_ADHOC: - settings.wireless.mode = 'adhoc' - settings.wireless.band = 'bg' - settings.ip4_config = IP4Config() - settings.ip4_config.method = 'link-local' - - wireless_security = self._get_security() - settings.wireless_security = wireless_security - - if wireless_security is not None: - settings.wireless.security = '802-11-wireless-security' + if connection: + logging.debug("Activating existing connection for %s", self._name) + connection.activate(self._device) + return - connection = network.add_connection(uuid, settings) + # Otherwise, create new connection and activate it + logging.debug("Creating new connection for %s", self._name) + settings = Settings() + settings.connection.id = str(self._name) + settings.connection.uuid = unique_id() + settings.connection.type = '802-11-wireless' + settings.wireless.ssid = self._name - obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) - netmgr = dbus.Interface(obj, _NM_IFACE) + if self._mode == network.NM_802_11_MODE_INFRA: + settings.wireless.mode = 'infrastructure' + settings.connection.autoconnect = True + elif self._mode == network.NM_802_11_MODE_ADHOC: + settings.wireless.mode = 'adhoc' + settings.wireless.band = 'bg' + settings.ip4_config = IP4Config() + settings.ip4_config.method = 'link-local' - netmgr.ActivateConnection(network.SETTINGS_SERVICE, connection.path, - self._device.object_path, - '/', - reply_handler=self.__activate_reply_cb, - error_handler=self.__activate_error_cb) + wireless_security = self._get_security() + settings.wireless_security = wireless_security - def __activate_reply_cb(self, connection): - logging.debug('Connection activated: %s', connection) + if wireless_security is not None: + settings.wireless.security = '802-11-wireless-security' - def __activate_error_cb(self, err): - logging.error('Failed to activate connection: %s', err) + network.add_and_activate_connection(self._device, settings, + self.get_first_ap().model) def set_filter(self, query): self._filtered = self._name.lower().find(query) == -1 self._update_icon() self._update_color() - def create_keydialog(self, settings, response): + def create_keydialog(self, response): keydialog.create(self._name, self._flags, self._wpa_flags, - self._rsn_flags, self._device_caps, settings, - response) + self._rsn_flags, self._device_caps, response) def update_strength(self): if self._active_ap is not None: @@ -431,6 +409,9 @@ class WirelessNetworkView(CanvasPulsingIcon): return None return self._access_points[ap_path] + def get_first_ap(self): + return self._access_points.values()[0] + def is_olpc_mesh(self): return self._mode == network.NM_802_11_MODE_ADHOC \ and self.name == 'olpc-mesh' @@ -446,11 +427,11 @@ class WirelessNetworkView(CanvasPulsingIcon): self._bus.remove_signal_receiver(self.__device_state_changed_cb, signal_name='StateChanged', path=self._device.object_path, - dbus_interface=_NM_DEVICE_IFACE) + dbus_interface=network.NM_DEVICE_IFACE) self._bus.remove_signal_receiver(self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=self._device.object_path, - dbus_interface=_NM_WIRELESS_IFACE) + dbus_interface=network.NM_WIRELESS_IFACE) class SugarAdhocView(CanvasPulsingIcon): @@ -526,9 +507,9 @@ class SugarAdhocView(CanvasPulsingIcon): if self._channel == channel: state = device_state else: - state = network.DEVICE_STATE_UNKNOWN + state = network.NM_DEVICE_STATE_UNKNOWN - if state == network.DEVICE_STATE_ACTIVATED: + if state == network.NM_DEVICE_STATE_ACTIVATED: icon_name = '%s-connected' % (self._ICON_NAME + str(self._channel)) else: icon_name = self._ICON_NAME + str(self._channel) @@ -538,16 +519,14 @@ class SugarAdhocView(CanvasPulsingIcon): icon = self._palette.props.icon icon.props.icon_name = icon_name - if state in [network.DEVICE_STATE_PREPARE, - network.DEVICE_STATE_CONFIG, - network.DEVICE_STATE_NEED_AUTH, - network.DEVICE_STATE_IP_CONFIG]: + if (state >= network.NM_DEVICE_STATE_PREPARE) and \ + (state <= network.NM_DEVICE_STATE_IP_CONFIG): if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() self._palette.props.secondary_text = _('Connecting...') self.props.pulsing = True - elif state == network.DEVICE_STATE_ACTIVATED: + elif state == network.NM_DEVICE_STATE_ACTIVATED: if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() @@ -609,21 +588,21 @@ class OlpcMeshView(CanvasPulsingIcon): self.connect('button-release-event', self.__button_release_event_cb) interface_props = dbus.Interface(device, dbus.PROPERTIES_IFACE) - interface_props.Get(_NM_DEVICE_IFACE, 'State', + interface_props.Get(network.NM_DEVICE_IFACE, 'State', reply_handler=self.__get_device_state_reply_cb, error_handler=self.__get_device_state_error_cb) - interface_props.Get(_NM_OLPC_MESH_IFACE, 'ActiveChannel', + interface_props.Get(network.NM_OLPC_MESH_IFACE, 'ActiveChannel', reply_handler=self.__get_active_channel_reply_cb, error_handler=self.__get_active_channel_error_cb) self._bus.add_signal_receiver(self.__device_state_changed_cb, signal_name='StateChanged', path=device.object_path, - dbus_interface=_NM_DEVICE_IFACE) + dbus_interface=network.NM_DEVICE_IFACE) self._bus.add_signal_receiver(self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=device.object_path, - dbus_interface=_NM_OLPC_MESH_IFACE) + dbus_interface=network.NM_OLPC_MESH_IFACE) pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), style.COLOR_TRANSPARENT.get_svg())) @@ -671,18 +650,18 @@ class OlpcMeshView(CanvasPulsingIcon): if self._active: state = self._device_state else: - state = network.DEVICE_STATE_UNKNOWN + state = network.NM_DEVICE_STATE_UNKNOWN - if state in [network.DEVICE_STATE_PREPARE, - network.DEVICE_STATE_CONFIG, - network.DEVICE_STATE_NEED_AUTH, - network.DEVICE_STATE_IP_CONFIG]: + if state in [network.NM_DEVICE_STATE_PREPARE, + network.NM_DEVICE_STATE_CONFIG, + network.NM_DEVICE_STATE_NEED_AUTH, + network.NM_DEVICE_STATE_IP_CONFIG]: if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() self._palette.props.secondary_text = _('Connecting...') self.props.pulsing = True - elif state == network.DEVICE_STATE_ACTIVATED: + elif state == network.NM_DEVICE_STATE_ACTIVATED: if self._disconnect_item: self._disconnect_item.show() self._connect_item.hide() @@ -711,12 +690,6 @@ class OlpcMeshView(CanvasPulsingIcon): def _connect(self): self._mesh_mgr.user_activate_channel(self._channel) - def __activate_reply_cb(self, connection): - logging.debug('Connection activated: %s', connection) - - def __activate_error_cb(self, err): - logging.error('Failed to activate connection: %s', err) - def set_filter(self, query): self._filtered = (query != '') self._update_color() @@ -727,8 +700,8 @@ class OlpcMeshView(CanvasPulsingIcon): self._bus.remove_signal_receiver(self.__device_state_changed_cb, signal_name='StateChanged', path=device_object_path, - dbus_interface=_NM_DEVICE_IFACE) + dbus_interface=network.NM_DEVICE_IFACE) self._bus.remove_signal_receiver(self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=device_object_path, - dbus_interface=_NM_OLPC_MESH_IFACE) + dbus_interface=network.NM_OLPC_MESH_IFACE) diff --git a/src/jarabe/model/adhoc.py b/src/jarabe/model/adhoc.py index 647bd8e..09325ed 100644 --- a/src/jarabe/model/adhoc.py +++ b/src/jarabe/model/adhoc.py @@ -25,14 +25,6 @@ from sugar.util import unique_id from jarabe.model.network import IP4Config -_NM_SERVICE = 'org.freedesktop.NetworkManager' -_NM_IFACE = 'org.freedesktop.NetworkManager' -_NM_PATH = '/org/freedesktop/NetworkManager' -_NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device' -_NM_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless' -_NM_ACCESSPOINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint' -_NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active' - _adhoc_manager_instance = None @@ -70,13 +62,17 @@ class AdHocManager(gobject.GObject): self._device = None self._idle_source = 0 self._listening_called = 0 - self._device_state = network.DEVICE_STATE_UNKNOWN + self._device_state = network.NM_DEVICE_STATE_UNKNOWN self._current_channel = None self._networks = {self._CHANNEL_1: None, self._CHANNEL_6: None, self._CHANNEL_11: None} + for channel in (self._CHANNEL_1, self._CHANNEL_6, self._CHANNEL_11): + if not self._find_connection(channel): + self._add_connection(channel) + def start_listening(self, device): self._listening_called += 1 if self._listening_called > 1: @@ -85,28 +81,28 @@ class AdHocManager(gobject.GObject): self._device = device props = dbus.Interface(device, dbus.PROPERTIES_IFACE) - self._device_state = props.Get(_NM_DEVICE_IFACE, 'State') + self._device_state = props.Get(network.NM_DEVICE_IFACE, 'State') self._bus.add_signal_receiver(self.__device_state_changed_cb, signal_name='StateChanged', path=self._device.object_path, - dbus_interface=_NM_DEVICE_IFACE) + dbus_interface=network.NM_DEVICE_IFACE) self._bus.add_signal_receiver(self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=self._device.object_path, - dbus_interface=_NM_WIRELESS_IFACE) + dbus_interface=network.NM_WIRELESS_IFACE) def stop_listening(self): self._listening_called = 0 self._bus.remove_signal_receiver(self.__device_state_changed_cb, signal_name='StateChanged', path=self._device.object_path, - dbus_interface=_NM_DEVICE_IFACE) + dbus_interface=network.NM_DEVICE_IFACE) self._bus.remove_signal_receiver(self.__wireless_properties_changed_cb, signal_name='PropertiesChanged', path=self._device.object_path, - dbus_interface=_NM_WIRELESS_IFACE) + dbus_interface=network.NM_WIRELESS_IFACE) def __device_state_changed_cb(self, new_state, old_state, reason): self._device_state = new_state @@ -115,10 +111,10 @@ class AdHocManager(gobject.GObject): def __wireless_properties_changed_cb(self, properties): if 'ActiveAccessPoint' in properties and \ properties['ActiveAccessPoint'] != '/': - active_ap = self._bus.get_object(_NM_SERVICE, + active_ap = self._bus.get_object(network.NM_SERVICE, properties['ActiveAccessPoint']) props = dbus.Interface(active_ap, dbus.PROPERTIES_IFACE) - props.GetAll(_NM_ACCESSPOINT_IFACE, byte_arrays=True, + props.GetAll(network.NM_ACCESSPOINT_IFACE, byte_arrays=True, reply_handler=self.__get_all_ap_props_reply_cb, error_handler=self.__get_all_ap_props_error_cb) @@ -137,13 +133,13 @@ class AdHocManager(gobject.GObject): def _update_state(self): self.emit('state-changed', self._current_channel, self._device_state) - def _have_configured_connections(self): - return len(network.get_settings().connections) > 0 - def autoconnect(self): """Start a timer which basically looks for 30 seconds of inactivity on the device, then does autoconnect to an Ad-hoc network. + This function may be called early on (e.g. when the device is still + in NM_DEVICE_STATE_UNMANAGED). It is assumed that initialisation + will complete quickly, and long before the timeout ticks. """ if self._idle_source != 0: gobject.source_remove(self._idle_source) @@ -151,7 +147,7 @@ class AdHocManager(gobject.GObject): self._AUTOCONNECT_TIMEOUT, self.__idle_check_cb) def __idle_check_cb(self): - if self._device_state == network.DEVICE_STATE_DISCONNECTED: + if self._device_state == network.NM_DEVICE_STATE_DISCONNECTED: logging.debug('Connect to Ad-hoc network due to inactivity.') self._autoconnect_adhoc() else: @@ -164,13 +160,13 @@ class AdHocManager(gobject.GObject): """ if self._networks[self._CHANNEL_1] is not None: - self._connect(self._CHANNEL_1) + self.activate_channel(self._CHANNEL_1) elif self._networks[self._CHANNEL_6] is not None: - self._connect(self._CHANNEL_6) + self.activate_channel(self._CHANNEL_6) elif self._networks[self._CHANNEL_11] is not None: - self._connect(self._CHANNEL_11) + self.activate_channel(self._CHANNEL_11) else: - self._connect(self._CHANNEL_1) + self.activate_channel(self._CHANNEL_1) def activate_channel(self, channel): """Activate a sugar Ad-hoc network. @@ -179,57 +175,54 @@ class AdHocManager(gobject.GObject): channel -- Channel to connect to (should be 1, 6, 11) """ - self._connect(channel) - - def _connect(self, channel): - name = 'Ad-hoc Network %d' % channel - connection = network.find_connection_by_ssid(name) - if connection is None: - settings = Settings() - settings.connection.id = name - settings.connection.uuid = unique_id() - settings.connection.type = '802-11-wireless' - settings.connection.autoconnect = True - settings.wireless.ssid = dbus.ByteArray(name) - settings.wireless.band = 'bg' - settings.wireless.channel = channel - settings.wireless.mode = 'adhoc' - settings.ip4_config = IP4Config() - settings.ip4_config.method = 'link-local' - - connection = network.add_connection(name, settings) - - obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) - netmgr = dbus.Interface(obj, _NM_IFACE) - - netmgr.ActivateConnection(network.SETTINGS_SERVICE, - connection.path, - self._device.object_path, - '/', - reply_handler=self.__activate_reply_cb, - error_handler=self.__activate_error_cb) + connection = self._find_connection(channel) + if connection: + connection.activate(self._device.object_path) + + @staticmethod + def _get_connection_id(channel): + return '%s%d' % (network.ADHOC_CONNECTION_ID_PREFIX, channel) + + def _add_connection(self, channel): + ssid = 'Ad-hoc Network %d' % (channel,) + settings = Settings() + settings.connection.id = self._get_connection_id(channel) + settings.connection.uuid = unique_id() + settings.connection.type = '802-11-wireless' + settings.connection.autoconnect = False + settings.wireless.ssid = dbus.ByteArray(ssid) + settings.wireless.band = 'bg' + settings.wireless.channel = channel + settings.wireless.mode = 'adhoc' + settings.ip4_config = IP4Config() + settings.ip4_config.method = 'link-local' + network.add_connection(settings) + + def _find_connection(self, channel): + connection_id = self._get_connection_id(channel) + return network.find_connection_by_id(connection_id) def deactivate_active_channel(self): """Deactivate the current active channel.""" - obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) - netmgr = dbus.Interface(obj, _NM_IFACE) + obj = self._bus.get_object(network.NM_SERVICE, network.NM_PATH) + netmgr = dbus.Interface(obj, network.NM_IFACE) netmgr_props = dbus.Interface(netmgr, dbus.PROPERTIES_IFACE) - netmgr_props.Get(_NM_IFACE, 'ActiveConnections', \ + netmgr_props.Get(network.NM_IFACE, 'ActiveConnections', \ reply_handler=self.__get_active_connections_reply_cb, error_handler=self.__get_active_connections_error_cb) def __get_active_connections_reply_cb(self, active_connections_o): for connection_o in active_connections_o: - obj = self._bus.get_object(_NM_IFACE, connection_o) + obj = self._bus.get_object(network.NM_IFACE, connection_o) props = dbus.Interface(obj, dbus.PROPERTIES_IFACE) - state = props.Get(_NM_ACTIVE_CONN_IFACE, 'State') + state = props.Get(network.NM_ACTIVE_CONN_IFACE, 'State') if state == network.NM_ACTIVE_CONNECTION_STATE_ACTIVATED: - access_point_o = props.Get(_NM_ACTIVE_CONN_IFACE, + access_point_o = props.Get(network.NM_ACTIVE_CONN_IFACE, 'SpecificObject') if access_point_o != '/': - obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) - netmgr = dbus.Interface(obj, _NM_IFACE) + obj = self._bus.get_object(network.NM_SERVICE, network.NM_PATH) + netmgr = dbus.Interface(obj, network.NM_IFACE) netmgr.DeactivateConnection(connection_o) def __get_active_connections_error_cb(self, err): diff --git a/src/jarabe/model/network.py b/src/jarabe/model/network.py index f265ae4..af510e1 100644 --- a/src/jarabe/model/network.py +++ b/src/jarabe/model/network.py @@ -21,7 +21,6 @@ from gettext import gettext as _ import logging import os -import time import dbus import dbus.service @@ -34,22 +33,38 @@ from sugar import dispatch from sugar import env from sugar.util import unique_id - -DEVICE_TYPE_802_3_ETHERNET = 1 -DEVICE_TYPE_802_11_WIRELESS = 2 -DEVICE_TYPE_GSM_MODEM = 3 -DEVICE_TYPE_802_11_OLPC_MESH = 6 - -DEVICE_STATE_UNKNOWN = 0 -DEVICE_STATE_UNMANAGED = 1 -DEVICE_STATE_UNAVAILABLE = 2 -DEVICE_STATE_DISCONNECTED = 3 -DEVICE_STATE_PREPARE = 4 -DEVICE_STATE_CONFIG = 5 -DEVICE_STATE_NEED_AUTH = 6 -DEVICE_STATE_IP_CONFIG = 7 -DEVICE_STATE_ACTIVATED = 8 -DEVICE_STATE_FAILED = 9 +NM_STATE_UNKNOWN = 0 +NM_STATE_ASLEEP = 10 +NM_STATE_DISCONNECTED = 20 +NM_STATE_DISCONNECTING = 30 +NM_STATE_CONNECTING = 40 +NM_STATE_CONNECTED_LOCAL = 50 +NM_STATE_CONNECTED_SITE = 60 +NM_STATE_CONNECTED_GLOBAL = 70 + +NM_DEVICE_TYPE_UNKNOWN = 0 +NM_DEVICE_TYPE_ETHERNET = 1 +NM_DEVICE_TYPE_WIFI = 2 +NM_DEVICE_TYPE_UNUSED1 = 3 +NM_DEVICE_TYPE_UNUSED2 = 4 +NM_DEVICE_TYPE_BT = 5 +NM_DEVICE_TYPE_OLPC_MESH = 6 +NM_DEVICE_TYPE_WIMAX = 7 +NM_DEVICE_TYPE_MODEM = 8 + +NM_DEVICE_STATE_UNKNOWN = 0 +NM_DEVICE_STATE_UNMANAGED = 10 +NM_DEVICE_STATE_UNAVAILABLE = 20 +NM_DEVICE_STATE_DISCONNECTED = 30 +NM_DEVICE_STATE_PREPARE = 40 +NM_DEVICE_STATE_CONFIG = 50 +NM_DEVICE_STATE_NEED_AUTH = 60 +NM_DEVICE_STATE_IP_CONFIG = 70 +NM_DEVICE_STATE_IP_CHECK = 80 +NM_DEVICE_STATE_SECONDARIES = 90 +NM_DEVICE_STATE_ACTIVATED = 100 +NM_DEVICE_STATE_DEACTIVATING = 110 +NM_DEVICE_STATE_FAILED = 120 NM_CONNECTION_TYPE_802_11_WIRELESS = '802-11-wireless' NM_CONNECTION_TYPE_GSM = 'gsm' @@ -57,15 +72,15 @@ NM_CONNECTION_TYPE_GSM = 'gsm' NM_ACTIVE_CONNECTION_STATE_UNKNOWN = 0 NM_ACTIVE_CONNECTION_STATE_ACTIVATING = 1 NM_ACTIVE_CONNECTION_STATE_ACTIVATED = 2 - +NM_ACTIVE_CONNECTION_STATE_DEACTIVATING = 3 NM_DEVICE_STATE_REASON_UNKNOWN = 0 NM_DEVICE_STATE_REASON_NONE = 1 NM_DEVICE_STATE_REASON_NOW_MANAGED = 2 NM_DEVICE_STATE_REASON_NOW_UNMANAGED = 3 NM_DEVICE_STATE_REASON_CONFIG_FAILED = 4 -NM_DEVICE_STATE_REASON_CONFIG_UNAVAILABLE = 5 -NM_DEVICE_STATE_REASON_CONFIG_EXPIRED = 6 +NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE = 5 +NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED = 6 NM_DEVICE_STATE_REASON_NO_SECRETS = 7 NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT = 8 NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED = 9 @@ -100,47 +115,74 @@ NM_DEVICE_STATE_REASON_SLEEPING = 37 NM_DEVICE_STATE_REASON_CONNECTION_REMOVED = 38 NM_DEVICE_STATE_REASON_USER_REQUESTED = 39 NM_DEVICE_STATE_REASON_CARRIER = 40 +NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED = 41 +NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE = 42 +NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND = 43 +NM_DEVICE_STATE_REASON_BT_FAILED = 44 +NM_DEVICE_STATE_REASON_LAST = 0xFFFF NM_802_11_AP_FLAGS_NONE = 0x00000000 NM_802_11_AP_FLAGS_PRIVACY = 0x00000001 -NM_802_11_AP_SEC_NONE = 0x00000000 -NM_802_11_AP_SEC_PAIR_WEP40 = 0x00000001 -NM_802_11_AP_SEC_PAIR_WEP104 = 0x00000002 -NM_802_11_AP_SEC_PAIR_TKIP = 0x00000004 -NM_802_11_AP_SEC_PAIR_CCMP = 0x00000008 -NM_802_11_AP_SEC_GROUP_WEP40 = 0x00000010 -NM_802_11_AP_SEC_GROUP_WEP104 = 0x00000020 -NM_802_11_AP_SEC_GROUP_TKIP = 0x00000040 -NM_802_11_AP_SEC_GROUP_CCMP = 0x00000080 -NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100 -NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200 +NM_802_11_AP_SEC_NONE = 0x0 +NM_802_11_AP_SEC_PAIR_WEP40 = 0x1 +NM_802_11_AP_SEC_PAIR_WEP104 = 0x2 +NM_802_11_AP_SEC_PAIR_TKIP = 0x4 +NM_802_11_AP_SEC_PAIR_CCMP = 0x8 +NM_802_11_AP_SEC_GROUP_WEP40 = 0x10 +NM_802_11_AP_SEC_GROUP_WEP104 = 0x20 +NM_802_11_AP_SEC_GROUP_TKIP = 0x40 +NM_802_11_AP_SEC_GROUP_CCMP = 0x80 +NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x100 +NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x200 NM_802_11_MODE_UNKNOWN = 0 NM_802_11_MODE_ADHOC = 1 NM_802_11_MODE_INFRA = 2 -NM_802_11_DEVICE_CAP_NONE = 0x00000000 -NM_802_11_DEVICE_CAP_CIPHER_WEP40 = 0x00000001 -NM_802_11_DEVICE_CAP_CIPHER_WEP104 = 0x00000002 -NM_802_11_DEVICE_CAP_CIPHER_TKIP = 0x00000004 -NM_802_11_DEVICE_CAP_CIPHER_CCMP = 0x00000008 -NM_802_11_DEVICE_CAP_WPA = 0x00000010 -NM_802_11_DEVICE_CAP_RSN = 0x00000020 +NM_WIFI_DEVICE_CAP_NONE = 0x00000000 +NM_WIFI_DEVICE_CAP_CIPHER_WEP40 = 0x00000001 +NM_WIFI_DEVICE_CAP_CIPHER_WEP104 = 0x00000002 +NM_WIFI_DEVICE_CAP_CIPHER_TKIP = 0x00000004 +NM_WIFI_DEVICE_CAP_CIPHER_CCMP = 0x00000008 +NM_WIFI_DEVICE_CAP_WPA = 0x00000010 +NM_WIFI_DEVICE_CAP_RSN = 0x00000020 + +NM_BT_CAPABILITY_NONE = 0x00000000 +NM_BT_CAPABILITY_DUN = 0x00000001 +NM_BT_CAPABILITY_NAP = 0x00000002 + +NM_DEVICE_MODEM_CAPABILITY_NONE = 0x00000000 +NM_DEVICE_MODEM_CAPABILITY_POTS = 0x00000001 +NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO = 0x00000002 +NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS = 0x00000004 +NM_DEVICE_MODEM_CAPABILITY_LTE = 0x00000008 -SETTINGS_SERVICE = 'org.freedesktop.NetworkManagerUserSettings' +SETTINGS_SERVICE = 'org.freedesktop.NetworkManager' NM_SERVICE = 'org.freedesktop.NetworkManager' NM_IFACE = 'org.freedesktop.NetworkManager' NM_PATH = '/org/freedesktop/NetworkManager' NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device' -NM_SETTINGS_PATH = '/org/freedesktop/NetworkManagerSettings' -NM_SETTINGS_IFACE = 'org.freedesktop.NetworkManagerSettings' -NM_CONNECTION_IFACE = 'org.freedesktop.NetworkManagerSettings.Connection' -NM_SECRETS_IFACE = 'org.freedesktop.NetworkManagerSettings.Connection.Secrets' +NM_WIRED_IFACE = 'org.freedesktop.NetworkManager.Device.Wired' +NM_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless' +NM_MODEM_IFACE = 'org.freedesktop.NetworkManager.Device.Modem' +NM_OLPC_MESH_IFACE = 'org.freedesktop.NetworkManager.Device.OlpcMesh' +NM_SETTINGS_PATH = '/org/freedesktop/NetworkManager/Settings' +NM_SETTINGS_IFACE = 'org.freedesktop.NetworkManager.Settings' +NM_CONNECTION_IFACE = 'org.freedesktop.NetworkManager.Settings.Connection' NM_ACCESSPOINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint' NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active' +NM_SECRET_AGENT_IFACE = 'org.freedesktop.NetworkManager.SecretAgent' +NM_SECRET_AGENT_PATH = '/org/freedesktop/NetworkManager/SecretAgent' +NM_AGENT_MANAGER_IFACE = 'org.freedesktop.NetworkManager.AgentManager' +NM_AGENT_MANAGER_PATH = '/org/freedesktop/NetworkManager/AgentManager' + +NM_AGENT_MANAGER_ERR_NO_SECRETS = 'org.freedesktop.NetworkManager.AgentManager.NoSecrets' + +GSM_CONNECTION_ID = 'Sugar Modem Connection' +GSM_BAUD_RATE = 115200 GSM_USERNAME_PATH = '/desktop/sugar/network/gsm/username' GSM_PASSWORD_PATH = '/desktop/sugar/network/gsm/password' GSM_NUMBER_PATH = '/desktop/sugar/network/gsm/number' @@ -148,8 +190,14 @@ GSM_APN_PATH = '/desktop/sugar/network/gsm/apn' GSM_PIN_PATH = '/desktop/sugar/network/gsm/pin' GSM_PUK_PATH = '/desktop/sugar/network/gsm/puk' +ADHOC_CONNECTION_ID_PREFIX = 'Sugar Ad-hoc Network ' +MESH_CONNECTION_ID_PREFIX = 'OLPC Mesh Network ' +XS_MESH_CONNECTION_ID_PREFIX = 'OLPC XS Mesh Network ' + +_network_manager = None _nm_settings = None -_conn_counter = 0 +_secret_agent = None +_connections = None _nm_device_state_reason_description = None @@ -169,10 +217,10 @@ def get_error_by_reason(reason): _('The device is no longer managed.'), NM_DEVICE_STATE_REASON_CONFIG_FAILED: _('The device could not be readied for configuration.'), - NM_DEVICE_STATE_REASON_CONFIG_UNAVAILABLE: + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE: _('IP configuration could not be reserved ' '(no available address, timeout, etc).'), - NM_DEVICE_STATE_REASON_CONFIG_EXPIRED: + NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED: _('The IP configuration is no longer valid.'), NM_DEVICE_STATE_REASON_NO_SECRETS: _('Secrets were required, but not provided.'), @@ -244,7 +292,18 @@ def get_error_by_reason(reason): NM_DEVICE_STATE_REASON_USER_REQUESTED: _('A user or client requested the disconnection.'), NM_DEVICE_STATE_REASON_CARRIER: - _("The device's carrier/link changed.")} + _("The device's carrier/link changed."), + NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED: + _("The device's existing connection was assumed."), + NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE: + _("The supplicant is now available."), + NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND: + _("The modem could not be found."), + NM_DEVICE_STATE_REASON_BT_FAILED: + _("The Bluetooth connection failed or timed out."), + NM_DEVICE_STATE_REASON_LAST: + _("Unused."), + } return _nm_device_state_reason_description[reason] @@ -288,6 +347,9 @@ class WirelessSecurity(object): self.proto = None self.group = None self.pairwise = None + self.wep_key = None + self.psk = None + self.auth_alg = None def get_dict(self): wireless_security = {} @@ -299,6 +361,12 @@ class WirelessSecurity(object): wireless_security['pairwise'] = self.pairwise if self.group is not None: wireless_security['group'] = self.group + if self.wep_key is not None: + wireless_security['wep-key0'] = self.wep_key + if self.psk is not None: + wireless_security['psk'] = self.psk + if self.auth_alg is not None: + wireless_security['auth-alg'] = self.auth_alg return wireless_security @@ -343,7 +411,7 @@ class OlpcMesh(object): return ret -class Connection(object): +class ConnectionSettings(object): def __init__(self): self.id = None self.uuid = None @@ -399,23 +467,29 @@ class Gsm(object): self.apn = None self.number = None self.username = None + self.pin = None + self.password = None def get_dict(self): gsm = {} - if self.apn is not None: + if self.apn: gsm['apn'] = self.apn - if self.number is not None: + if self.number: gsm['number'] = self.number - if self.username is not None: + if self.username: gsm['username'] = self.username + if self.password: + gsm['password'] = self.password + if self.pin: + gsm['pin'] = self.pin return gsm class Settings(object): def __init__(self, wireless_cfg=None): - self.connection = Connection() + self.connection = ConnectionSettings() self.ip4_config = None self.wireless_security = None @@ -436,35 +510,9 @@ class Settings(object): return settings -class Secrets(object): - def __init__(self, settings): - self.settings = settings - self.wep_key = None - self.psk = None - self.auth_alg = None - - def get_dict(self): - # Although we could just return the keys here, we instead return all - # of the network settings so that we can apply any late decisions made - # by the user (e.g. if they selected shared key authentication). see - # http://bugs.sugarlabs.org/ticket/1602 - settings = self.settings.get_dict() - if '802-11-wireless-security' not in settings: - settings['802-11-wireless-security'] = {} - - if self.wep_key is not None: - settings['802-11-wireless-security']['wep-key0'] = self.wep_key - if self.psk is not None: - settings['802-11-wireless-security']['psk'] = self.psk - if self.auth_alg is not None: - settings['802-11-wireless-security']['auth-alg'] = self.auth_alg - - return settings - - class SettingsGsm(object): def __init__(self): - self.connection = Connection() + self.connection = ConnectionSettings() self.ip4_config = IP4Config() self.serial = Serial() self.ppp = Ppp() @@ -482,222 +530,69 @@ class SettingsGsm(object): return settings -class SecretsGsm(object): - def __init__(self): - self.password = None - self.pin = None - self.puk = None - - def get_dict(self): - secrets = {} - if self.password is not None: - secrets['password'] = self.password - if self.pin is not None: - secrets['pin'] = self.pin - if self.puk is not None: - secrets['puk'] = self.puk - return {'gsm': secrets} - - -class NMSettings(dbus.service.Object): - def __init__(self): - bus = dbus.SystemBus() - bus_name = dbus.service.BusName(SETTINGS_SERVICE, bus=bus) - dbus.service.Object.__init__(self, bus_name, NM_SETTINGS_PATH) - - self.connections = {} - self.secrets_request = dispatch.Signal() - - @dbus.service.method(dbus_interface=NM_SETTINGS_IFACE, - in_signature='', out_signature='ao') - def ListConnections(self): - return self.connections.values() - - @dbus.service.signal(NM_SETTINGS_IFACE, signature='o') - def NewConnection(self, connection_path): - pass - - def add_connection(self, uuid, conn): - self.connections[uuid] = conn - conn.secrets_request.connect(self.__secrets_request_cb) - self.NewConnection(conn.path) - - def __secrets_request_cb(self, sender, **kwargs): - self.secrets_request.send(self, connection=sender, - response=kwargs['response']) - - def clear_wifi_connections(self): - for uuid in self.connections.keys(): - conn = self.connections[uuid] - if conn._settings.connection.type == \ - NM_CONNECTION_TYPE_802_11_WIRELESS: - conn.Removed() - self.connections.pop(uuid) - - class SecretsResponse(object): """Intermediate object to report the secrets from the dialog back to the connection object and which will inform NM """ - def __init__(self, connection, reply_cb, error_cb): - self._connection = connection + def __init__(self, reply_cb, error_cb): self._reply_cb = reply_cb self._error_cb = error_cb def set_secrets(self, secrets): - self._connection.set_secrets(secrets) - self._reply_cb(secrets.get_dict()) + self._reply_cb(secrets) def set_error(self, error): self._error_cb(error) -class NMSettingsConnection(dbus.service.Object): - def __init__(self, path, settings, secrets): - bus = dbus.SystemBus() - bus_name = dbus.service.BusName(SETTINGS_SERVICE, bus=bus) - dbus.service.Object.__init__(self, bus_name, path) - - self.path = path +def set_connected(): + try: + # try to flush resolver cache - SL#1940 + # ctypes' syntactic sugar does not work + # so we must get the func ptr explicitly + libc = ctypes.CDLL('libc.so.6') + res_init = getattr(libc, '__res_init') + res_init(None) + except: + # pylint: disable=W0702 + logging.exception('Error calling libc.__res_init') + + +class SecretAgent(dbus.service.Object): + def __init__(self): + self._bus = dbus.SystemBus() + dbus.service.Object.__init__(self, self._bus, NM_SECRET_AGENT_PATH) self.secrets_request = dispatch.Signal() + proxy = self._bus.get_object(NM_IFACE, NM_AGENT_MANAGER_PATH) + proxy.Register("org.sugarlabs.sugar", + dbus_interface=NM_AGENT_MANAGER_IFACE, + reply_handler=self._register_reply_cb, + error_handler=self._register_error_cb) - self._settings = settings - self._secrets = secrets - - @dbus.service.signal(dbus_interface=NM_CONNECTION_IFACE, - signature='') - def Removed(self): - pass - - @dbus.service.signal(dbus_interface=NM_CONNECTION_IFACE, - signature='a{sa{sv}}') - def Updated(self, settings): - pass - - def set_connected(self): - if self._settings.connection.type == NM_CONNECTION_TYPE_GSM: - self._settings.connection.timestamp = int(time.time()) - elif not self._settings.connection.autoconnect: - self._settings.connection.autoconnect = True - self._settings.connection.timestamp = int(time.time()) - if (self._settings.connection.type == - NM_CONNECTION_TYPE_802_11_WIRELESS): - self.Updated(self._settings.get_dict()) - self.save() - - try: - # try to flush resolver cache - SL#1940 - # ctypes' syntactic sugar does not work - # so we must get the func ptr explicitly - libc = ctypes.CDLL('libc.so.6') - res_init = getattr(libc, '__res_init') - res_init(None) - except: - # pylint: disable=W0702 - logging.exception('Error calling libc.__res_init') - - def disable_autoconnect(self): - if self._settings.connection.type != NM_CONNECTION_TYPE_GSM and \ - self._settings.connection.autoconnect: - self._settings.connection.autoconnect = False - self._settings.connection.timestamp = None - self.Updated(self._settings.get_dict()) - self.save() - - def set_secrets(self, secrets): - self._secrets = secrets - if self._settings.connection.type == \ - NM_CONNECTION_TYPE_802_11_WIRELESS: - self.save() - - def get_settings(self): - return self._settings - - def save(self): - config_path = _get_wifi_connections_path() - - config = ConfigParser.ConfigParser() - try: - try: - if not config.read(config_path): - logging.error('Error reading the nm config file') - return - except ConfigParser.ParsingError: - logging.exception('Error reading the nm config file') - return - identifier = self._settings.connection.id - - if identifier not in config.sections(): - config.add_section(identifier) - config.set(identifier, 'type', self._settings.connection.type) - config.set(identifier, 'ssid', self._settings.wireless.ssid) - config.set(identifier, 'uuid', self._settings.connection.uuid) - config.set(identifier, 'autoconnect', - self._settings.connection.autoconnect) - if self._settings.connection.timestamp is not None: - config.set(identifier, 'timestamp', - self._settings.connection.timestamp) - if self._settings.wireless_security is not None: - if self._settings.wireless_security.key_mgmt is not None: - config.set(identifier, 'key-mgmt', - self._settings.wireless_security.key_mgmt) - if self._settings.wireless_security.proto is not None: - config.set(identifier, 'proto', - self._settings.wireless_security.proto) - if self._settings.wireless_security.pairwise is not None: - config.set(identifier, 'pairwise', - self._settings.wireless_security.pairwise) - if self._settings.wireless_security.group is not None: - config.set(identifier, 'group', - self._settings.wireless_security.group) - if self._settings.wireless.security is not None: - config.set(identifier, 'security', - self._settings.wireless.security) - if self._secrets is not None: - if self._settings.wireless_security.key_mgmt == 'none': - config.set(identifier, 'key', self._secrets.wep_key) - config.set(identifier, 'auth-alg', self._secrets.auth_alg) - elif self._settings.wireless_security.key_mgmt == 'wpa-psk': - config.set(identifier, 'key', self._secrets.psk) - except ConfigParser.Error, e: - logging.exception('Error constructing %s', identifier) - else: - f = open(config_path, 'w') - try: - config.write(f) - except ConfigParser.Error: - logging.exception('Can not write %s', config_path) - f.close() + def _register_reply_cb(self): + logging.debug("SecretAgent registered") - @dbus.service.method(dbus_interface=NM_CONNECTION_IFACE, - in_signature='', out_signature='a{sa{sv}}') - def GetSettings(self): - return self._settings.get_dict() + def _register_error_cb(self, error): + logging.error("Failed to register SecretAgent: %s", error) - @dbus.service.method(dbus_interface=NM_SECRETS_IFACE, + @dbus.service.method(NM_SECRET_AGENT_IFACE, async_callbacks=('reply', 'error'), - in_signature='sasb', out_signature='a{sa{sv}}') - def GetSecrets(self, setting_name, hints, request_new, reply, error): - logging.debug('Secrets requested for connection %s request_new=%s', - self.path, request_new) - if self._settings.connection.type is not NM_CONNECTION_TYPE_GSM: - if request_new or self._secrets is None: - # request_new is for example the case when the pw on the AP - # changes - response = SecretsResponse(self, reply, error) - try: - self.secrets_request.send(self, response=response) - except Exception: - logging.exception('Error requesting the secrets via' - ' dialog') - else: - reply(self._secrets.get_dict()) - else: - if not request_new: - reply(self._secrets.get_dict()) - else: - raise Exception('The stored GSM secret has already been' - ' supplied') + in_signature='a{sa{sv}}osasb', + out_signature='a{sa{sv}}', + sender_keyword='sender', + byte_arrays=True) + def GetSecrets(self, settings, connection_path, setting_name, hints, + request_new, reply, error, sender=None): + if setting_name != '802-11-wireless-security': + raise ValueError("Unsupported setting type %s" % (setting_name,)) + if not sender: + raise Exception("Internal error: couldn't get sender") + uid = self._bus.get_unix_user(sender) + if uid != 0: + raise Exception("UID %d not authorized" % (uid,)) + + response = SecretsResponse(reply, error) + self.secrets_request.send(self, settings=settings, response=response) class AccessPoint(gobject.GObject): @@ -808,58 +703,218 @@ class AccessPoint(gobject.GObject): dbus_interface=NM_ACCESSPOINT_IFACE) -def get_settings(): +def get_manager(): + global _network_manager + if _network_manager is None: + obj = dbus.SystemBus().get_object(NM_SERVICE, NM_PATH) + _network_manager = dbus.Interface(obj, NM_IFACE) + return _network_manager + + +def _get_settings(): global _nm_settings if _nm_settings is None: - try: - _nm_settings = NMSettings() - except dbus.DBusException: - logging.exception('Cannot create the UserSettings service.') - load_connections() + obj = dbus.SystemBus().get_object(NM_SERVICE, NM_SETTINGS_PATH) + _nm_settings = dbus.Interface(obj, NM_SETTINGS_IFACE) + _migrate_old_wifi_connections() + _migrate_old_gsm_connection() return _nm_settings -def find_connection_by_ssid(ssid): - connections = get_settings().connections +def get_secret_agent(): + global _secret_agent + if _secret_agent is None: + _secret_agent = SecretAgent() + return _secret_agent + + +def _activate_reply_cb(connection): + logging.debug('Activated connection: %s', connection) + + +def _activate_error_cb(err): + logging.error('Failed to activate connection: %s', err) + + +class Connection(gobject.GObject): + __gsignals__ = { + 'removed': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), + } + + def __init__(self, bus, path): + gobject.GObject.__init__(self) + obj = bus.get_object(NM_SERVICE, path) + self._connection = dbus.Interface(obj, NM_CONNECTION_IFACE) + self._removed_handle = self._connection.connect_to_signal( + 'Removed', self._removed_cb) + self._updated_handle = self._connection.connect_to_signal( + 'Updated', self._updated_cb) + self._settings = self._connection.GetSettings(byte_arrays=True) + + def _updated_cb(self): + self._settings = self._connection.GetSettings(byte_arrays=True) + + def _removed_cb(self): + self._updated_handle.remove() + self._removed_handle.remove() + self.emit('removed') + + def get_settings(self, stype=None): + if not stype: + return self._settings + elif stype in self._settings: + return self._settings[stype] + else: + return None + + def get_secrets(self, stype, reply_handler, error_handler): + return self._connection.GetSecrets(stype, byte_arrays=True, + reply_handler=reply_handler, + error_handler=error_handler) + + def update_settings(self, settings): + self._connection.Update(settings) + + def activate(self, device_o, reply_handler=_activate_reply_cb, + error_handler=_activate_error_cb): + activate_connection_by_path(self.get_path(), device_o, + reply_handler=reply_handler, + error_handler=error_handler) + + def delete(self): + self._connection.Delete() + + def get_ssid(self): + wifi_settings = self.get_settings('802-11-wireless') + if wifi_settings and 'ssid' in wifi_settings: + return wifi_settings['ssid'] + else: + return None + + def get_id(self): + return self.get_settings('connection')['id'] + + def get_path(self): + return self._connection.object_path + + def is_sugar_internal_connection(self): + """Returns True if this connection is a 'special' Sugar connection, + i.e. one that has been created by Sugar internals and should not be + visible to the user or deleted by connection-clearing code.""" + connection_id = self.get_id() + return connection_id == GSM_CONNECTION_ID \ + or connection_id.startswith(ADHOC_CONNECTION_ID_PREFIX) \ + or connection_id.startswith(MESH_CONNECTION_ID_PREFIX) \ + or connection_id.startswith(XS_MESH_CONNECTION_ID_PREFIX) + + +class Connections(object): + def __init__(self): + self._bus = dbus.SystemBus() + self._connections = [] + + settings = _get_settings() + settings.connect_to_signal('NewConnection', self._new_connection_cb) + + for connection_o in settings.ListConnections(): + self._monitor_connection(connection_o) + + def get_list(self): + return self._connections + + def _monitor_connection(self, connection_o): + connection = Connection(self._bus, connection_o) + connection.connect('removed', self._connection_removed_cb) + self._connections.append(connection) + + def _new_connection_cb(self, connection_o): + self._monitor_connection(connection_o) + + def _connection_removed_cb(self, connection): + connection.disconnect_by_func(self._connection_removed_cb) + self._connections.remove(connection) - for conn_index in connections: - connection = connections[conn_index] - if connection._settings.connection.type == \ - NM_CONNECTION_TYPE_802_11_WIRELESS and \ - connection._settings.wireless.ssid == ssid: + def clear(self): + """Remove all connections except Sugar-internal ones.""" + + # copy the list, to avoid problems with removing elements of a list + # while looping over it + connections = list(self._connections) + for connection in connections: + if connection.is_sugar_internal_connection(): + continue + try: + connection.delete() + except dbus.DBusException: + logging.debug("Could not remove connection %s", + connection.get_id()) + + +def get_connections(): + global _connections + if _connections is None: + _connections = Connections() + return _connections + + +def find_connection_by_ssid(ssid): + # FIXME: this check should be more extensive. + # it should look at mode (infra/adhoc), band, security, and really + # anything that is stored in the settings. + for connection in get_connections().get_list(): + if connection.get_ssid() == ssid: return connection + return None + +def find_connection_by_id(connection_id): + for connection in get_connections().get_list(): + if connection.get_id() == connection_id: + return connection return None -def add_connection(uuid, settings, secrets=None): - global _conn_counter +def _add_connection_reply_cb(connection): + logging.debug('Added connection: %s', connection) - path = NM_SETTINGS_PATH + '/' + str(_conn_counter) - _conn_counter += 1 - conn = NMSettingsConnection(path, settings, secrets) - _nm_settings.add_connection(uuid, conn) - return conn +def _add_connection_error_cb(err): + logging.error('Failed to add connection: %s', err) -def _get_wifi_connections_path(): - profile_path = env.get_profile_path() - return os.path.join(profile_path, 'nm', 'connections.cfg') +def add_connection(settings, reply_handler=_add_connection_reply_cb, + error_handler=_add_connection_error_cb): + _get_settings().AddConnection(settings.get_dict(), + reply_handler=reply_handler, + error_handler=error_handler) + + +def activate_connection_by_path(connection, device_o, + reply_handler=_activate_reply_cb, + error_handler=_activate_error_cb): + get_manager().ActivateConnection(connection, + device_o, + '/', + reply_handler=reply_handler, + error_handler=error_handler) -def _create_wifi_connections(config_path): - if not os.path.exists(os.path.dirname(config_path)): - os.makedirs(os.path.dirname(config_path), 0755) - f = open(config_path, 'w') - f.close() +def add_and_activate_connection(device_o, settings, specific_object): + get_manager().AddAndActivateConnection(settings.get_dict(), device_o, + specific_object, + reply_handler=_activate_reply_cb, + error_handler=_activate_error_cb) -def load_wifi_connections(): - config_path = _get_wifi_connections_path() +def _migrate_old_wifi_connections(): + """Migrate connections.cfg from Sugar-0.94 and previous to NetworkManager + system-wide connections + """ + profile_path = env.get_profile_path() + config_path = os.path.join(profile_path, 'nm', 'connections.cfg') if not os.path.exists(config_path): - _create_wifi_connections(config_path) + return config = ConfigParser.ConfigParser() try: @@ -887,9 +942,7 @@ def load_wifi_connections(): timestamp = int(config.get(section, 'timestamp')) settings.connection.timestamp = timestamp - secrets = None if config.has_option(section, 'key-mgmt'): - secrets = Secrets(settings) settings.wireless_security = WirelessSecurity() mgmt = config.get(section, 'key-mgmt') settings.wireless_security.key_mgmt = mgmt @@ -897,11 +950,11 @@ def load_wifi_connections(): settings.wireless.security = security key = config.get(section, 'key') if mgmt == 'none': - secrets.wep_key = key + settings.wireless_security.wep_key = key auth_alg = config.get(section, 'auth-alg') - secrets.auth_alg = auth_alg + settings.wireless_security.auth_alg = auth_alg elif mgmt == 'wpa-psk': - secrets.psk = key + settings.wireless_security.psk = key if config.has_option(section, 'proto'): value = config.get(section, 'proto') settings.wireless_security.proto = value @@ -914,11 +967,33 @@ def load_wifi_connections(): except ConfigParser.Error: logging.exception('Error reading section') else: - add_connection(uuid, settings, secrets) + add_connection(settings) + + os.unlink(config_path) -def load_gsm_connection(): - _BAUD_RATE = 115200 +def create_gsm_connection(username, password, number, apn, pin): + settings = SettingsGsm() + settings.gsm.username = username + settings.gsm.number = number + settings.gsm.apn = apn + settings.gsm.pin = pin + settings.gsm.password = password + + settings.connection.id = GSM_CONNECTION_ID + settings.connection.type = NM_CONNECTION_TYPE_GSM + settings.connection.uuid = unique_id() + settings.connection.autoconnect = False + settings.ip4_config.method = 'auto' + settings.serial.baud = GSM_BAUD_RATE + + add_connection(settings) + + +def _migrate_old_gsm_connection(): + if find_gsm_connection(): + # don't attempt migration if a NM-level connection already exists + return client = gconf.client_get_default() @@ -927,60 +1002,22 @@ def load_gsm_connection(): number = client.get_string(GSM_NUMBER_PATH) or '' apn = client.get_string(GSM_APN_PATH) or '' pin = client.get_string(GSM_PIN_PATH) or '' - puk = client.get_string(GSM_PUK_PATH) or '' - - if username and number and apn: - settings = SettingsGsm() - settings.gsm.username = username - settings.gsm.number = number - settings.gsm.apn = apn - - secrets = SecretsGsm() - secrets.pin = pin - secrets.puk = puk - secrets.password = password - - settings.connection.id = 'gsm' - settings.connection.type = NM_CONNECTION_TYPE_GSM - uuid = settings.connection.uuid = unique_id() - settings.connection.autoconnect = False - settings.ip4_config.method = 'auto' - settings.serial.baud = _BAUD_RATE + if apn or number: + logging.info("Migrating old GSM connection details") try: - add_connection(uuid, settings, secrets) + create_gsm_connection(username, password, number, apn, pin) + # remove old connection + for setting in (GSM_USERNAME_PATH, GSM_PASSWORD_PATH, + GSM_NUMBER_PATH, GSM_APN_PATH, GSM_PIN_PATH, + GSM_PUK_PATH): + client.set_string(setting, '') except Exception: logging.exception('Error adding gsm connection to NMSettings.') - else: - logging.warning('No gsm connection was set in GConf.') - - -def load_connections(): - load_wifi_connections() - load_gsm_connection() def find_gsm_connection(): - connections = get_settings().connections - - for connection in connections.values(): - if connection.get_settings().connection.type == NM_CONNECTION_TYPE_GSM: - return connection - - logging.debug('There is no gsm connection in the NMSettings.') - return None - - -def have_wifi_connections(): - return bool(get_settings().connections) - - -def clear_wifi_connections(): - if _nm_settings is not None: - _nm_settings.clear_wifi_connections() - - config_path = _get_wifi_connections_path() - _create_wifi_connections(config_path) + return find_connection_by_id(GSM_CONNECTION_ID) def disconnect_access_points(ap_paths): diff --git a/src/jarabe/model/olpcmesh.py b/src/jarabe/model/olpcmesh.py index f070100..6ab7ab6 100644 --- a/src/jarabe/model/olpcmesh.py +++ b/src/jarabe/model/olpcmesh.py @@ -24,64 +24,61 @@ from jarabe.model.network import Settings from jarabe.model.network import OlpcMesh as OlpcMeshSettings from sugar.util import unique_id - -_NM_SERVICE = 'org.freedesktop.NetworkManager' -_NM_IFACE = 'org.freedesktop.NetworkManager' -_NM_PATH = '/org/freedesktop/NetworkManager' -_NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device' -_NM_OLPC_MESH_IFACE = 'org.freedesktop.NetworkManager.Device.OlpcMesh' - _XS_ANYCAST = '\xc0\x27\xc0\x27\xc0\x00' -DEVICE_STATE_UNKNOWN = 0 -DEVICE_STATE_UNMANAGED = 1 -DEVICE_STATE_UNAVAILABLE = 2 -DEVICE_STATE_DISCONNECTED = 3 -DEVICE_STATE_PREPARE = 4 -DEVICE_STATE_CONFIG = 5 -DEVICE_STATE_NEED_AUTH = 6 -DEVICE_STATE_IP_CONFIG = 7 -DEVICE_STATE_ACTIVATED = 8 -DEVICE_STATE_FAILED = 9 - class OlpcMeshManager(object): def __init__(self, mesh_device): self._bus = dbus.SystemBus() + # counter for how many asynchronous connection additions we are + # waiting for + self._add_connections_pending = 0 + self.mesh_device = mesh_device self.eth_device = self._get_companion_device() self._connection_queue = [] """Stack of connections that we'll iterate through until we find one - that works. + that works. Each entry in the list specifies the channel and + whether to seek an XS or not.""" - """ + # Ensure that all the connections we'll use later are present + for channel in (1, 6, 11): + self._ensure_connection_exists(channel, xs_hosted=True) + self._ensure_connection_exists(channel, xs_hosted=False) props = dbus.Interface(self.mesh_device, dbus.PROPERTIES_IFACE) - props.Get(_NM_DEVICE_IFACE, 'State', + props.Get(network.NM_DEVICE_IFACE, 'State', reply_handler=self.__get_mesh_state_reply_cb, error_handler=self.__get_state_error_cb) props = dbus.Interface(self.eth_device, dbus.PROPERTIES_IFACE) - props.Get(_NM_DEVICE_IFACE, 'State', + props.Get(network.NM_DEVICE_IFACE, 'State', reply_handler=self.__get_eth_state_reply_cb, error_handler=self.__get_state_error_cb) self._bus.add_signal_receiver(self.__eth_device_state_changed_cb, signal_name='StateChanged', path=self.eth_device.object_path, - dbus_interface=_NM_DEVICE_IFACE) + dbus_interface=network.NM_DEVICE_IFACE) self._bus.add_signal_receiver(self.__mshdev_state_changed_cb, signal_name='StateChanged', path=self.mesh_device.object_path, - dbus_interface=_NM_DEVICE_IFACE) + dbus_interface=network.NM_DEVICE_IFACE) self._idle_source = 0 - self._mesh_device_state = DEVICE_STATE_UNKNOWN - self._eth_device_state = DEVICE_STATE_UNKNOWN + self._mesh_device_state = network.NM_DEVICE_STATE_UNKNOWN + self._eth_device_state = network.NM_DEVICE_STATE_UNKNOWN + if self._add_connections_pending == 0: + self.ready() + + def ready(self): + """Called when all connections have been added (if they were not + already present), meaning that we can start the automesh functionality. + """ if self._have_configured_connections(): self._start_automesh_timer() else: @@ -89,11 +86,11 @@ class OlpcMeshManager(object): def _get_companion_device(self): props = dbus.Interface(self.mesh_device, dbus.PROPERTIES_IFACE) - eth_device_o = props.Get(_NM_OLPC_MESH_IFACE, 'Companion') - return self._bus.get_object(_NM_SERVICE, eth_device_o) + eth_device_o = props.Get(network.NM_OLPC_MESH_IFACE, 'Companion') + return self._bus.get_object(network.NM_SERVICE, eth_device_o) def _have_configured_connections(self): - return len(network.get_settings().connections) > 0 + return len(network.get_connections().get_list()) > 0 def _start_automesh_timer(self): """Start our timer system which basically looks for 10 seconds of @@ -123,8 +120,8 @@ class OlpcMeshManager(object): self._eth_device_state = new_state self._maybe_schedule_idle_check() - if new_state >= DEVICE_STATE_PREPARE \ - and new_state <= DEVICE_STATE_ACTIVATED \ + if new_state >= network.NM_DEVICE_STATE_PREPARE \ + and new_state <= network.NM_DEVICE_STATE_ACTIVATED \ and len(self._connection_queue) > 0: self._connection_queue = [] @@ -132,62 +129,81 @@ class OlpcMeshManager(object): self._mesh_device_state = new_state self._maybe_schedule_idle_check() - if new_state == DEVICE_STATE_FAILED: + if new_state == network.NM_DEVICE_STATE_FAILED: self._try_next_connection_from_queue() - elif new_state == DEVICE_STATE_ACTIVATED \ + elif new_state == network.NM_DEVICE_STATE_ACTIVATED \ and len(self._connection_queue) > 0: self._empty_connection_queue() def _maybe_schedule_idle_check(self): - if self._mesh_device_state == DEVICE_STATE_DISCONNECTED \ - and self._eth_device_state == DEVICE_STATE_DISCONNECTED: + if self._mesh_device_state == network.NM_DEVICE_STATE_DISCONNECTED \ + and self._eth_device_state == network.NM_DEVICE_STATE_DISCONNECTED: self._start_automesh_timer() def _idle_check(self): - if self._mesh_device_state == DEVICE_STATE_DISCONNECTED \ - and self._eth_device_state == DEVICE_STATE_DISCONNECTED: + if self._mesh_device_state == network.NM_DEVICE_STATE_DISCONNECTED \ + and self._eth_device_state == network.NM_DEVICE_STATE_DISCONNECTED: logging.debug('starting automesh due to inactivity') self._start_automesh() return False - def _make_connection(self, channel, anycast_address=None): - wireless_config = OlpcMeshSettings(channel, anycast_address) + @staticmethod + def _get_connection_id(channel, xs_hosted): + if xs_hosted: + return '%s%d' % (network.XS_MESH_CONNECTION_ID_PREFIX, channel) + else: + return '%s%d' % (network.MESH_CONNECTION_ID_PREFIX, channel) + + def _connection_added(self): + if self._add_connections_pending > 0: + self._add_connections_pending = self._add_connections_pending - 1 + if self._add_connections_pending == 0: + self.ready() + + def _add_connection_reply_cb(self, connection): + logging.debug("Added connection: %s", connection) + self._connection_added() + + def _add_connection_err_cb(self, err): + logging.debug("Error adding mesh connection: %s", err) + self._connection_added() + + def _add_connection(self, channel, xs_hosted): + anycast_addr = _XS_ANYCAST if xs_hosted else None + wireless_config = OlpcMeshSettings(channel, anycast_addr) settings = Settings(wireless_cfg=wireless_config) - if not anycast_address: + if not xs_hosted: settings.ip4_config = network.IP4Config() settings.ip4_config.method = 'link-local' - settings.connection.id = 'olpc-mesh-' + str(channel) + settings.connection.id = self._get_connection_id(channel, xs_hosted) + settings.connection.autoconnect = False settings.connection.uuid = unique_id() settings.connection.type = '802-11-olpc-mesh' - connection = network.add_connection(settings.connection.id, settings) - return connection - - def __activate_reply_cb(self, connection): - logging.debug('Connection activated: %s', connection) - - def __activate_error_cb(self, err): - logging.error('Failed to activate connection: %s', err) - - def _activate_connection(self, channel, anycast_address=None): - logging.debug('activate channel %d anycast %r', - channel, anycast_address) - proxy = self._bus.get_object(_NM_SERVICE, _NM_PATH) - network_manager = dbus.Interface(proxy, _NM_IFACE) - connection = self._make_connection(channel, anycast_address) - - network_manager.ActivateConnection(network.SETTINGS_SERVICE, - connection.path, - self.mesh_device.object_path, - self.mesh_device.object_path, - reply_handler=self.__activate_reply_cb, - error_handler=self.__activate_error_cb) + network.add_connection(settings, + reply_handler=self._add_connection_reply_cb, + error_handler=self._add_connection_err_cb) + + def _find_connection(self, channel, xs_hosted): + connection_id = self._get_connection_id(channel, xs_hosted) + return network.find_connection_by_id(connection_id) + + def _ensure_connection_exists(self, channel, xs_hosted): + if not self._find_connection(channel, xs_hosted): + self._add_connection(channel, xs_hosted) + + def _activate_connection(self, channel, xs_hosted): + connection = self._find_connection(channel, xs_hosted) + if connection: + connection.activate(self.mesh_device.object_path) + else: + logging.warning("Could not find mesh connection") def _try_next_connection_from_queue(self): if len(self._connection_queue) == 0: return - channel, anycast = self._connection_queue.pop() - self._activate_connection(channel, anycast) + channel, xs_hosted = self._connection_queue.pop() + self._activate_connection(channel, xs_hosted) def _empty_connection_queue(self): self._connection_queue = [] @@ -196,8 +212,8 @@ class OlpcMeshManager(object): """Activate a mesh connection on a user-specified channel. Looks for XS first, then resorts to simple mesh.""" self._empty_connection_queue() - self._connection_queue.append((channel, None)) - self._connection_queue.append((channel, _XS_ANYCAST)) + self._connection_queue.append((channel, False)) + self._connection_queue.append((channel, True)) self._try_next_connection_from_queue() def _start_automesh(self): @@ -205,8 +221,8 @@ class OlpcMeshManager(object): networks to connect to. First looks for XS on all channels, then falls back to simple mesh on channel 1.""" self._empty_connection_queue() - self._connection_queue.append((1, None)) - self._connection_queue.append((11, _XS_ANYCAST)) - self._connection_queue.append((6, _XS_ANYCAST)) - self._connection_queue.append((1, _XS_ANYCAST)) + self._connection_queue.append((1, False)) + self._connection_queue.append((11, True)) + self._connection_queue.append((6, True)) + self._connection_queue.append((1, True)) self._try_next_connection_from_queue() |