Ticket #1610: adhoc_default_networks_1406.patch

File adhoc_default_networks_1406.patch, 32.3 KB (added by erikos, 12 years ago)

Patch with autoconnection if there is no known network

  • extensions/deviceicon/network.py

    diff --git a/extensions/deviceicon/network.py b/extensions/deviceicon/network.py
    index 202c563..b266489 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:
     413                self._color = profile.get_color()
    443414            else:
    444415                sh = sha.new()
    445416                data = self._name + hex(self._flags)
    class WirelessDeviceView(ToolButton): 
    475446        else:
    476447            state = network.DEVICE_STATE_UNKNOWN
    477448
    478         if state == network.DEVICE_STATE_ACTIVATED:
    479             icon_name = '%s-connected' % self._ICON_NAME
    480         else:
    481             icon_name = self._ICON_NAME
     449        if self._mode != network.NM_802_11_MODE_ADHOC:
     450            if state == network.DEVICE_STATE_ACTIVATED:
     451                icon_name = '%s-connected' % 'network-wireless'
     452            else:
     453                icon_name = 'network-wireless'
    482454
    483         icon_name = get_icon_state(icon_name, self._strength)
    484         if icon_name:
    485             self._icon.props.icon_name = icon_name
     455            icon_name = get_icon_state(icon_name, self._strength)
     456            if icon_name:
     457                self._icon.props.icon_name = icon_name
     458        else:
     459            try:
     460                channel = network.frequency_to_channel(self._frequency)
     461            except KeyError:
     462                channel = 1
     463            if state == network.DEVICE_STATE_ACTIVATED:
     464                self._icon.props.icon_name = 'network-adhoc-%s-connected' \
     465                        % channel
     466            else:
     467                self._icon.props.icon_name = 'network-adhoc-%s' % channel
     468            self._icon.props.base_color = profile.get_color()
    486469
    487470        if state == network.DEVICE_STATE_PREPARE or \
    488471           state == network.DEVICE_STATE_CONFIG or \
    class WirelessDeviceView(ToolButton): 
    526509                    netmgr.DeactivateConnection(conn_o)
    527510                    break
    528511
    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 
    577512    def __activate_reply_cb(self, connection):
    578513        logging.debug('Network created: %s', connection)
    579514
  • src/jarabe/desktop/meshbox.py

    diff --git a/src/jarabe/desktop/meshbox.py b/src/jarabe/desktop/meshbox.py
    index 29a9cf1..0cd1afa 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): 
    469469                                         dbus_interface=_NM_WIRELESS_IFACE)
    470470
    471471
     472class AdHocView(CanvasPulsingIcon):
     473    def __init__(self, manager, channel):
     474        CanvasPulsingIcon.__init__(self,
     475                                   icon_name='network-adhoc-%s' % channel,
     476                                   size=style.STANDARD_ICON_SIZE, cache=True)
     477        self._bus = dbus.SystemBus()
     478        self._manager = manager
     479        self._device = manager.device
     480        self._channel = channel
     481        self._icon_name = 'network-adhoc-%s' % self._channel
     482        self._disconnect_item = None
     483        self._connect_item = None
     484        self._palette_icon = None
     485        self._greyed_out = False
     486        self._name = "Ad-hoc Network %d" % channel
     487        self._device_state = None
     488        self._connection = None
     489        self._active = False
     490
     491        self.connect('button-release-event', self.__button_release_event_cb)
     492
     493        interface_props = dbus.Interface(self._device,
     494                                         'org.freedesktop.DBus.Properties')
     495        interface_props.Get(_NM_DEVICE_IFACE, 'State',
     496                            reply_handler=self.__get_device_state_reply_cb,
     497                            error_handler=self.__get_device_state_error_cb)
     498
     499        self._bus.add_signal_receiver(self.__device_state_changed_cb,
     500                                      signal_name='StateChanged',
     501                                      path=self._device.object_path,
     502                                      dbus_interface=_NM_DEVICE_IFACE)
     503        self._bus.add_signal_receiver(self.__wireless_properties_changed_cb,
     504                                      signal_name='PropertiesChanged',
     505                                      path=self._device.object_path,
     506                                      dbus_interface=_NM_WIRELESS_IFACE)
     507
     508        pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(),
     509                                         style.COLOR_TRANSPARENT.get_svg()))
     510        self.props.pulse_color = pulse_color
     511        self._state_color = XoColor('%s,%s' % \
     512                                       (profile.get_color().get_stroke_color(),
     513                                        style.COLOR_TRANSPARENT.get_svg()))
     514        self.props.base_color = self._state_color
     515        self._palette = self._create_palette()
     516        self.set_palette(self._palette)
     517        self._palette_icon.props.xo_color = self._state_color
     518
     519    def _create_palette(self):
     520        self._palette_icon = Icon(icon_name=self._icon_name,
     521                                  icon_size=style.STANDARD_ICON_SIZE)
     522
     523        _palette = palette.Palette(_("Ad-hoc Network %d") % self._channel,
     524                                   icon=self._palette_icon)
     525
     526        self._connect_item = MenuItem(_('Connect'), 'dialog-ok')
     527        self._connect_item.connect('activate', self.__connect_activate_cb)
     528        _palette.menu.append(self._connect_item)
     529
     530        self._disconnect_item = MenuItem(_('Disconnect'), 'media-eject')
     531        self._disconnect_item.connect('activate',
     532                                      self.__disconnect_activate_cb)
     533        _palette.menu.append(self._disconnect_item)
     534
     535        return _palette
     536
     537    def __button_release_event_cb(self, icon, event):
     538        self._manager.activate_channel(self._channel)
     539
     540    def __connect_activate_cb(self, icon):
     541        self._manager.activate_channel(self._channel)
     542
     543    def __disconnect_activate_cb(self, icon):
     544        obj = self._bus.get_object(_NM_SERVICE, _NM_PATH)
     545        netmgr = dbus.Interface(obj, _NM_IFACE)
     546
     547        netmgr_props = dbus.Interface(netmgr, dbus.PROPERTIES_IFACE)
     548        active_connections_o = netmgr_props.Get(_NM_IFACE, 'ActiveConnections')
     549
     550        for conn_o in active_connections_o:
     551            obj = self._bus.get_object(_NM_IFACE, conn_o)
     552            props = dbus.Interface(obj, dbus.PROPERTIES_IFACE)
     553            state = props.Get(_NM_ACTIVE_CONN_IFACE, 'State')
     554            if state == network.NM_ACTIVE_CONNECTION_STATE_ACTIVATED:
     555                ap_o = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject')
     556                if ap_o != '/':
     557                    netmgr.DeactivateConnection(conn_o)
     558
     559    def __get_device_state_reply_cb(self, state):
     560        self._device_state = state
     561        self._update()
     562
     563    def __get_device_state_error_cb(self, err):
     564        logging.error('Error getting the device state: %s', err)
     565
     566    def __device_state_changed_cb(self, new_state, old_state, reason):
     567        self._device_state = new_state
     568        self._update()
     569
     570    def __wireless_properties_changed_cb(self, properties):
     571        if 'ActiveAccessPoint' in properties and \
     572                properties['ActiveAccessPoint'] is not '/':
     573            active_ap = self._bus.get_object(_NM_SERVICE,
     574                                             properties['ActiveAccessPoint'])
     575            props = dbus.Interface(active_ap, dbus.PROPERTIES_IFACE)
     576
     577            props.GetAll(_NM_ACCESSPOINT_IFACE, byte_arrays=True,
     578                         reply_handler=self.__get_all_ap_props_reply_cb,
     579                         error_handler=self.__get_all_ap_props_error_cb)
     580
     581    def __get_all_ap_props_reply_cb(self, properties):
     582        if properties['Mode'] == network.NM_802_11_MODE_ADHOC:
     583            channel = network.frequency_to_channel(properties['Frequency'])
     584            if self._channel == channel:
     585                self._active = True
     586            else:
     587                self._active = False
     588        else:
     589            self._active = False
     590        self._update()
     591
     592    def __get_all_ap_props_error_cb(self, err):
     593        logging.error('Error getting the access point properties: %s', err)
     594
     595    def _update(self):
     596        if self._active:
     597            state = self._device_state
     598        else:
     599            state = network.DEVICE_STATE_UNKNOWN
     600
     601        if state == network.DEVICE_STATE_ACTIVATED:
     602            icon_name = '%s-connected' % self._icon_name
     603        else:
     604            icon_name = self._icon_name
     605
     606        self.props.base_color = self._state_color
     607        self._palette_icon.props.xo_color = self._state_color
     608
     609        if icon_name is not None:
     610            self.props.icon_name = icon_name
     611            icon = self._palette.props.icon
     612            icon.props.icon_name = icon_name
     613
     614        if state in [network.DEVICE_STATE_PREPARE,
     615                     network.DEVICE_STATE_CONFIG,
     616                     network.DEVICE_STATE_NEED_AUTH,
     617                     network.DEVICE_STATE_IP_CONFIG]:
     618            if self._disconnect_item:
     619                self._disconnect_item.show()
     620            self._connect_item.hide()
     621            self._palette.props.secondary_text = _('Connecting...')
     622            self.props.pulsing = True
     623        elif state == network.DEVICE_STATE_ACTIVATED:
     624            if self._disconnect_item:
     625                self._disconnect_item.show()
     626            self._connect_item.hide()
     627            self._palette.props.secondary_text = _('Connected')
     628            self.props.pulsing = False
     629        else:
     630            if self._disconnect_item:
     631                self._disconnect_item.hide()
     632            self._connect_item.show()
     633            self._palette.props.secondary_text = None
     634            self.props.pulsing = False
     635
     636    def _update_color(self):
     637        if self._greyed_out:
     638            self.props.base_color = XoColor('#D5D5D5,#D5D5D5')
     639        else:
     640            self.props.base_color = self._state_color
     641
     642    def indicate_population(self, state):
     643        if state == True:
     644            self._state_color = profile.get_color()
     645            self.props.base_color = self._state_color
     646            self._palette_icon.props.xo_color = self._state_color
     647        else:
     648            color = '%s,%s' % (profile.get_color().get_stroke_color(),
     649                               style.COLOR_TRANSPARENT.get_svg())
     650            self._state_color = XoColor(color)
     651            self.props.base_color = self._state_color
     652            self._palette_icon.props.xo_color = self._state_color
     653
     654    def set_filter(self, query):
     655        self._greyed_out = self._name.lower().find(query) == -1
     656        self._update_color()
     657   
     658    def disconnect(self):
     659        self._bus.remove_signal_receiver(self.__device_state_changed_cb,
     660                                         signal_name='StateChanged',
     661                                         path=self._device.object_path,
     662                                         dbus_interface=_NM_DEVICE_IFACE)
     663        self._bus.remove_signal_receiver(self.__wireless_properties_changed_cb,
     664                                         signal_name='PropertiesChanged',
     665                                         path=self._device.object_path,
     666                                         dbus_interface=_NM_WIRELESS_IFACE)
     667
    472668class OlpcMeshView(CanvasPulsingIcon):
    473669    def __init__(self, mesh_mgr, channel):
    474670        CanvasPulsingIcon.__init__(self, icon_name=_OLPC_MESH_ICON_NAME,
    class NetworkManagerObserver(object): 
    8461042        self._bus = dbus.SystemBus()
    8471043        self._devices = {}
    8481044        self._netmgr = None
     1045        self._has_mesh_device = False
     1046        self._check_mesh_source = 0
    8491047
    8501048    def listen(self):
    8511049        try:
    class NetworkManagerObserver(object): 
    8641062        self._bus.add_signal_receiver(self.__device_removed_cb,
    8651063                                      signal_name='DeviceRemoved',
    8661064                                      dbus_interface=_NM_IFACE)
     1065        self._bus.add_signal_receiver(self.__properties_changed_cb,
     1066                                      signal_name='PropertiesChanged',
     1067                                      dbus_interface=_NM_IFACE)
    8671068
    8681069        settings = network.get_settings()
    8691070        if settings is not None:
    class NetworkManagerObserver(object): 
    9071108        device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType')
    9081109        if device_type == network.DEVICE_TYPE_802_11_WIRELESS:
    9091110            self._devices[device_o] = DeviceObserver(self._box, device)
     1111            if self._check_mesh_source != 0:
     1112                gobject.source_remove(self._check_mesh_source)
     1113            self._check_mesh_source = gobject.timeout_add( \
     1114                    5, self._add_adhoc_networks, device)
    9101115        elif device_type == network.DEVICE_TYPE_802_11_OLPC_MESH:
     1116            self._has_mesh_device = True
    9111117            self._box.enable_olpc_mesh(device)
    9121118
    9131119    def _get_device_path_error_cb(self, err):
    class NetworkManagerObserver(object): 
    9211127            observer = self._devices[device_o]
    9221128            observer.disconnect()
    9231129            del self._devices[device_o]
     1130            if self._has_mesh_device == False:
     1131                self._box.remove_adhoc_networks()
    9241132            return
    9251133
    9261134        device = self._bus.get_object(_NM_SERVICE, device_o)
    class NetworkManagerObserver(object): 
    9291137        if device_type == network.DEVICE_TYPE_802_11_OLPC_MESH:
    9301138            self._box.disable_olpc_mesh(device)
    9311139
     1140    def _add_adhoc_networks(self, device):
     1141        """If we do not find mesh hardware we create Ad-hoc networks."""
     1142        if self._has_mesh_device == False:
     1143            self._box.add_adhoc_networks(device)
     1144        return False
     1145
     1146    def __properties_changed_cb(self, properties):
     1147        if 'WirelessHardwareEnabled' in properties:
     1148            if properties['WirelessHardwareEnabled'] == False:
     1149                if self._has_mesh_device == False:
     1150                    self._box.remove_adhoc_networks()
     1151            if properties['WirelessHardwareEnabled'] == True:
     1152                for device in self._devices:
     1153                    if self._has_mesh_device == False:
     1154                        self._box.add_adhoc_networks(device)
    9321155
    9331156class MeshBox(gtk.VBox):
    9341157    __gtype_name__ = 'SugarMeshBox'
    class MeshBox(gtk.VBox): 
    9391162        gobject.GObject.__init__(self)
    9401163
    9411164        self.wireless_networks = {}
     1165        self._adhoc_manager = None
    9421166
    9431167        self._model = neighborhood.get_model()
    9441168        self._buddies = {}
    class MeshBox(gtk.VBox): 
    9481172        self._suspended = True
    9491173        self._query = ''
    9501174        self._owner_icon = None
    951            
     1175
    9521176        self._toolbar = MeshToolbar()
    9531177        self._toolbar.connect('query-changed', self._toolbar_query_changed_cb)
    9541178        self.pack_start(self._toolbar, expand=False)
    class MeshBox(gtk.VBox): 
    10961320            ap.disconnect()
    10971321            return
    10981322
     1323        if self._adhoc_manager != None and \
     1324                ap.name.startswith('Ad-hoc Network') and \
     1325                ap.mode == network.NM_802_11_MODE_ADHOC:
     1326 
     1327            if old_hash is None: # new Ad-hoc network finished initializing
     1328                self._adhoc_manager.add_access_point(ap)
     1329                return
     1330
    10991331        if old_hash is None: # new AP finished initializing
    11001332            self._add_ap_to_network(ap)
    11011333            return
    class MeshBox(gtk.VBox): 
    11181350        ap.initialize()
    11191351
    11201352    def remove_access_point(self, ap_o):
     1353        if self._adhoc_manager.remove_access_point(ap_o) == True:
     1354            return
     1355
    11211356        # we don't keep an index of ap object path to network, but since
    11221357        # we'll only ever have a handful of networks, just try them all...
    11231358        for net in self.wireless_networks.values():
    class MeshBox(gtk.VBox): 
    11341369        # it (e.g. olpc-mesh adhoc network)
    11351370        logging.debug('Can not remove access point %s' % ap_o)
    11361371
     1372    def add_adhoc_networks(self, device):
     1373        if self._adhoc_manager is None:
     1374            self._adhoc_manager = AdHocManager(device)
     1375        for channel in self._adhoc_manager.channels:
     1376            self._add_adhoc_network_icon(self._adhoc_manager, channel)
     1377
     1378    def remove_adhoc_networks(self):
     1379        for channel in self._adhoc_manger.channels:
     1380            icon = self._adhoc_manager.remove_network(channel)
     1381            if icon is not None:
     1382                icon.disconnect()
     1383                self._layout.remove(icon)
     1384
     1385    def _add_adhoc_network_icon(self, device, channel):
     1386        icon = AdHocView(device, channel)
     1387        self._layout.add(icon)
     1388        self._adhoc_manager.add_network(channel, icon)
     1389
    11371390    def _add_olpc_mesh_icon(self, mesh_mgr, channel):
    11381391        icon = OlpcMeshView(mesh_mgr, channel)
    11391392        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..9a9f025 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):