Ticket #1610: 0001-adhoc-master.patch

File 0001-adhoc-master.patch, 37.3 KB (added by erikos, 12 years ago)

Patch against master

  • extensions/deviceicon/network.py

    diff --git a/extensions/deviceicon/network.py b/extensions/deviceicon/network.py
    index 94a4293..2e4d24c 100644
    a b _GSM_STATE_CONNECTING = 2 
    6565_GSM_STATE_CONNECTED = 3
    6666_GSM_STATE_NEED_AUTH = 4
    6767
    68 def frequency_to_channel(frequency):
    69     ftoc = { 2412: 1, 2417: 2, 2422: 3, 2427: 4,
    70              2432: 5, 2437: 6, 2442: 7, 2447: 8,
    71              2452: 9, 2457: 10, 2462: 11, 2467: 12,
    72              2472: 13}
    73     return ftoc[frequency]
    7468
    7569class WirelessPalette(Palette):
    7670    __gtype_name__ = 'SugarWirelessPalette'
    7771
    7872    __gsignals__ = {
    7973        'deactivate-connection' : (gobject.SIGNAL_RUN_FIRST,
    80                                    gobject.TYPE_NONE, ([])),
    81         'create-connection'     : (gobject.SIGNAL_RUN_FIRST,
    82                                    gobject.TYPE_NONE, ([])),
     74                                   gobject.TYPE_NONE, ([]))
    8375    }
    8476
    85     def __init__(self, primary_text, can_create=True):
     77    def __init__(self, primary_text):
    8678        Palette.__init__(self, label=primary_text)
    8779
    8880        self._disconnect_item = None
    class WirelessPalette(Palette): 
    113105        self._disconnect_item.connect('activate', self.__disconnect_activate_cb)
    114106        self.menu.append(self._disconnect_item)
    115107
    116         if can_create:
    117             self._adhoc_item = gtk.MenuItem(_('Create new wireless network'))
    118             self._adhoc_item.connect('activate', self.__adhoc_activate_cb)
    119             self.menu.append(self._adhoc_item)
    120             self._adhoc_item.show()
    121 
    122108    def set_connecting(self):
    123109        self.props.secondary_text = _('Connecting...')
    124110
    class WirelessPalette(Palette): 
    145131    def __disconnect_activate_cb(self, menuitem):
    146132        self.emit('deactivate-connection')
    147133
    148     def __adhoc_activate_cb(self, menuitem):
    149         self.emit('create-connection')
    150 
    151134    def _set_frequency(self, frequency):
    152135        try:
    153             channel = frequency_to_channel(frequency)
     136            channel = network.frequency_to_channel(frequency)
    154137        except KeyError:
    155138            channel = 0
    156139        self._set_channel(channel)
    class GsmPalette(Palette): 
    314297
    315298class WirelessDeviceView(ToolButton):
    316299
    317     _ICON_NAME = 'network-wireless'
    318300    FRAME_POSITION_RELATIVE = 302
    319301
    320302    def __init__(self, device):
    class WirelessDeviceView(ToolButton): 
    333315        self._active_ap_op = None
    334316
    335317        self._icon = PulsingIcon()
    336         self._icon.props.icon_name = get_icon_state(self._ICON_NAME, 0)
     318        self._icon.props.icon_name = get_icon_state('network-wireless', 0)
    337319        self._inactive_color = xocolor.XoColor( \
    338320            "%s,%s" % (style.COLOR_BUTTON_GREY.get_svg(),
    339321                       style.COLOR_TRANSPARENT.get_svg()))
    class WirelessDeviceView(ToolButton): 
    347329        self._palette = WirelessPalette(self._name)
    348330        self._palette.connect('deactivate-connection',
    349331                              self.__deactivate_connection_cb)
    350         self._palette.connect('create-connection',
    351                               self.__create_connection_cb)
    352332        self.set_palette(self._palette)
    353333        self._palette.set_group_id('frame')
    354334
    class WirelessDeviceView(ToolButton): 
    418398    def __ap_properties_changed_cb(self, properties):
    419399        self._update_properties(properties)
    420400
    421     def _name_encodes_colors(self):
    422         """Match #XXXXXX,#YYYYYY at the end of the network name"""
    423         return self._name[-7] == '#' and self._name[-8] == ',' \
    424             and self._name[-15] == '#'
    425 
    426401    def _update_properties(self, properties):
    427402        if 'Mode' in properties:
    428403            self._mode = properties['Mode']
    class WirelessDeviceView(ToolButton): 
    438413            self._frequency = properties['Frequency']
    439414
    440415        if self._color == None:
    441             if self._mode == network.NM_802_11_MODE_ADHOC \
    442                     and self._name_encodes_colors():
    443                 encoded_color = self._name.split("#", 1)
    444                 if len(encoded_color) == 2:
    445                     self._color = xocolor.XoColor('#' + encoded_color[1])
     416            if self._mode == network.NM_802_11_MODE_ADHOC and \
     417                    self._name.startswith('Ad-hoc Network'):
     418                self._color = profile.get_color()
    446419            else:
    447420                sha_hash = hashlib.sha1()
    448421                data = self._name + hex(self._flags)
    class WirelessDeviceView(ToolButton): 
    478451        else:
    479452            state = network.DEVICE_STATE_UNKNOWN
    480453
    481         if state == network.DEVICE_STATE_ACTIVATED:
    482             icon_name = '%s-connected' % self._ICON_NAME
    483         else:
    484             icon_name = self._ICON_NAME
     454        if self._mode != network.NM_802_11_MODE_ADHOC and \
     455                self._name.startswith('Ad-hoc Network') == False:
     456            if state == network.DEVICE_STATE_ACTIVATED:
     457                icon_name = '%s-connected' % 'network-wireless'
     458            else:
     459                icon_name = 'network-wireless'
    485460
    486         icon_name = get_icon_state(icon_name, self._strength)
    487         if icon_name:
    488             self._icon.props.icon_name = icon_name
     461            icon_name = get_icon_state(icon_name, self._strength)
     462            if icon_name:
     463                self._icon.props.icon_name = icon_name
     464        else:
     465            try:
     466                channel = network.frequency_to_channel(self._frequency)
     467            except KeyError:
     468                channel = 1
     469            if state == network.DEVICE_STATE_ACTIVATED:
     470                self._icon.props.icon_name = 'network-adhoc-%s-connected' \
     471                        % channel
     472            else:
     473                self._icon.props.icon_name = 'network-adhoc-%s' % channel
     474            self._icon.props.base_color = profile.get_color()
    489475
    490476        if state == network.DEVICE_STATE_PREPARE or \
    491477           state == network.DEVICE_STATE_CONFIG or \
    class WirelessDeviceView(ToolButton): 
    524510                    netmgr.DeactivateConnection(conn_o)
    525511                    break
    526512
    527     def __create_connection_cb(self, palette, data=None):
    528         """Create an 802.11 IBSS network.
    529 
    530         The user's color is encoded at the end of the network name. The network
    531         name is truncated so that it does not exceed the 32 byte SSID limit.
    532         """
    533         client = gconf.client_get_default()
    534         nick = client.get_string('/desktop/sugar/user/nick').decode('utf-8')
    535         color = client.get_string('/desktop/sugar/user/color')
    536         color_suffix = ' %s' % color
    537 
    538         format = _('%s\'s network').encode('utf-8')
    539         extra_length = (len(format) - len('%s')) + len(color_suffix)
    540         name_limit = 32 - extra_length
    541 
    542         # truncate the nick and use a regex to drop any partial characters
    543         # at the end
    544         nick = nick.encode('utf-8')[:name_limit]
    545         pattern = "([\xf6-\xf7][\x80-\xbf]{0,2}|[\xe0-\xef][\x80-\xbf]{0,1}|[\xc0-\xdf])$"
    546         nick = re.sub(pattern, '', nick)
    547 
    548         connection_name = format % nick
    549         connection_name += color_suffix
    550 
    551         connection = network.find_connection_by_ssid(connection_name)
    552         if connection is None:
    553             settings = Settings()
    554             settings.connection.id = 'Auto ' + connection_name
    555             uuid = settings.connection.uuid = unique_id()
    556             settings.connection.type = '802-11-wireless'
    557             settings.wireless.ssid = dbus.ByteArray(connection_name)
    558             settings.wireless.band = 'bg'
    559             settings.wireless.mode = 'adhoc'
    560             settings.ip4_config = IP4Config()
    561             settings.ip4_config.method = 'link-local'
    562 
    563             connection = network.add_connection(uuid, settings)
    564 
    565         obj = self._bus.get_object(_NM_SERVICE, _NM_PATH)
    566         netmgr = dbus.Interface(obj, _NM_IFACE)
    567 
    568         netmgr.ActivateConnection(network.SETTINGS_SERVICE,
    569                                   connection.path,
    570                                   self._device.object_path,
    571                                   '/',
    572                                   reply_handler=self.__activate_reply_cb,
    573                                   error_handler=self.__activate_error_cb)
    574 
    575513    def __activate_reply_cb(self, connection):
    576514        logging.debug('Network created: %s', connection)
    577515
  • src/jarabe/desktop/meshbox.py

    diff --git a/src/jarabe/desktop/meshbox.py b/src/jarabe/desktop/meshbox.py
    index a04922b..3adae82 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 IP4Config 
    5353from jarabe.model.network import WirelessSecurity
    5454from jarabe.model.network import AccessPoint
    5555from jarabe.model.olpcmesh import OlpcMeshManager
     56from jarabe.model.adhoc import AdHocManager
    5657
    5758_NM_SERVICE = 'org.freedesktop.NetworkManager'
    5859_NM_IFACE = 'org.freedesktop.NetworkManager'
    class WirelessNetworkView(CanvasPulsingIcon): 
    8990        self._connection = None
    9091        self._color = None
    9192
    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])
     93        if self._mode == network.NM_802_11_MODE_ADHOC and \
     94                self._name.startswith('Ad-hoc Network'):
     95            self._color = profile.get_color()
    9796        else:
    9897            sha_hash = hashlib.sha1()
    9998            data = self._name + hex(self._flags)
    class WirelessNetworkView(CanvasPulsingIcon): 
    115114        self.set_palette(self._palette)
    116115        self._palette_icon.props.xo_color = self._color
    117116
    118         if network.find_connection_by_ssid(self._name) is not None:
    119             self.props.badge_name = "emblem-favorite"
    120             self._palette_icon.props.badge_name = "emblem-favorite"
    121         elif initial_ap.flags == network.NM_802_11_AP_FLAGS_PRIVACY:
    122             self.props.badge_name = "emblem-locked"
    123             self._palette_icon.props.badge_name = "emblem-locked"
     117        if self._mode != network.NM_802_11_MODE_ADHOC:
     118            if network.find_connection_by_ssid(self._name) is not None:
     119                self.props.badge_name = "emblem-favorite"
     120                self._palette_icon.props.badge_name = "emblem-favorite"
     121            elif self._flags == network.NM_802_11_AP_FLAGS_PRIVACY:
     122                self.props.badge_name = "emblem-locked"
     123                self._palette_icon.props.badge_name = "emblem-locked"
     124            else:
     125                self.props.badge_name = None
     126                self._palette_icon.props.badge_name = None
    124127        else:
    125128            self.props.badge_name = None
    126129            self._palette_icon.props.badge_name = None
    class WirelessNetworkView(CanvasPulsingIcon): 
    146149                                      path=self._device.object_path,
    147150                                      dbus_interface=_NM_WIRELESS_IFACE)
    148151
    149     def _name_encodes_colors(self):
    150         """Match #XXXXXX,#YYYYYY at the end of the network name"""
    151         return self._name[-7] == '#' and self._name[-8] == ',' \
    152             and self._name[-15] == '#'
    153 
    154152    def _create_palette(self):
    155153        icon_name = get_icon_state(_AP_ICON_NAME, self._strength)
    156154        self._palette_icon = Icon(icon_name=icon_name,
    class WirelessNetworkView(CanvasPulsingIcon): 
    221219        else:
    222220            state = network.DEVICE_STATE_UNKNOWN
    223221
    224         if state == network.DEVICE_STATE_ACTIVATED:
    225             connection = network.find_connection_by_ssid(self._name)
    226             if connection:
    227                 if self._mode == network.NM_802_11_MODE_INFRA:
    228                     connection.set_connected()
    229 
    230             icon_name = '%s-connected' % _AP_ICON_NAME
    231         else:
    232             icon_name = _AP_ICON_NAME
    233 
    234         icon_name = get_icon_state(icon_name, self._strength)
    235         if icon_name:
     222        if self._mode == network.NM_802_11_MODE_ADHOC and \
     223                self._name.startswith('Ad-hoc Network'):
     224            channel = max([1] + [ap.channel for ap in
     225                                      self._access_points.values()])
     226            if state == network.DEVICE_STATE_ACTIVATED:
     227                icon_name = 'network-adhoc-%s-connected' % channel
     228            else:
     229                icon_name = 'network-adhoc-%s' % channel
    236230            self.props.icon_name = icon_name
    237231            icon = self._palette.props.icon
    238232            icon.props.icon_name = icon_name
     233        else:
     234            if state == network.DEVICE_STATE_ACTIVATED:
     235                connection = network.find_connection_by_ssid(self._name)
     236                if connection:
     237                    if self._mode == network.NM_802_11_MODE_INFRA:
     238                        connection.set_connected()
     239                icon_name = '%s-connected' % _AP_ICON_NAME
     240            else:
     241                icon_name = _AP_ICON_NAME
     242
     243            icon_name = get_icon_state(icon_name, self._strength)
     244            if icon_name:
     245                self.props.icon_name = icon_name
     246                icon = self._palette.props.icon
     247                icon.props.icon_name = icon_name
    239248
    240249        if state == network.DEVICE_STATE_PREPARE or \
    241250           state == network.DEVICE_STATE_CONFIG or \
    class WirelessNetworkView(CanvasPulsingIcon): 
    444453                                         dbus_interface=_NM_WIRELESS_IFACE)
    445454
    446455
     456class AdHocView(CanvasPulsingIcon):
     457    def __init__(self, manager, channel):
     458        CanvasPulsingIcon.__init__(self,
     459                                   icon_name='network-adhoc-%s' % channel,
     460                                   size=style.STANDARD_ICON_SIZE, cache=True)
     461        self._bus = dbus.SystemBus()
     462        self._manager = manager
     463        self._device = manager.device
     464        self._channel = channel
     465        self._icon_name = 'network-adhoc-%s' % self._channel
     466        self._disconnect_item = None
     467        self._connect_item = None
     468        self._palette_icon = None
     469        self._greyed_out = False
     470        self._name = "Ad-hoc Network %d" % channel
     471        self._device_state = None
     472        self._connection = None
     473        self._active = False
     474
     475        self.connect('button-release-event', self.__button_release_event_cb)
     476
     477        interface_props = dbus.Interface(self._device,
     478                                         'org.freedesktop.DBus.Properties')
     479        interface_props.Get(_NM_DEVICE_IFACE, 'State',
     480                            reply_handler=self.__get_device_state_reply_cb,
     481                            error_handler=self.__get_device_state_error_cb)
     482
     483        self._bus.add_signal_receiver(self.__device_state_changed_cb,
     484                                      signal_name='StateChanged',
     485                                      path=self._device.object_path,
     486                                      dbus_interface=_NM_DEVICE_IFACE)
     487        self._bus.add_signal_receiver(self.__wireless_properties_changed_cb,
     488                                      signal_name='PropertiesChanged',
     489                                      path=self._device.object_path,
     490                                      dbus_interface=_NM_WIRELESS_IFACE)
     491
     492        pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(),
     493                                         style.COLOR_TRANSPARENT.get_svg()))
     494        self.props.pulse_color = pulse_color
     495        self._state_color = XoColor('%s,%s' % \
     496                                       (profile.get_color().get_stroke_color(),
     497                                        style.COLOR_TRANSPARENT.get_svg()))
     498        self.props.base_color = self._state_color
     499        self._palette = self._create_palette()
     500        self.set_palette(self._palette)
     501        self._palette_icon.props.xo_color = self._state_color
     502
     503    def _create_palette(self):
     504        self._palette_icon = Icon(icon_name=self._icon_name,
     505                                  icon_size=style.STANDARD_ICON_SIZE)
     506
     507        _palette = palette.Palette(_("Ad-hoc Network %d") % self._channel,
     508                                   icon=self._palette_icon)
     509
     510        self._connect_item = MenuItem(_('Connect'), 'dialog-ok')
     511        self._connect_item.connect('activate', self.__connect_activate_cb)
     512        _palette.menu.append(self._connect_item)
     513
     514        self._disconnect_item = MenuItem(_('Disconnect'), 'media-eject')
     515        self._disconnect_item.connect('activate',
     516                                      self.__disconnect_activate_cb)
     517        _palette.menu.append(self._disconnect_item)
     518
     519        return _palette
     520
     521    def __button_release_event_cb(self, icon, event):
     522        self._manager.activate_channel(self._channel)
     523
     524    def __connect_activate_cb(self, icon):
     525        self._manager.activate_channel(self._channel)
     526
     527    def __disconnect_activate_cb(self, icon):
     528        obj = self._bus.get_object(_NM_SERVICE, _NM_PATH)
     529        netmgr = dbus.Interface(obj, _NM_IFACE)
     530
     531        netmgr_props = dbus.Interface(netmgr, dbus.PROPERTIES_IFACE)
     532        active_connections_o = netmgr_props.Get(_NM_IFACE, 'ActiveConnections')
     533
     534        for conn_o in active_connections_o:
     535            obj = self._bus.get_object(_NM_IFACE, conn_o)
     536            props = dbus.Interface(obj, dbus.PROPERTIES_IFACE)
     537            state = props.Get(_NM_ACTIVE_CONN_IFACE, 'State')
     538            if state == network.NM_ACTIVE_CONNECTION_STATE_ACTIVATED:
     539                ap_o = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject')
     540                if ap_o != '/':
     541                    netmgr.DeactivateConnection(conn_o)
     542
     543    def __get_device_state_reply_cb(self, state):
     544        self._device_state = state
     545        self._update()
     546
     547    def __get_device_state_error_cb(self, err):
     548        logging.error('Error getting the device state: %s', err)
     549
     550    def __device_state_changed_cb(self, new_state, old_state, reason):
     551        self._device_state = new_state
     552        self._update()
     553
     554    def __wireless_properties_changed_cb(self, properties):
     555        if 'ActiveAccessPoint' in properties and \
     556                properties['ActiveAccessPoint'] is not '/':
     557            active_ap = self._bus.get_object(_NM_SERVICE,
     558                                             properties['ActiveAccessPoint'])
     559            props = dbus.Interface(active_ap, dbus.PROPERTIES_IFACE)
     560
     561            props.GetAll(_NM_ACCESSPOINT_IFACE, byte_arrays=True,
     562                         reply_handler=self.__get_all_ap_props_reply_cb,
     563                         error_handler=self.__get_all_ap_props_error_cb)
     564
     565    def __get_all_ap_props_reply_cb(self, properties):
     566        if properties['Mode'] == network.NM_802_11_MODE_ADHOC:
     567            channel = network.frequency_to_channel(properties['Frequency'])
     568            if self._channel == channel:
     569                self._active = True
     570            else:
     571                self._active = False
     572        else:
     573            self._active = False
     574        self._update()
     575
     576    def __get_all_ap_props_error_cb(self, err):
     577        logging.error('Error getting the access point properties: %s', err)
     578
     579    def _update(self):
     580        if self._active:
     581            state = self._device_state
     582        else:
     583            state = network.DEVICE_STATE_UNKNOWN
     584
     585        if state == network.DEVICE_STATE_ACTIVATED:
     586            icon_name = '%s-connected' % self._icon_name
     587        else:
     588            icon_name = self._icon_name
     589
     590        self.props.base_color = self._state_color
     591        self._palette_icon.props.xo_color = self._state_color
     592
     593        if icon_name is not None:
     594            self.props.icon_name = icon_name
     595            icon = self._palette.props.icon
     596            icon.props.icon_name = icon_name
     597
     598        if state in [network.DEVICE_STATE_PREPARE,
     599                     network.DEVICE_STATE_CONFIG,
     600                     network.DEVICE_STATE_NEED_AUTH,
     601                     network.DEVICE_STATE_IP_CONFIG]:
     602            if self._disconnect_item:
     603                self._disconnect_item.show()
     604            self._connect_item.hide()
     605            self._palette.props.secondary_text = _('Connecting...')
     606            self.props.pulsing = True
     607        elif state == network.DEVICE_STATE_ACTIVATED:
     608            if self._disconnect_item:
     609                self._disconnect_item.show()
     610            self._connect_item.hide()
     611            self._palette.props.secondary_text = _('Connected')
     612            self.props.pulsing = False
     613        else:
     614            if self._disconnect_item:
     615                self._disconnect_item.hide()
     616            self._connect_item.show()
     617            self._palette.props.secondary_text = None
     618            self.props.pulsing = False
     619
     620    def _update_color(self):
     621        if self._greyed_out:
     622            self.props.base_color = XoColor('#D5D5D5,#D5D5D5')
     623        else:
     624            self.props.base_color = self._state_color
     625
     626    def indicate_population(self, state):
     627        if state == True:
     628            self._state_color = profile.get_color()
     629            self.props.base_color = self._state_color
     630            self._palette_icon.props.xo_color = self._state_color
     631        else:
     632            color = '%s,%s' % (profile.get_color().get_stroke_color(),
     633                               style.COLOR_TRANSPARENT.get_svg())
     634            self._state_color = XoColor(color)
     635            self.props.base_color = self._state_color
     636            self._palette_icon.props.xo_color = self._state_color
     637
     638    def set_filter(self, query):
     639        self._greyed_out = self._name.lower().find(query) == -1
     640        self._update_color()
     641
     642    def disconnect(self):
     643        self._bus.remove_signal_receiver(self.__device_state_changed_cb,
     644                                         signal_name='StateChanged',
     645                                         path=self._device.object_path,
     646                                         dbus_interface=_NM_DEVICE_IFACE)
     647        self._bus.remove_signal_receiver(self.__wireless_properties_changed_cb,
     648                                         signal_name='PropertiesChanged',
     649                                         path=self._device.object_path,
     650                                         dbus_interface=_NM_WIRELESS_IFACE)
     651
     652
    447653class OlpcMeshView(CanvasPulsingIcon):
    448654    def __init__(self, mesh_mgr, channel):
    449655        CanvasPulsingIcon.__init__(self, icon_name=_OLPC_MESH_ICON_NAME,
    class NetworkManagerObserver(object): 
    8211027        self._bus = None
    8221028        self._devices = {}
    8231029        self._netmgr = None
     1030        self._has_mesh_device = False
     1031        self._check_mesh_source = 0
    8241032
    8251033    def listen(self):
    8261034        try:
    class NetworkManagerObserver(object): 
    8401048        self._bus.add_signal_receiver(self.__device_removed_cb,
    8411049                                      signal_name='DeviceRemoved',
    8421050                                      dbus_interface=_NM_IFACE)
     1051        self._bus.add_signal_receiver(self.__properties_changed_cb,
     1052                                      signal_name='PropertiesChanged',
     1053                                      dbus_interface=_NM_IFACE)
    8431054
    8441055        settings = network.get_settings()
    8451056        if settings is not None:
    class NetworkManagerObserver(object): 
    8841095        device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType')
    8851096        if device_type == network.DEVICE_TYPE_802_11_WIRELESS:
    8861097            self._devices[device_o] = DeviceObserver(self._box, device)
     1098            if self._check_mesh_source != 0:
     1099                gobject.source_remove(self._check_mesh_source)
     1100            self._check_mesh_source = gobject.timeout_add( \
     1101                    5, self._add_adhoc_networks, device)
    8871102        elif device_type == network.DEVICE_TYPE_802_11_OLPC_MESH:
     1103            self._has_mesh_device = True
    8881104            self._box.enable_olpc_mesh(device)
    8891105
    8901106    def _get_device_path_error_cb(self, err):
    class NetworkManagerObserver(object): 
    8981114            observer = self._devices[device_o]
    8991115            observer.disconnect()
    9001116            del self._devices[device_o]
     1117            if self._has_mesh_device == False:
     1118                self._box.remove_adhoc_networks()
    9011119            return
    9021120           
    9031121        device = self._bus.get_object(_NM_SERVICE, device_o)
    class NetworkManagerObserver(object): 
    9061124        if device_type == network.DEVICE_TYPE_802_11_OLPC_MESH:
    9071125            self._box.disable_olpc_mesh(device)
    9081126
     1127    def _add_adhoc_networks(self, device):
     1128        """If we do not find mesh hardware we create Ad-hoc networks."""
     1129        if self._has_mesh_device == False:
     1130            self._box.add_adhoc_networks(device)
     1131        return False
     1132
     1133    def __properties_changed_cb(self, properties):
     1134        if 'WirelessHardwareEnabled' in properties:
     1135            if properties['WirelessHardwareEnabled'] == False:
     1136                if self._has_mesh_device == False:
     1137                    self._box.remove_adhoc_networks()
     1138            if properties['WirelessHardwareEnabled'] == True:
     1139                for device in self._devices:
     1140                    if self._has_mesh_device == False:
     1141                        self._box.add_adhoc_networks(device)
     1142
     1143
    9091144class MeshBox(gtk.VBox):
    9101145    __gtype_name__ = 'SugarMeshBox'
    9111146
    class MeshBox(gtk.VBox): 
    9151150        gobject.GObject.__init__(self)
    9161151
    9171152        self.wireless_networks = {}
     1153        self._adhoc_manager = None
    9181154
    9191155        self._model = neighborhood.get_model()
    9201156        self._buddies = {}
    class MeshBox(gtk.VBox): 
    10721308            ap.disconnect()
    10731309            return
    10741310
     1311        if self._adhoc_manager != None and \
     1312                ap.name.startswith('Ad-hoc Network') and \
     1313                ap.mode == network.NM_802_11_MODE_ADHOC:
     1314
     1315            if old_hash is None: # new Ad-hoc network finished initializing
     1316                self._adhoc_manager.add_access_point(ap)
     1317            # we are called as well in other cases but we do not need to
     1318            # act here as we don't display signal strength for Ad-hoc networks
     1319            return
     1320
    10751321        if old_hash is None: # new AP finished initializing
    10761322            self._add_ap_to_network(ap)
    10771323            return
    class MeshBox(gtk.VBox): 
    10941340        ap.initialize()
    10951341
    10961342    def remove_access_point(self, ap_o):
     1343        if self._adhoc_manager is not None:
     1344            if self._adhoc_manager.remove_access_point(ap_o) == True:
     1345                return
     1346
    10971347        # we don't keep an index of ap object path to network, but since
    10981348        # we'll only ever have a handful of networks, just try them all...
    10991349        for net in self.wireless_networks.values():
    class MeshBox(gtk.VBox): 
    11101360        # it (e.g. olpc-mesh adhoc network)
    11111361        logging.debug('Can not remove access point %s' % ap_o)
    11121362
     1363    def add_adhoc_networks(self, device):
     1364        if self._adhoc_manager is None:
     1365            self._adhoc_manager = AdHocManager(device)
     1366        for channel in self._adhoc_manager.channels:
     1367            self._add_adhoc_network_icon(self._adhoc_manager, channel)
     1368
     1369    def remove_adhoc_networks(self):
     1370        for channel in self._adhoc_manger.channels:
     1371            icon = self._adhoc_manager.remove_network(channel)
     1372            if icon is not None:
     1373                icon.disconnect()
     1374                self._layout.remove(icon)
     1375
     1376    def _add_adhoc_network_icon(self, adhoc_manager, channel):
     1377        icon = AdHocView(adhoc_manager, channel)
     1378        self._layout.add(icon)
     1379        self._adhoc_manager.add_network(channel, icon)
     1380
    11131381    def _add_olpc_mesh_icon(self, mesh_mgr, channel):
    11141382        icon = OlpcMeshView(mesh_mgr, channel)
    11151383        self._layout.add(icon)
  • src/jarabe/model/Makefile.am

    diff --git a/src/jarabe/model/Makefile.am b/src/jarabe/model/Makefile.am
    index e9f0700..4650c3b 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 3a949da..63a35e5 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# Copyright (C) 2010 Plan Ceibal, Daniel Castelo
    66#
    GSM_PUK_PATH = '/desktop/sugar/network/gsm/puk' 
    9999_nm_settings = None
    100100_conn_counter = 0
    101101
     102
     103def frequency_to_channel(frequency):
     104    ftoc = {2412: 1, 2417: 2, 2422: 3, 2427: 4,
     105            2432: 5, 2437: 6, 2442: 7, 2447: 8,
     106            2452: 9, 2457: 10, 2462: 11, 2467: 12,
     107            2472: 13}
     108    return ftoc[frequency]
     109
     110
    102111class WirelessSecurity(object):
    103112    def __init__(self):
    104113        self.key_mgmt = None
    105114        self.proto = None
    106115        self.group = None
    107116        self.pairwise = None
     117        self.channel = None
    108118
    109119    def get_dict(self):
    110120        wireless_security = {}
    class WirelessSecurity(object): 
    116126            wireless_security['pairwise'] = self.pairwise
    117127        if self.group is not None:
    118128            wireless_security['group'] = self.group
     129        if self.channel:
     130            wireless['channel'] = self.channel
    119131        return wireless_security
    120132
    121133class Wireless(object):
    class AccessPoint(gobject.GObject): 
    475487        self.wpa_flags = 0
    476488        self.rsn_flags = 0
    477489        self.mode = 0
     490        self.channel = 1
    478491
    479492    def initialize(self):
    480493        model_props = dbus.Interface(self.model,
    class AccessPoint(gobject.GObject): 
    544557            self.rsn_flags = properties['RsnFlags']
    545558        if 'Mode' in properties:
    546559            self.mode = properties['Mode']
     560        if 'Frequency' in properties:
     561            try:
     562                self.channel = frequency_to_channel(properties['Frequency'])
     563            except KeyError:
     564                self.channel = 1
     565
    547566        self._initialized = True
    548567        self.emit('props-changed', old_hash)
    549568