Ticket #1610: adhoc_default_networks_2306-2.patch

File adhoc_default_networks_2306-2.patch, 37.7 KB (added by erikos, 14 years ago)

Fixed another little bug

  • extensions/deviceicon/network.py

    diff --git a/extensions/deviceicon/network.py b/extensions/deviceicon/network.py
    index 202c563..ba5bae5 100644
    a b _GSM_STATE_CONNECTING = 2 
    6464_GSM_STATE_CONNECTED = 3
    6565_GSM_STATE_NEED_AUTH = 4
    6666
    67 def frequency_to_channel(frequency):
    68     ftoc = { 2412: 1, 2417: 2, 2422: 3, 2427: 4,
    69              2432: 5, 2437: 6, 2442: 7, 2447: 8,
    70              2452: 9, 2457: 10, 2462: 11, 2467: 12,
    71              2472: 13}
    72     return ftoc[frequency]
    73 
    7467class WirelessPalette(Palette):
    7568    __gtype_name__ = 'SugarWirelessPalette'
    7669
    7770    __gsignals__ = {
    7871        'deactivate-connection' : (gobject.SIGNAL_RUN_FIRST,
    79                                    gobject.TYPE_NONE, ([])),
    80         'create-connection'     : (gobject.SIGNAL_RUN_FIRST,
    81                                    gobject.TYPE_NONE, ([])),
     72                                   gobject.TYPE_NONE, ([]))
    8273    }
    8374
    84     def __init__(self, primary_text, can_create=True):
     75    def __init__(self, primary_text):
    8576        Palette.__init__(self, label=primary_text)
    8677
    8778        self._disconnect_item = None
    class WirelessPalette(Palette): 
    112103        self._disconnect_item.connect('activate', self.__disconnect_activate_cb)
    113104        self.menu.append(self._disconnect_item)
    114105
    115         if can_create:
    116             self._adhoc_item = gtk.MenuItem(_('Create new wireless network'))
    117             self._adhoc_item.connect('activate', self.__adhoc_activate_cb)
    118             self.menu.append(self._adhoc_item)
    119             self._adhoc_item.show()
    120 
    121106    def set_connecting(self):
    122107        self.props.secondary_text = _('Connecting...')
    123108
    class WirelessPalette(Palette): 
    144129    def __disconnect_activate_cb(self, menuitem):
    145130        self.emit('deactivate-connection')
    146131
    147     def __adhoc_activate_cb(self, menuitem):
    148         self.emit('create-connection')
    149 
    150132    def _set_frequency(self, frequency):
    151133        try:
    152             channel = frequency_to_channel(frequency)
     134            channel = network.frequency_to_channel(frequency)
    153135        except KeyError:
    154136            channel = 0
    155137        self._set_channel(channel)
    class GsmPalette(Palette): 
    312294
    313295class WirelessDeviceView(ToolButton):
    314296
    315     _ICON_NAME = 'network-wireless'
    316297    FRAME_POSITION_RELATIVE = 302
    317298
    318299    def __init__(self, device):
    class WirelessDeviceView(ToolButton): 
    331312        self._active_ap_op = None
    332313
    333314        self._icon = PulsingIcon()
    334         self._icon.props.icon_name = get_icon_state(self._ICON_NAME, 0)
     315        self._icon.props.icon_name = get_icon_state('network-wireless', 0)
    335316        self._inactive_color = xocolor.XoColor( \
    336317            "%s,%s" % (style.COLOR_BUTTON_GREY.get_svg(),
    337318                       style.COLOR_TRANSPARENT.get_svg()))
    class WirelessDeviceView(ToolButton): 
    345326        self._palette = WirelessPalette(self._name)
    346327        self._palette.connect('deactivate-connection',
    347328                              self.__deactivate_connection_cb)
    348         self._palette.connect('create-connection',
    349                               self.__create_connection_cb)
    350329        self.set_palette(self._palette)
    351330        self._palette.set_group_id('frame')
    352331
    class WirelessDeviceView(ToolButton): 
    415394    def __ap_properties_changed_cb(self, properties):
    416395        self._update_properties(properties)
    417396
    418     def _name_encodes_colors(self):
    419         """Match #XXXXXX,#YYYYYY at the end of the network name"""
    420         return self._name[-7] == '#' and self._name[-8] == ',' \
    421             and self._name[-15] == '#'
    422 
    423397    def _update_properties(self, properties):
    424398        if 'Mode' in properties:
    425399            self._mode = properties['Mode']
    class WirelessDeviceView(ToolButton): 
    435409            self._frequency = properties['Frequency']
    436410
    437411        if self._color == None:
    438             if self._mode == network.NM_802_11_MODE_ADHOC \
    439                     and self._name_encodes_colors():
    440                 encoded_color = self._name.split("#", 1)
    441                 if len(encoded_color) == 2:
    442                     self._color = xocolor.XoColor('#' + encoded_color[1])
     412            if self._mode == network.NM_802_11_MODE_ADHOC and \
     413                    self._name.startswith('Ad-hoc Network'):
     414                self._color = profile.get_color()
    443415            else:
    444416                sh = sha.new()
    445417                data = self._name + hex(self._flags)
    class WirelessDeviceView(ToolButton): 
    475447        else:
    476448            state = network.DEVICE_STATE_UNKNOWN
    477449
    478         if state == network.DEVICE_STATE_ACTIVATED:
    479             icon_name = '%s-connected' % self._ICON_NAME
    480         else:
    481             icon_name = self._ICON_NAME
     450        if self._mode != network.NM_802_11_MODE_ADHOC and \
     451                self._name.startswith('Ad-hoc Network') == False:
     452            if state == network.DEVICE_STATE_ACTIVATED:
     453                icon_name = '%s-connected' % 'network-wireless'
     454            else:
     455                icon_name = 'network-wireless'
    482456
    483         icon_name = get_icon_state(icon_name, self._strength)
    484         if icon_name:
    485             self._icon.props.icon_name = icon_name
     457            icon_name = get_icon_state(icon_name, self._strength)
     458            if icon_name:
     459                self._icon.props.icon_name = icon_name
     460        else:
     461            try:
     462                channel = network.frequency_to_channel(self._frequency)
     463            except KeyError:
     464                channel = 1
     465            if state == network.DEVICE_STATE_ACTIVATED:
     466                self._icon.props.icon_name = 'network-adhoc-%s-connected' \
     467                        % channel
     468            else:
     469                self._icon.props.icon_name = 'network-adhoc-%s' % channel
     470            self._icon.props.base_color = profile.get_color()
    486471
    487472        if state == network.DEVICE_STATE_PREPARE or \
    488473           state == network.DEVICE_STATE_CONFIG or \
    class WirelessDeviceView(ToolButton): 
    526511                    netmgr.DeactivateConnection(conn_o)
    527512                    break
    528513
    529     def __create_connection_cb(self, palette, data=None):
    530         """Create an 802.11 IBSS network.
    531 
    532         The user's color is encoded at the end of the network name. The network
    533         name is truncated so that it does not exceed the 32 byte SSID limit.
    534         """
    535         client = gconf.client_get_default()
    536         nick = client.get_string('/desktop/sugar/user/nick').decode('utf-8')
    537         color = client.get_string('/desktop/sugar/user/color')
    538         color_suffix = ' %s' % color
    539 
    540         format = _('%s\'s network').encode('utf-8')
    541         extra_length = (len(format) - len('%s')) + len(color_suffix)
    542         name_limit = 32 - extra_length
    543 
    544         # truncate the nick and use a regex to drop any partial characters
    545         # at the end
    546         nick = nick.encode('utf-8')[:name_limit]
    547         pattern = "([\xf6-\xf7][\x80-\xbf]{0,2}|[\xe0-\xef][\x80-\xbf]{0,1}|[\xc0-\xdf])$"
    548         nick = re.sub(pattern, '', nick)
    549 
    550         connection_name = format % nick
    551         connection_name += color_suffix
    552 
    553         connection = network.find_connection_by_ssid(connection_name)
    554         if connection is None:
    555             settings = Settings()
    556             settings.connection.id = 'Auto ' + connection_name
    557             uuid = settings.connection.uuid = unique_id()
    558             settings.connection.type = '802-11-wireless'
    559             settings.wireless.ssid = dbus.ByteArray(connection_name)
    560             settings.wireless.band = 'bg'
    561             settings.wireless.mode = 'adhoc'
    562             settings.ip4_config = IP4Config()
    563             settings.ip4_config.method = 'link-local'
    564 
    565             connection = network.add_connection(uuid, settings)
    566 
    567         obj = self._bus.get_object(_NM_SERVICE, _NM_PATH)
    568         netmgr = dbus.Interface(obj, _NM_IFACE)
    569 
    570         netmgr.ActivateConnection(network.SETTINGS_SERVICE,
    571                                   connection.path,
    572                                   self._device.object_path,
    573                                   '/',
    574                                   reply_handler=self.__activate_reply_cb,
    575                                   error_handler=self.__activate_error_cb)
    576 
    577514    def __activate_reply_cb(self, connection):
    578515        logging.debug('Network created: %s', connection)
    579516
  • src/jarabe/desktop/meshbox.py

    diff --git a/src/jarabe/desktop/meshbox.py b/src/jarabe/desktop/meshbox.py
    index 29a9cf1..f88f912 100644
    a b  
    11# Copyright (C) 2006-2007 Red Hat, Inc.
    22# Copyright (C) 2009 Tomeu Vizoso, Simon Schampijer
    3 # Copyright (C) 2009 One Laptop per Child
     3# Copyright (C) 2009-2010 One Laptop per Child
    44#
    55# This program is free software; you can redistribute it and/or modify
    66# it under the terms of the GNU General Public License as published by
    from jarabe.model.network import Settings 
    5252from jarabe.model.network import IP4Config
    5353from jarabe.model.network import WirelessSecurity
    5454from jarabe.model.network import AccessPoint
    55 from jarabe.model.network import OlpcMesh as OlpcMeshSettings
    5655from jarabe.model.olpcmesh import OlpcMeshManager
     56from jarabe.model.adhoc import AdHocManager
    5757
    5858_NM_SERVICE = 'org.freedesktop.NetworkManager'
    5959_NM_IFACE = 'org.freedesktop.NetworkManager'
    class WirelessNetworkView(CanvasPulsingIcon): 
    8989        self._device_state = None
    9090        self._color = None
    9191
    92         if self._mode == network.NM_802_11_MODE_ADHOC \
    93                 and self._name_encodes_colors():
    94             encoded_color = self._name.split("#", 1)
    95             if len(encoded_color) == 2:
    96                 self._color = xocolor.XoColor('#' + encoded_color[1])
     92        if self._mode == network.NM_802_11_MODE_ADHOC and \
     93                self._name.startswith('Ad-hoc Network'):
     94            self._color = profile.get_color()
    9795        else:
    9896            sh = sha.new()
    9997            data = self._name + hex(self._flags)
    class WirelessNetworkView(CanvasPulsingIcon): 
    137135                                      path=self._device.object_path,
    138136                                      dbus_interface=_NM_WIRELESS_IFACE)
    139137
    140     def _name_encodes_colors(self):
    141         """Match #XXXXXX,#YYYYYY at the end of the network name"""
    142         return self._name[-7] == '#' and self._name[-8] == ',' \
    143             and self._name[-15] == '#'
    144 
    145138    def _create_palette(self):
    146139        icon_name = get_icon_state(_AP_ICON_NAME, self._strength)
    147140        self._palette_icon = Icon(icon_name=icon_name,
    class WirelessNetworkView(CanvasPulsingIcon): 
    214207        else:
    215208            state = network.DEVICE_STATE_UNKNOWN
    216209
    217         if state == network.DEVICE_STATE_ACTIVATED:
    218             connection = network.find_connection_by_ssid(self._name)
    219             if connection:
    220                 if self._mode == network.NM_802_11_MODE_INFRA:
    221                     connection.set_connected()
    222 
    223             icon_name = '%s-connected' % _AP_ICON_NAME
    224         else:
    225             icon_name = _AP_ICON_NAME
    226 
    227         icon_name = get_icon_state(icon_name, self._strength)
    228         if icon_name:
     210        if self._mode == network.NM_802_11_MODE_ADHOC and \
     211                self._name.startswith('Ad-hoc Network'):
     212            channel = max([1] + [ap.channel for ap in
     213                                      self._access_points.values()])
     214            if state == network.DEVICE_STATE_ACTIVATED:
     215                icon_name = 'network-adhoc-%s-connected' % channel
     216            else:
     217                icon_name = 'network-adhoc-%s' % channel
    229218            self.props.icon_name = icon_name
    230219            icon = self._palette.props.icon
    231220            icon.props.icon_name = icon_name
     221        else:
     222            if state == network.DEVICE_STATE_ACTIVATED:
     223                connection = network.find_connection_by_ssid(self._name)
     224                if connection:
     225                    if self._mode == network.NM_802_11_MODE_INFRA:
     226                        connection.set_connected()
     227                icon_name = '%s-connected' % _AP_ICON_NAME
     228            else:
     229                icon_name = _AP_ICON_NAME
     230
     231            icon_name = get_icon_state(icon_name, self._strength)
     232            if icon_name:
     233                self.props.icon_name = icon_name
     234                icon = self._palette.props.icon
     235                icon.props.icon_name = icon_name
    232236
    233237        if state == network.DEVICE_STATE_PREPARE or \
    234238           state == network.DEVICE_STATE_CONFIG or \
    class WirelessNetworkView(CanvasPulsingIcon): 
    260264            self.props.base_color = self._color
    261265
    262266    def _update_badge(self):
    263         if network.find_connection_by_ssid(self._name) is not None:
    264             self.props.badge_name = "emblem-favorite"
    265             self._palette_icon.props.badge_name = "emblem-favorite"
    266         elif self._flags == network.NM_802_11_AP_FLAGS_PRIVACY:
    267             self.props.badge_name = "emblem-locked"
    268             self._palette_icon.props.badge_name = "emblem-locked"
     267        if self._mode != network.NM_802_11_MODE_ADHOC:
     268            if network.find_connection_by_ssid(self._name) is not None:
     269                self.props.badge_name = "emblem-favorite"
     270                self._palette_icon.props.badge_name = "emblem-favorite"
     271            elif self._flags == network.NM_802_11_AP_FLAGS_PRIVACY:
     272                self.props.badge_name = "emblem-locked"
     273                self._palette_icon.props.badge_name = "emblem-locked"
     274            else:
     275                self.props.badge_name = None
     276                self._palette_icon.props.badge_name = None
    269277        else:
    270278            self.props.badge_name = None
    271279            self._palette_icon.props.badge_name = None
    class WirelessNetworkView(CanvasPulsingIcon): 
    469477                                         dbus_interface=_NM_WIRELESS_IFACE)
    470478
    471479
     480class AdHocView(CanvasPulsingIcon):
     481    def __init__(self, manager, channel):
     482        CanvasPulsingIcon.__init__(self,
     483                                   icon_name='network-adhoc-%s' % channel,
     484                                   size=style.STANDARD_ICON_SIZE, cache=True)
     485        self._bus = dbus.SystemBus()
     486        self._manager = manager
     487        self._device = manager.device
     488        self._channel = channel
     489        self._icon_name = 'network-adhoc-%s' % self._channel
     490        self._disconnect_item = None
     491        self._connect_item = None
     492        self._palette_icon = None
     493        self._greyed_out = False
     494        self._name = "Ad-hoc Network %d" % channel
     495        self._device_state = None
     496        self._connection = None
     497        self._active = False
     498
     499        self.connect('button-release-event', self.__button_release_event_cb)
     500
     501        interface_props = dbus.Interface(self._device,
     502                                         'org.freedesktop.DBus.Properties')
     503        interface_props.Get(_NM_DEVICE_IFACE, 'State',
     504                            reply_handler=self.__get_device_state_reply_cb,
     505                            error_handler=self.__get_device_state_error_cb)
     506
     507        self._bus.add_signal_receiver(self.__device_state_changed_cb,
     508                                      signal_name='StateChanged',
     509                                      path=self._device.object_path,
     510                                      dbus_interface=_NM_DEVICE_IFACE)
     511        self._bus.add_signal_receiver(self.__wireless_properties_changed_cb,
     512                                      signal_name='PropertiesChanged',
     513                                      path=self._device.object_path,
     514                                      dbus_interface=_NM_WIRELESS_IFACE)
     515
     516        pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(),
     517                                         style.COLOR_TRANSPARENT.get_svg()))
     518        self.props.pulse_color = pulse_color
     519        self._state_color = XoColor('%s,%s' % \
     520                                       (profile.get_color().get_stroke_color(),
     521                                        style.COLOR_TRANSPARENT.get_svg()))
     522        self.props.base_color = self._state_color
     523        self._palette = self._create_palette()
     524        self.set_palette(self._palette)
     525        self._palette_icon.props.xo_color = self._state_color
     526
     527    def _create_palette(self):
     528        self._palette_icon = Icon(icon_name=self._icon_name,
     529                                  icon_size=style.STANDARD_ICON_SIZE)
     530
     531        _palette = palette.Palette(_("Ad-hoc Network %d") % self._channel,
     532                                   icon=self._palette_icon)
     533
     534        self._connect_item = MenuItem(_('Connect'), 'dialog-ok')
     535        self._connect_item.connect('activate', self.__connect_activate_cb)
     536        _palette.menu.append(self._connect_item)
     537
     538        self._disconnect_item = MenuItem(_('Disconnect'), 'media-eject')
     539        self._disconnect_item.connect('activate',
     540                                      self.__disconnect_activate_cb)
     541        _palette.menu.append(self._disconnect_item)
     542
     543        return _palette
     544
     545    def __button_release_event_cb(self, icon, event):
     546        self._manager.activate_channel(self._channel)
     547
     548    def __connect_activate_cb(self, icon):
     549        self._manager.activate_channel(self._channel)
     550
     551    def __disconnect_activate_cb(self, icon):
     552        obj = self._bus.get_object(_NM_SERVICE, _NM_PATH)
     553        netmgr = dbus.Interface(obj, _NM_IFACE)
     554
     555        netmgr_props = dbus.Interface(netmgr, dbus.PROPERTIES_IFACE)
     556        active_connections_o = netmgr_props.Get(_NM_IFACE, 'ActiveConnections')
     557
     558        for conn_o in active_connections_o:
     559            obj = self._bus.get_object(_NM_IFACE, conn_o)
     560            props = dbus.Interface(obj, dbus.PROPERTIES_IFACE)
     561            state = props.Get(_NM_ACTIVE_CONN_IFACE, 'State')
     562            if state == network.NM_ACTIVE_CONNECTION_STATE_ACTIVATED:
     563                ap_o = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject')
     564                if ap_o != '/':
     565                    netmgr.DeactivateConnection(conn_o)
     566
     567    def __get_device_state_reply_cb(self, state):
     568        self._device_state = state
     569        self._update()
     570
     571    def __get_device_state_error_cb(self, err):
     572        logging.error('Error getting the device state: %s', err)
     573
     574    def __device_state_changed_cb(self, new_state, old_state, reason):
     575        self._device_state = new_state
     576        self._update()
     577
     578    def __wireless_properties_changed_cb(self, properties):
     579        if 'ActiveAccessPoint' in properties and \
     580                properties['ActiveAccessPoint'] is not '/':
     581            active_ap = self._bus.get_object(_NM_SERVICE,
     582                                             properties['ActiveAccessPoint'])
     583            props = dbus.Interface(active_ap, dbus.PROPERTIES_IFACE)
     584
     585            props.GetAll(_NM_ACCESSPOINT_IFACE, byte_arrays=True,
     586                         reply_handler=self.__get_all_ap_props_reply_cb,
     587                         error_handler=self.__get_all_ap_props_error_cb)
     588
     589    def __get_all_ap_props_reply_cb(self, properties):
     590        if properties['Mode'] == network.NM_802_11_MODE_ADHOC:
     591            channel = network.frequency_to_channel(properties['Frequency'])
     592            if self._channel == channel:
     593                self._active = True
     594            else:
     595                self._active = False
     596        else:
     597            self._active = False
     598        self._update()
     599
     600    def __get_all_ap_props_error_cb(self, err):
     601        logging.error('Error getting the access point properties: %s', err)
     602
     603    def _update(self):
     604        if self._active:
     605            state = self._device_state
     606        else:
     607            state = network.DEVICE_STATE_UNKNOWN
     608
     609        if state == network.DEVICE_STATE_ACTIVATED:
     610            icon_name = '%s-connected' % self._icon_name
     611        else:
     612            icon_name = self._icon_name
     613
     614        self.props.base_color = self._state_color
     615        self._palette_icon.props.xo_color = self._state_color
     616
     617        if icon_name is not None:
     618            self.props.icon_name = icon_name
     619            icon = self._palette.props.icon
     620            icon.props.icon_name = icon_name
     621
     622        if state in [network.DEVICE_STATE_PREPARE,
     623                     network.DEVICE_STATE_CONFIG,
     624                     network.DEVICE_STATE_NEED_AUTH,
     625                     network.DEVICE_STATE_IP_CONFIG]:
     626            if self._disconnect_item:
     627                self._disconnect_item.show()
     628            self._connect_item.hide()
     629            self._palette.props.secondary_text = _('Connecting...')
     630            self.props.pulsing = True
     631        elif state == network.DEVICE_STATE_ACTIVATED:
     632            if self._disconnect_item:
     633                self._disconnect_item.show()
     634            self._connect_item.hide()
     635            self._palette.props.secondary_text = _('Connected')
     636            self.props.pulsing = False
     637        else:
     638            if self._disconnect_item:
     639                self._disconnect_item.hide()
     640            self._connect_item.show()
     641            self._palette.props.secondary_text = None
     642            self.props.pulsing = False
     643
     644    def _update_color(self):
     645        if self._greyed_out:
     646            self.props.base_color = XoColor('#D5D5D5,#D5D5D5')
     647        else:
     648            self.props.base_color = self._state_color
     649
     650    def indicate_population(self, state):
     651        if state == True:
     652            self._state_color = profile.get_color()
     653            self.props.base_color = self._state_color
     654            self._palette_icon.props.xo_color = self._state_color
     655        else:
     656            color = '%s,%s' % (profile.get_color().get_stroke_color(),
     657                               style.COLOR_TRANSPARENT.get_svg())
     658            self._state_color = XoColor(color)
     659            self.props.base_color = self._state_color
     660            self._palette_icon.props.xo_color = self._state_color
     661
     662    def set_filter(self, query):
     663        self._greyed_out = self._name.lower().find(query) == -1
     664        self._update_color()
     665
     666    def disconnect(self):
     667        self._bus.remove_signal_receiver(self.__device_state_changed_cb,
     668                                         signal_name='StateChanged',
     669                                         path=self._device.object_path,
     670                                         dbus_interface=_NM_DEVICE_IFACE)
     671        self._bus.remove_signal_receiver(self.__wireless_properties_changed_cb,
     672                                         signal_name='PropertiesChanged',
     673                                         path=self._device.object_path,
     674                                         dbus_interface=_NM_WIRELESS_IFACE)
     675
    472676class OlpcMeshView(CanvasPulsingIcon):
    473677    def __init__(self, mesh_mgr, channel):
    474678        CanvasPulsingIcon.__init__(self, icon_name=_OLPC_MESH_ICON_NAME,
    class NetworkManagerObserver(object): 
    8461050        self._bus = dbus.SystemBus()
    8471051        self._devices = {}
    8481052        self._netmgr = None
     1053        self._has_mesh_device = False
     1054        self._check_mesh_source = 0
    8491055
    8501056    def listen(self):
    8511057        try:
    class NetworkManagerObserver(object): 
    8641070        self._bus.add_signal_receiver(self.__device_removed_cb,
    8651071                                      signal_name='DeviceRemoved',
    8661072                                      dbus_interface=_NM_IFACE)
     1073        self._bus.add_signal_receiver(self.__properties_changed_cb,
     1074                                      signal_name='PropertiesChanged',
     1075                                      dbus_interface=_NM_IFACE)
    8671076
    8681077        settings = network.get_settings()
    8691078        if settings is not None:
    class NetworkManagerObserver(object): 
    9071116        device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType')
    9081117        if device_type == network.DEVICE_TYPE_802_11_WIRELESS:
    9091118            self._devices[device_o] = DeviceObserver(self._box, device)
     1119            if self._check_mesh_source != 0:
     1120                gobject.source_remove(self._check_mesh_source)
     1121            self._check_mesh_source = gobject.timeout_add( \
     1122                    5, self._add_adhoc_networks, device)
    9101123        elif device_type == network.DEVICE_TYPE_802_11_OLPC_MESH:
     1124            self._has_mesh_device = True
    9111125            self._box.enable_olpc_mesh(device)
    9121126
    9131127    def _get_device_path_error_cb(self, err):
    class NetworkManagerObserver(object): 
    9211135            observer = self._devices[device_o]
    9221136            observer.disconnect()
    9231137            del self._devices[device_o]
     1138            if self._has_mesh_device == False:
     1139                self._box.remove_adhoc_networks()
    9241140            return
    9251141
    9261142        device = self._bus.get_object(_NM_SERVICE, device_o)
    class NetworkManagerObserver(object): 
    9291145        if device_type == network.DEVICE_TYPE_802_11_OLPC_MESH:
    9301146            self._box.disable_olpc_mesh(device)
    9311147
     1148    def _add_adhoc_networks(self, device):
     1149        """If we do not find mesh hardware we create Ad-hoc networks."""
     1150        if self._has_mesh_device == False:
     1151            self._box.add_adhoc_networks(device)
     1152        return False
     1153
     1154    def __properties_changed_cb(self, properties):
     1155        if 'WirelessHardwareEnabled' in properties:
     1156            if properties['WirelessHardwareEnabled'] == False:
     1157                if self._has_mesh_device == False:
     1158                    self._box.remove_adhoc_networks()
     1159            if properties['WirelessHardwareEnabled'] == True:
     1160                for device in self._devices:
     1161                    if self._has_mesh_device == False:
     1162                        self._box.add_adhoc_networks(device)
    9321163
    9331164class MeshBox(gtk.VBox):
    9341165    __gtype_name__ = 'SugarMeshBox'
    class MeshBox(gtk.VBox): 
    9391170        gobject.GObject.__init__(self)
    9401171
    9411172        self.wireless_networks = {}
     1173        self._adhoc_manager = None
    9421174
    9431175        self._model = neighborhood.get_model()
    9441176        self._buddies = {}
    class MeshBox(gtk.VBox): 
    9481180        self._suspended = True
    9491181        self._query = ''
    9501182        self._owner_icon = None
    951            
     1183
    9521184        self._toolbar = MeshToolbar()
    9531185        self._toolbar.connect('query-changed', self._toolbar_query_changed_cb)
    9541186        self.pack_start(self._toolbar, expand=False)
    class MeshBox(gtk.VBox): 
    10961328            ap.disconnect()
    10971329            return
    10981330
     1331        if self._adhoc_manager != None and \
     1332                ap.name.startswith('Ad-hoc Network') and \
     1333                ap.mode == network.NM_802_11_MODE_ADHOC:
     1334
     1335            if old_hash is None: # new Ad-hoc network finished initializing
     1336                self._adhoc_manager.add_access_point(ap)
     1337            # we are called as well in other cases but we do not need to
     1338            # act here as we don't display signal strength for Ad-hoc networks
     1339            return
     1340
    10991341        if old_hash is None: # new AP finished initializing
    11001342            self._add_ap_to_network(ap)
    11011343            return
    class MeshBox(gtk.VBox): 
    11181360        ap.initialize()
    11191361
    11201362    def remove_access_point(self, ap_o):
     1363        if self._adhoc_manager is not None:
     1364            if self._adhoc_manager.remove_access_point(ap_o) == True:
     1365                return
     1366
    11211367        # we don't keep an index of ap object path to network, but since
    11221368        # we'll only ever have a handful of networks, just try them all...
    11231369        for net in self.wireless_networks.values():
    class MeshBox(gtk.VBox): 
    11341380        # it (e.g. olpc-mesh adhoc network)
    11351381        logging.debug('Can not remove access point %s' % ap_o)
    11361382
     1383    def add_adhoc_networks(self, device):
     1384        if self._adhoc_manager is None:
     1385            self._adhoc_manager = AdHocManager(device)
     1386        for channel in self._adhoc_manager.channels:
     1387            self._add_adhoc_network_icon(self._adhoc_manager, channel)
     1388
     1389    def remove_adhoc_networks(self):
     1390        for channel in self._adhoc_manger.channels:
     1391            icon = self._adhoc_manager.remove_network(channel)
     1392            if icon is not None:
     1393                icon.disconnect()
     1394                self._layout.remove(icon)
     1395
     1396    def _add_adhoc_network_icon(self, adhoc_manager, channel):
     1397        icon = AdHocView(adhoc_manager, channel)
     1398        self._layout.add(icon)
     1399        self._adhoc_manager.add_network(channel, icon)
     1400
    11371401    def _add_olpc_mesh_icon(self, mesh_mgr, channel):
    11381402        icon = OlpcMeshView(mesh_mgr, channel)
    11391403        self._layout.add(icon)
  • src/jarabe/model/Makefile.am

    diff --git a/src/jarabe/model/Makefile.am b/src/jarabe/model/Makefile.am
    index 18d44da..1df2cde 100644
    a b  
    11sugardir = $(pythondir)/jarabe/model
    22sugar_PYTHON =                  \
     3        adhoc.py                \
    34        __init__.py             \
    45        buddy.py                \
    56        bundleregistry.py       \
  • new file src/jarabe/model/adhoc.py

    diff --git a/src/jarabe/model/adhoc.py b/src/jarabe/model/adhoc.py
    new file mode 100644
    index 0000000..2afc321
    - +  
     1# Copyright (C) 2010 One Laptop per Child
     2#
     3# This program is free software; you can redistribute it and/or modify
     4# it under the terms of the GNU General Public License as published by
     5# the Free Software Foundation; either version 2 of the License, or
     6# (at your option) any later version.
     7#
     8# This program is distributed in the hope that it will be useful,
     9# but WITHOUT ANY WARRANTY; without even the implied warranty of
     10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11# GNU General Public License for more details.
     12#
     13# You should have received a copy of the GNU General Public License
     14# along with this program; if not, write to the Free Software
     15# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     16
     17import logging
     18
     19import dbus
     20import gobject
     21
     22from jarabe.model import network
     23from jarabe.model.network import Settings
     24from sugar.util import unique_id
     25from jarabe.model.network import IP4Config
     26
     27_NM_SERVICE = 'org.freedesktop.NetworkManager'
     28_NM_IFACE = 'org.freedesktop.NetworkManager'
     29_NM_PATH = '/org/freedesktop/NetworkManager'
     30_NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device'
     31_NM_OLPC_MESH_IFACE = 'org.freedesktop.NetworkManager.Device.OlpcMesh'
     32
     33
     34class Network(object):
     35    """Representation of an Ad-hoc network"""
     36
     37    def __init__(self, icon, access_point):
     38        self.icon = icon
     39        self.access_point = access_point
     40
     41
     42class AdHocManager(object):
     43    """To mimic the mesh behavior on devices where mesh hardware is
     44    not available we support the creation of an Ad-hoc network on
     45    three channels 1, 6, 11. If Sugar sees no "known" network when it
     46    starts, it does autoconnect to an Ad-hoc network.
     47
     48    """
     49
     50    timeout = 30
     51
     52    def __init__(self, device):
     53        self._bus = dbus.SystemBus()
     54
     55        self.device = device
     56        self._idle_source = 0
     57        self._device_state = network.DEVICE_STATE_UNKNOWN
     58
     59        self.channels = [1, 6, 11]
     60        self._networks = {}
     61
     62        props = dbus.Interface(device,
     63                                   'org.freedesktop.DBus.Properties')
     64        props.Get(_NM_DEVICE_IFACE, 'State',
     65                  reply_handler=self.__get_device_state_reply_cb,
     66                  error_handler=self.__get_state_error_cb)
     67
     68        self._bus.add_signal_receiver(self.__device_state_changed_cb,
     69                                      signal_name='StateChanged',
     70                                      path=self.device.object_path,
     71                                      dbus_interface=_NM_DEVICE_IFACE)
     72
     73        if self._have_configured_connections():
     74            self._autoconnect_adhoc_timer()
     75        else:
     76            self._autoconnect_adhoc()
     77
     78    def _have_configured_connections(self):
     79        return len(network.get_settings().connections) > 0
     80
     81    def __get_state_error_cb(self, err):
     82        logging.debug('Error getting the device state: %s', err)
     83
     84    def __get_device_state_reply_cb(self, state):
     85        self._device_state = state
     86
     87    def __device_state_changed_cb(self, new_state, old_state, reason):
     88        self._device_state = new_state
     89
     90    def _autoconnect_adhoc_timer(self):
     91        """Start a timer which basically looks for 30 seconds of inactivity
     92        on the device, then does autoconnect to an Ad-hoc network.
     93
     94        """
     95        if self._idle_source != 0:
     96            gobject.source_remove(self._idle_source)
     97        self._idle_source = gobject.timeout_add_seconds(self.timeout,
     98                                                        self._idle_check)
     99
     100    def _autoconnect_adhoc(self):
     101        """First we try if there is an Ad-hoc network that is used by other
     102        learners in the area, if not we default to channel 1.
     103
     104        """
     105        if self._networks[1].access_point is not None:
     106            self._connect(1)
     107        elif self._networks[6].access_point is not None:
     108            self._connect(6)
     109        elif self._networks[11].access_point is not None:
     110            self._connect(11)
     111        else:
     112            self._connect(1)
     113
     114    def _idle_check(self):
     115        if  self._device_state == network.DEVICE_STATE_DISCONNECTED:
     116            logging.debug("Connect to Ad-hoc network due to inactivity.")
     117            self._autoconnect_adhoc()
     118        return False
     119
     120    def activate_channel(self, channel):
     121        self._connect(channel)
     122
     123    def _connect(self, channel):
     124        name = "Ad-hoc Network %d" % channel
     125        connection = network.find_connection_by_ssid(name)
     126        if connection is None:
     127            settings = Settings()
     128            settings.connection.id = name
     129            settings.connection.uuid = unique_id()
     130            settings.connection.type = '802-11-wireless'
     131            settings.wireless.ssid = dbus.ByteArray(name)
     132            settings.wireless.band = 'bg'
     133            settings.wireless.channel = channel
     134            settings.wireless.mode = 'adhoc'
     135            settings.ip4_config = IP4Config()
     136            settings.ip4_config.method = 'link-local'
     137
     138            connection = network.add_connection(name, settings)
     139
     140        obj = self._bus.get_object(_NM_SERVICE, _NM_PATH)
     141        netmgr = dbus.Interface(obj, _NM_IFACE)
     142
     143        netmgr.ActivateConnection(network.SETTINGS_SERVICE,
     144                                  connection.path,
     145                                  self.device.object_path,
     146                                  '/',
     147                                  reply_handler=self.__activate_reply_cb,
     148                                  error_handler=self.__activate_error_cb)
     149
     150    def __activate_reply_cb(self, connection):
     151        logging.debug('Ad-hoc network created: %s', connection)
     152
     153    def __activate_error_cb(self, err):
     154        logging.debug('Failed to create Ad-hoc network: %s', err)
     155
     156    def add_network(self, channel, icon):
     157        if channel not in self._networks:
     158            self._networks[channel] = Network(icon, None)
     159
     160    def remove_network(self, channel):
     161        if channel in self._networks:
     162            net = self._networks.pop(channel)
     163            return net.icon
     164        return None
     165
     166    def add_access_point(self, access_point):
     167        """If a new adhoc network is announcd that is named like an Ad-hoc
     168        network we take this as an indication that other learners are
     169        using the network an indicate this.
     170
     171        """
     172        if ' 1' == access_point.name[-2:]:
     173            self._networks[1].icon.indicate_population(True)
     174            self._networks[1].access_point = access_point
     175        elif '6' == access_point.name[-1]:
     176            self._networks[6].icon.indicate_population(True)
     177            self._networks[6].access_point = access_point
     178        elif '11' == access_point.name[-2:]:
     179            self._networks[11].icon.indicate_population(True)
     180            self._networks[11].access_point = access_point
     181
     182    def remove_access_point(self, ap_object_path):
     183        """When the last user of the network goes away we remove
     184        the access point and indicate this.
     185
     186        """
     187        for net in self._networks.values():
     188            if net.access_point is not None:
     189                if net.access_point.model.object_path == ap_object_path:
     190                    net.icon.indicate_population(False)
     191                    net.access_point.disconnect()
     192                    net.access_point = None
     193                    return True
     194        return False
  • src/jarabe/model/network.py

    diff --git a/src/jarabe/model/network.py b/src/jarabe/model/network.py
    index 4389b87..dccd467 100644
    a b  
    11# Copyright (C) 2008 Red Hat, Inc.
    22# Copyright (C) 2009 Tomeu Vizoso, Simon Schampijer
    3 # Copyright (C) 2009 One Laptop per Child
     3# Copyright (C) 2009-2010 One Laptop per Child
    44# Copyright (C) 2009 Paraguay Educa, Martin Abente
    55#
    66# This program is free software; you can redistribute it and/or modify
    GSM_PUK_PATH = '/desktop/sugar/network/gsm/puk' 
    9898_nm_settings = None
    9999_conn_counter = 0
    100100
     101
     102def frequency_to_channel(frequency):
     103    ftoc = {2412: 1, 2417: 2, 2422: 3, 2427: 4,
     104            2432: 5, 2437: 6, 2442: 7, 2447: 8,
     105            2452: 9, 2457: 10, 2462: 11, 2467: 12,
     106            2472: 13}
     107    return ftoc[frequency]
     108
     109
    101110class WirelessSecurity(object):
    102111    def __init__(self):
    103112        self.key_mgmt = None
    class Wireless(object): 
    125134        self.security = None
    126135        self.mode = None
    127136        self.band = None
     137        self.channel = None
    128138
    129139    def get_dict(self):
    130140        wireless = {'ssid': self.ssid}
    class Wireless(object): 
    134144            wireless['mode'] = self.mode
    135145        if self.band:
    136146            wireless['band'] = self.band
     147        if self.channel:
     148            wireless['channel'] = self.channel
    137149        return wireless
    138150
    139151class OlpcMesh(object):
    class AccessPoint(gobject.GObject): 
    497509        self.wpa_flags = 0
    498510        self.rsn_flags = 0
    499511        self.mode = 0
     512        self.channel = 0
    500513
    501514    def initialize(self):
    502515        model_props = dbus.Interface(self.model, dbus.PROPERTIES_IFACE)
    class AccessPoint(gobject.GObject): 
    565578            self.rsn_flags = properties['RsnFlags']
    566579        if 'Mode' in properties:
    567580            self.mode = properties['Mode']
     581        if 'Frequency' in properties:
     582            try:
     583                self.channel = frequency_to_channel(properties['Frequency'])
     584            except KeyError:
     585                self.channel = 1
     586
    568587        self._initialized = True
    569588        self.emit('props-changed', old_hash)
    570589