Ticket #1610: 0001-Add-default-Ad-hoc-networks-1610-5.patch
File 0001-Add-default-Ad-hoc-networks-1610-5.patch, 44.9 KB (added by erikos, 14 years ago) |
---|
-
data/sugar.schemas.in
From e0d1315cbb39d5f4f9ecfd68006d8fa5b84d834d Mon Sep 17 00:00:00 2001 From: Simon Schampijer <simon@schampijer.de> Date: Thu, 12 Aug 2010 16:26:52 +0200 Subject: [PATCH] Add default Ad-hoc networks #1610 This patch adds three default Ad-hoc networks, for channel 1, 6 and 11. They are represented with designated icons in the neighborhood view. This will mimic the mesh behavior on devices where mesh hardware is not available and make the "under a tree"-scenario possible in those cases. If Sugar sees no "known" network when it starts, it does autoconnect to an Ad-hoc network. --- data/sugar.schemas.in | 14 ++ extensions/deviceicon/network.py | 116 +++------------ src/jarabe/desktop/meshbox.py | 300 +++++++++++++++++++++++++++++++++----- src/jarabe/model/Makefile.am | 1 + src/jarabe/model/adhoc.py | 299 +++++++++++++++++++++++++++++++++++++ src/jarabe/model/network.py | 42 +++++- 6 files changed, 639 insertions(+), 133 deletions(-) create mode 100644 src/jarabe/model/adhoc.py diff --git a/data/sugar.schemas.in b/data/sugar.schemas.in index b9606ba..2e6b820 100644
a b 329 329 </locale> 330 330 </schema> 331 331 332 <schema> 333 <key>/schemas/desktop/sugar/network/adhoc</key> 334 <applyto>/desktop/sugar/network/adhoc</applyto> 335 <owner>sugar</owner> 336 <type>bool</type> 337 <default>true</default> 338 <locale name="C"> 339 <short>Show Sugar Ad-hoc networks</short> 340 <long>If TRUE, Sugar will show default Ad-hoc networks for 341 channel 1,6 and 11. If Sugar sees no "known" network when 342 it starts, it does autoconnect to an Ad-hoc network.</long> 343 </locale> 344 </schema> 345 332 346 </schemalist> 333 347 </gconfschemafile> -
extensions/deviceicon/network.py
diff --git a/extensions/deviceicon/network.py b/extensions/deviceicon/network.py index 227ba46..d76e8f1 100644
a b _GSM_STATE_CONNECTING = 2 67 67 _GSM_STATE_CONNECTED = 3 68 68 _GSM_STATE_NEED_AUTH = 4 69 69 70 def frequency_to_channel(frequency):71 ftoc = { 2412: 1, 2417: 2, 2422: 3, 2427: 4,72 2432: 5, 2437: 6, 2442: 7, 2447: 8,73 2452: 9, 2457: 10, 2462: 11, 2467: 12,74 2472: 13}75 return ftoc[frequency]76 70 77 71 class WirelessPalette(Palette): 78 72 __gtype_name__ = 'SugarWirelessPalette' 79 73 80 74 __gsignals__ = { 81 75 'deactivate-connection' : (gobject.SIGNAL_RUN_FIRST, 82 gobject.TYPE_NONE, ([])), 83 'create-connection' : (gobject.SIGNAL_RUN_FIRST, 84 gobject.TYPE_NONE, ([])), 76 gobject.TYPE_NONE, ([])) 85 77 } 86 78 87 def __init__(self, primary_text , can_create=True):79 def __init__(self, primary_text): 88 80 Palette.__init__(self, label=primary_text) 89 81 90 82 self._disconnect_item = None … … class WirelessPalette(Palette): 117 109 self._disconnect_item.connect('activate', self.__disconnect_activate_cb) 118 110 self.menu.append(self._disconnect_item) 119 111 120 if can_create:121 self._adhoc_item = gtk.MenuItem(_('Create new wireless network'))122 self._adhoc_item.connect('activate', self.__adhoc_activate_cb)123 self.menu.append(self._adhoc_item)124 self._adhoc_item.show()125 126 112 def set_connecting(self): 127 113 self.props.secondary_text = _('Connecting...') 128 114 … … class WirelessPalette(Palette): 149 135 def __disconnect_activate_cb(self, menuitem): 150 136 self.emit('deactivate-connection') 151 137 152 def __adhoc_activate_cb(self, menuitem):153 self.emit('create-connection')154 155 138 def _set_frequency(self, frequency): 156 try: 157 channel = frequency_to_channel(frequency) 158 except KeyError: 159 channel = 0 139 channel = network.frequency_to_channel(frequency) 160 140 self._set_channel(channel) 161 141 162 142 def _set_channel(self, channel): … … class GsmPalette(Palette): 318 298 319 299 class WirelessDeviceView(ToolButton): 320 300 321 _ICON_NAME = 'network-wireless'322 301 FRAME_POSITION_RELATIVE = 302 323 302 324 303 def __init__(self, device): … … class WirelessDeviceView(ToolButton): 337 316 self._active_ap_op = None 338 317 339 318 self._icon = PulsingIcon() 340 self._icon.props.icon_name = get_icon_state( self._ICON_NAME, 0)319 self._icon.props.icon_name = get_icon_state('network-wireless', 0) 341 320 self._inactive_color = xocolor.XoColor( \ 342 321 "%s,%s" % (style.COLOR_BUTTON_GREY.get_svg(), 343 322 style.COLOR_TRANSPARENT.get_svg())) … … class WirelessDeviceView(ToolButton): 351 330 self._palette = WirelessPalette(self._name) 352 331 self._palette.connect('deactivate-connection', 353 332 self.__deactivate_connection_cb) 354 self._palette.connect('create-connection',355 self.__create_connection_cb)356 333 self.set_palette(self._palette) 357 334 self._palette.set_group_id('frame') 358 335 … … class WirelessDeviceView(ToolButton): 422 399 def __ap_properties_changed_cb(self, properties): 423 400 self._update_properties(properties) 424 401 425 def _name_encodes_colors(self):426 """Match #XXXXXX,#YYYYYY at the end of the network name"""427 return self._name[-7] == '#' and self._name[-8] == ',' \428 and self._name[-15] == '#'429 430 402 def _update_properties(self, properties): 431 403 if 'Mode' in properties: 432 404 self._mode = properties['Mode'] … … class WirelessDeviceView(ToolButton): 442 414 self._frequency = properties['Frequency'] 443 415 444 416 if self._color == None: 445 if self._mode == network.NM_802_11_MODE_ADHOC \ 446 and self._name_encodes_colors(): 447 encoded_color = self._name.split("#", 1) 448 if len(encoded_color) == 2: 449 self._color = xocolor.XoColor('#' + encoded_color[1]) 417 if self._mode == network.NM_802_11_MODE_ADHOC and \ 418 network.is_sugar_adhoc_network(self._name): 419 self._color = profile.get_color() 450 420 else: 451 421 sha_hash = hashlib.sha1() 452 422 data = self._name + hex(self._flags) … … class WirelessDeviceView(ToolButton): 482 452 else: 483 453 state = network.DEVICE_STATE_UNKNOWN 484 454 485 if state == network.DEVICE_STATE_ACTIVATED: 486 icon_name = '%s-connected' % self._ICON_NAME 487 else: 488 icon_name = self._ICON_NAME 455 if self._mode != network.NM_802_11_MODE_ADHOC and \ 456 network.is_sugar_adhoc_network(self._name) == False: 457 if state == network.DEVICE_STATE_ACTIVATED: 458 icon_name = '%s-connected' % 'network-wireless' 459 else: 460 icon_name = 'network-wireless' 489 461 490 icon_name = get_icon_state(icon_name, self._strength) 491 if icon_name: 492 self._icon.props.icon_name = icon_name 462 icon_name = get_icon_state(icon_name, self._strength) 463 if icon_name: 464 self._icon.props.icon_name = icon_name 465 else: 466 channel = network.frequency_to_channel(self._frequency) 467 if state == network.DEVICE_STATE_ACTIVATED: 468 self._icon.props.icon_name = 'network-adhoc-%s-connected' \ 469 % channel 470 else: 471 self._icon.props.icon_name = 'network-adhoc-%s' % channel 472 self._icon.props.base_color = profile.get_color() 493 473 494 474 if state == network.DEVICE_STATE_PREPARE or \ 495 475 state == network.DEVICE_STATE_CONFIG or \ … … class WirelessDeviceView(ToolButton): 528 508 netmgr.DeactivateConnection(conn_o) 529 509 break 530 510 531 def __create_connection_cb(self, palette, data=None):532 """Create an 802.11 IBSS network.533 534 The user's color is encoded at the end of the network name. The network535 name is truncated so that it does not exceed the 32 byte SSID limit.536 """537 client = gconf.client_get_default()538 nick = client.get_string('/desktop/sugar/user/nick').decode('utf-8')539 color = client.get_string('/desktop/sugar/user/color')540 color_suffix = ' %s' % color541 542 format = _('%s\'s network').encode('utf-8')543 extra_length = (len(format) - len('%s')) + len(color_suffix)544 name_limit = 32 - extra_length545 546 # truncate the nick and use a regex to drop any partial characters547 # at the end548 nick = nick.encode('utf-8')[:name_limit]549 pattern = "([\xf6-\xf7][\x80-\xbf]{0,2}|[\xe0-\xef][\x80-\xbf]{0,1}|[\xc0-\xdf])$"550 nick = re.sub(pattern, '', nick)551 552 connection_name = format % nick553 connection_name += color_suffix554 555 connection = network.find_connection_by_ssid(connection_name)556 if connection is None:557 settings = Settings()558 settings.connection.id = 'Auto ' + connection_name559 uuid = settings.connection.uuid = unique_id()560 settings.connection.type = '802-11-wireless'561 settings.wireless.ssid = dbus.ByteArray(connection_name)562 settings.wireless.band = 'bg'563 settings.wireless.mode = 'adhoc'564 settings.ip4_config = IP4Config()565 settings.ip4_config.method = 'link-local'566 567 connection = network.add_connection(uuid, settings)568 569 obj = self._bus.get_object(_NM_SERVICE, _NM_PATH)570 netmgr = dbus.Interface(obj, _NM_IFACE)571 572 netmgr.ActivateConnection(network.SETTINGS_SERVICE,573 connection.path,574 self._device.object_path,575 '/',576 reply_handler=self.__activate_reply_cb,577 error_handler=self.__activate_error_cb)578 579 511 def __activate_reply_cb(self, connection): 580 512 logging.debug('Network created: %s', connection) 581 513 -
src/jarabe/desktop/meshbox.py
diff --git a/src/jarabe/desktop/meshbox.py b/src/jarabe/desktop/meshbox.py index e5ef720..b88b545 100644
a b 1 1 # Copyright (C) 2006-2007 Red Hat, Inc. 2 2 # Copyright (C) 2009 Tomeu Vizoso, Simon Schampijer 3 # Copyright (C) 2009 One Laptop per Child3 # Copyright (C) 2009-2010 One Laptop per Child 4 4 # 5 5 # This program is free software; you can redistribute it and/or modify 6 6 # it under the terms of the GNU General Public License as published by … … import dbus 24 24 import hippo 25 25 import gobject 26 26 import gtk 27 import gconf 27 28 28 29 from sugar.graphics.icon import CanvasIcon, Icon 29 30 from sugar.graphics.xocolor import XoColor … … from jarabe.model.network import IP4Config 52 53 from jarabe.model.network import WirelessSecurity 53 54 from jarabe.model.network import AccessPoint 54 55 from jarabe.model.olpcmesh import OlpcMeshManager 56 from jarabe.model.adhoc import get_adhoc_manager_instance 55 57 from jarabe.journal import misc 56 58 57 59 _NM_SERVICE = 'org.freedesktop.NetworkManager' … … _NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active' 66 68 _AP_ICON_NAME = 'network-wireless' 67 69 _OLPC_MESH_ICON_NAME = 'network-mesh' 68 70 71 69 72 class WirelessNetworkView(CanvasPulsingIcon): 70 73 def __init__(self, initial_ap): 71 74 CanvasPulsingIcon.__init__(self, size=style.STANDARD_ICON_SIZE, … … class WirelessNetworkView(CanvasPulsingIcon): 89 92 self._connection = None 90 93 self._color = None 91 94 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]) 95 if self._mode == network.NM_802_11_MODE_ADHOC and \ 96 network.is_sugar_adhoc_network(self._name): 97 self._color = profile.get_color() 97 98 else: 98 99 sha_hash = hashlib.sha1() 99 100 data = self._name + hex(self._flags) … … class WirelessNetworkView(CanvasPulsingIcon): 115 116 self.set_palette(self._palette) 116 117 self._palette_icon.props.xo_color = self._color 117 118 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" 119 if self._mode != network.NM_802_11_MODE_ADHOC: 120 if network.find_connection_by_ssid(self._name) is not None: 121 self.props.badge_name = "emblem-favorite" 122 self._palette_icon.props.badge_name = "emblem-favorite" 123 elif self._flags == network.NM_802_11_AP_FLAGS_PRIVACY: 124 self.props.badge_name = "emblem-locked" 125 self._palette_icon.props.badge_name = "emblem-locked" 126 else: 127 self.props.badge_name = None 128 self._palette_icon.props.badge_name = None 124 129 else: 125 130 self.props.badge_name = None 126 131 self._palette_icon.props.badge_name = None … … class WirelessNetworkView(CanvasPulsingIcon): 146 151 path=self._device.object_path, 147 152 dbus_interface=_NM_WIRELESS_IFACE) 148 153 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 154 154 def _create_palette(self): 155 155 icon_name = get_icon_state(_AP_ICON_NAME, self._strength) 156 156 self._palette_icon = Icon(icon_name=icon_name, … … class WirelessNetworkView(CanvasPulsingIcon): 221 221 else: 222 222 state = network.DEVICE_STATE_UNKNOWN 223 223 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: 224 if self._mode == network.NM_802_11_MODE_ADHOC and \ 225 network.is_sugar_adhoc_network(self._name): 226 channel = max([1] + [ap.channel for ap in 227 self._access_points.values()]) 228 if state == network.DEVICE_STATE_ACTIVATED: 229 icon_name = 'network-adhoc-%s-connected' % channel 230 else: 231 icon_name = 'network-adhoc-%s' % channel 236 232 self.props.icon_name = icon_name 237 233 icon = self._palette.props.icon 238 234 icon.props.icon_name = icon_name 235 else: 236 if state == network.DEVICE_STATE_ACTIVATED: 237 connection = network.find_connection_by_ssid(self._name) 238 if connection is not None: 239 if self._mode == network.NM_802_11_MODE_INFRA: 240 connection.set_connected() 241 icon_name = '%s-connected' % _AP_ICON_NAME 242 else: 243 icon_name = _AP_ICON_NAME 244 245 icon_name = get_icon_state(icon_name, self._strength) 246 if icon_name: 247 self.props.icon_name = icon_name 248 icon = self._palette.props.icon 249 icon.props.icon_name = icon_name 239 250 240 251 if state == network.DEVICE_STATE_PREPARE or \ 241 252 state == network.DEVICE_STATE_CONFIG or \ … … class WirelessNetworkView(CanvasPulsingIcon): 443 454 path=self._device.object_path, 444 455 dbus_interface=_NM_WIRELESS_IFACE) 445 456 457 class SugarAdhocView(CanvasPulsingIcon): 458 """To mimic the mesh behavior on devices where mesh hardware is 459 not available we support the creation of an Ad-hoc network on 460 three channels 1, 6, 11. This is the class for an icon 461 representing a channel in the neighborhood view. 462 463 """ 464 465 _ICON_NAME = 'network-adhoc-' 466 _NAME = 'Ad-hoc Network ' 467 468 def __init__(self, channel): 469 CanvasPulsingIcon.__init__(self, 470 icon_name=self._ICON_NAME + str(channel), 471 size=style.STANDARD_ICON_SIZE, cache=True) 472 self._bus = dbus.SystemBus() 473 self._channel = channel 474 self._disconnect_item = None 475 self._connect_item = None 476 self._palette_icon = None 477 self._greyed_out = False 478 479 get_adhoc_manager_instance().connect('members-changed', 480 self.__members_changed_cb) 481 get_adhoc_manager_instance().connect('state-changed', 482 self.__state_changed_cb) 483 484 self.connect('button-release-event', self.__button_release_event_cb) 485 486 pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), 487 style.COLOR_TRANSPARENT.get_svg())) 488 self.props.pulse_color = pulse_color 489 self._state_color = XoColor('%s,%s' % \ 490 (profile.get_color().get_stroke_color(), 491 style.COLOR_TRANSPARENT.get_svg())) 492 self.props.base_color = self._state_color 493 self._palette = self._create_palette() 494 self.set_palette(self._palette) 495 self._palette_icon.props.xo_color = self._state_color 496 497 def _create_palette(self): 498 self._palette_icon = Icon( \ 499 icon_name=self._ICON_NAME + str(self._channel), 500 icon_size=style.STANDARD_ICON_SIZE) 501 502 palette_ = palette.Palette(_("Ad-hoc Network %d") % self._channel, 503 icon=self._palette_icon) 504 505 self._connect_item = MenuItem(_('Connect'), 'dialog-ok') 506 self._connect_item.connect('activate', self.__connect_activate_cb) 507 palette_.menu.append(self._connect_item) 508 509 self._disconnect_item = MenuItem(_('Disconnect'), 'media-eject') 510 self._disconnect_item.connect('activate', 511 self.__disconnect_activate_cb) 512 palette_.menu.append(self._disconnect_item) 513 514 return palette_ 515 516 def __button_release_event_cb(self, icon, event): 517 get_adhoc_manager_instance().activate_channel(self._channel) 518 519 def __connect_activate_cb(self, icon): 520 get_adhoc_manager_instance().activate_channel(self._channel) 521 522 def __disconnect_activate_cb(self, icon): 523 get_adhoc_manager_instance().deactivate_active_channel() 524 525 def __state_changed_cb(self, adhoc_manager, channel, device_state): 526 if self._channel == channel: 527 state = device_state 528 else: 529 state = network.DEVICE_STATE_UNKNOWN 530 531 if state == network.DEVICE_STATE_ACTIVATED: 532 icon_name = '%s-connected' % (self._ICON_NAME + str(self._channel)) 533 else: 534 icon_name = self._ICON_NAME + str(self._channel) 535 536 self.props.base_color = self._state_color 537 self._palette_icon.props.xo_color = self._state_color 538 539 if icon_name is not None: 540 self.props.icon_name = icon_name 541 icon = self._palette.props.icon 542 icon.props.icon_name = icon_name 543 544 if state in [network.DEVICE_STATE_PREPARE, 545 network.DEVICE_STATE_CONFIG, 546 network.DEVICE_STATE_NEED_AUTH, 547 network.DEVICE_STATE_IP_CONFIG]: 548 if self._disconnect_item: 549 self._disconnect_item.show() 550 self._connect_item.hide() 551 self._palette.props.secondary_text = _('Connecting...') 552 self.props.pulsing = True 553 elif state == network.DEVICE_STATE_ACTIVATED: 554 if self._disconnect_item: 555 self._disconnect_item.show() 556 self._connect_item.hide() 557 self._palette.props.secondary_text = _('Connected') 558 self.props.pulsing = False 559 else: 560 if self._disconnect_item: 561 self._disconnect_item.hide() 562 self._connect_item.show() 563 self._palette.props.secondary_text = None 564 self.props.pulsing = False 565 566 def _update_color(self): 567 if self._greyed_out: 568 self.props.base_color = XoColor('#D5D5D5,#D5D5D5') 569 else: 570 self.props.base_color = self._state_color 571 572 def __members_changed_cb(self, adhoc_manager, channel, has_members): 573 if channel == self._channel: 574 if has_members == True: 575 self._state_color = profile.get_color() 576 self.props.base_color = self._state_color 577 self._palette_icon.props.xo_color = self._state_color 578 else: 579 color = '%s,%s' % (profile.get_color().get_stroke_color(), 580 style.COLOR_TRANSPARENT.get_svg()) 581 self._state_color = XoColor(color) 582 self.props.base_color = self._state_color 583 self._palette_icon.props.xo_color = self._state_color 584 585 def set_filter(self, query): 586 name = self._NAME + str(self._channel) 587 self._greyed_out = name.lower().find(query) == -1 588 self._update_color() 589 446 590 447 591 class OlpcMeshView(CanvasPulsingIcon): 448 592 def __init__(self, mesh_mgr, channel): … … class MeshToolbar(gtk.Toolbar): 762 906 return False 763 907 764 908 765 class DeviceObserver(object): 766 def __init__(self, box, device): 767 self._box = box 909 class DeviceObserver(gobject.GObject): 910 __gsignals__ = { 911 'access-point-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 912 ([gobject.TYPE_PYOBJECT])), 913 'access-point-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 914 ([gobject.TYPE_PYOBJECT])) 915 } 916 def __init__(self, device): 917 gobject.GObject.__init__(self) 768 918 self._bus = dbus.SystemBus() 769 self. _device = device919 self.device = device 770 920 771 wireless = dbus.Interface( self._device, _NM_WIRELESS_IFACE)921 wireless = dbus.Interface(device, _NM_WIRELESS_IFACE) 772 922 wireless.GetAccessPoints(reply_handler=self._get_access_points_reply_cb, 773 923 error_handler=self._get_access_points_error_cb) 774 924 … … class DeviceObserver(object): 784 934 def _get_access_points_reply_cb(self, access_points_o): 785 935 for ap_o in access_points_o: 786 936 ap = self._bus.get_object(_NM_SERVICE, ap_o) 787 self. _box.add_access_point(self._device, ap)937 self.emit('access-point-added', ap) 788 938 789 939 def _get_access_points_error_cb(self, err): 790 940 logging.error('Failed to get access points: %s', err) 791 941 792 942 def __access_point_added_cb(self, access_point_o): 793 943 ap = self._bus.get_object(_NM_SERVICE, access_point_o) 794 self. _box.add_access_point(self._device, ap)944 self.emit('access-point-added', ap) 795 945 796 946 def __access_point_removed_cb(self, access_point_o): 797 self. _box.remove_access_point(access_point_o)947 self.emit('access-point-removed', access_point_o) 798 948 799 949 def disconnect(self): 800 950 self._bus.remove_signal_receiver(self.__access_point_added_cb, 801 951 signal_name='AccessPointAdded', 802 path=self. _device.object_path,952 path=self.device.object_path, 803 953 dbus_interface=_NM_WIRELESS_IFACE) 804 954 self._bus.remove_signal_receiver(self.__access_point_removed_cb, 805 955 signal_name='AccessPointRemoved', 806 path=self. _device.object_path,956 path=self.device.object_path, 807 957 dbus_interface=_NM_WIRELESS_IFACE) 808 958 809 959 810 960 class NetworkManagerObserver(object): 961 962 _SHOW_ADHOC_GCONF_KEY = '/desktop/sugar/network/adhoc' 963 811 964 def __init__(self, box): 812 965 self._box = box 813 966 self._bus = None … … class NetworkManagerObserver(object): 815 968 self._netmgr = None 816 969 self._olpc_mesh_device_o = None 817 970 971 client = gconf.client_get_default() 972 self._have_adhoc_networks = client.get_bool(self._SHOW_ADHOC_GCONF_KEY) 973 818 974 def listen(self): 819 975 try: 820 976 self._bus = dbus.SystemBus() … … class NetworkManagerObserver(object): 833 989 self._bus.add_signal_receiver(self.__device_removed_cb, 834 990 signal_name='DeviceRemoved', 835 991 dbus_interface=_NM_IFACE) 992 self._bus.add_signal_receiver(self.__properties_changed_cb, 993 signal_name='PropertiesChanged', 994 dbus_interface=_NM_IFACE) 836 995 837 996 settings = network.get_settings() 838 997 if settings is not None: … … class NetworkManagerObserver(object): 876 1035 877 1036 device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType') 878 1037 if device_type == network.DEVICE_TYPE_802_11_WIRELESS: 879 self._devices[device_o] = DeviceObserver(self._box, device) 1038 self._devices[device_o] = DeviceObserver(device) 1039 self._devices[device_o].connect('access-point-added', 1040 self.__ap_added_cb) 1041 self._devices[device_o].connect('access-point-removed', 1042 self.__ap_removed_cb) 1043 if self._have_adhoc_networks: 1044 self._box.add_adhoc_networks(device) 880 1045 elif device_type == network.DEVICE_TYPE_802_11_OLPC_MESH: 881 1046 self._olpc_mesh_device_o = device_o 882 1047 self._box.enable_olpc_mesh(device) … … class NetworkManagerObserver(object): 892 1057 observer = self._devices[device_o] 893 1058 observer.disconnect() 894 1059 del self._devices[device_o] 1060 if self._have_adhoc_networks: 1061 self._box.remove_adhoc_networks() 895 1062 return 896 1063 897 1064 if self._olpc_mesh_device_o == device_o: 898 1065 self._box.disable_olpc_mesh(device_o) 899 1066 1067 def __ap_added_cb(self, device_observer, access_point): 1068 self._box.add_access_point(device_observer.device, access_point) 1069 1070 def __ap_removed_cb(self, device_observer, access_point_o): 1071 self._box.remove_access_point(access_point_o) 1072 1073 def __properties_changed_cb(self, properties): 1074 if 'WirelessHardwareEnabled' in properties: 1075 if properties['WirelessHardwareEnabled']: 1076 if not self._have_adhoc_networks: 1077 self._box.remove_adhoc_networks() 1078 elif properties['WirelessHardwareEnabled']: 1079 for device in self._devices: 1080 if self._have_adhoc_networks: 1081 self._box.add_adhoc_networks(device) 1082 1083 900 1084 class MeshBox(gtk.VBox): 901 1085 __gtype_name__ = 'SugarMeshBox' 902 1086 … … class MeshBox(gtk.VBox): 906 1090 gobject.GObject.__init__(self) 907 1091 908 1092 self.wireless_networks = {} 1093 self._adhoc_manager = None 1094 self._adhoc_networks = [] 909 1095 910 1096 self._model = neighborhood.get_model() 911 1097 self._buddies = {} … … class MeshBox(gtk.VBox): 1063 1249 ap.disconnect() 1064 1250 return 1065 1251 1252 if self._adhoc_manager is not None and \ 1253 network.is_sugar_adhoc_network(ap.name) and \ 1254 ap.mode == network.NM_802_11_MODE_ADHOC: 1255 if old_hash is None: # new Ad-hoc network finished initializing 1256 self._adhoc_manager.add_access_point(ap) 1257 # we are called as well in other cases but we do not need to 1258 # act here as we don't display signal strength for Ad-hoc networks 1259 return 1260 1066 1261 if old_hash is None: # new AP finished initializing 1067 1262 self._add_ap_to_network(ap) 1068 1263 return … … class MeshBox(gtk.VBox): 1085 1280 ap.initialize() 1086 1281 1087 1282 def remove_access_point(self, ap_o): 1283 if self._adhoc_manager is not None: 1284 if self._adhoc_manager.is_sugar_adhoc_access_point(ap_o): 1285 self._adhoc_manager.remove_access_point(ap_o) 1286 return 1287 1088 1288 # we don't keep an index of ap object path to network, but since 1089 1289 # we'll only ever have a handful of networks, just try them all... 1090 1290 for net in self.wireless_networks.values(): … … class MeshBox(gtk.VBox): 1101 1301 # it (e.g. olpc-mesh adhoc network) 1102 1302 logging.debug('Can not remove access point %s' % ap_o) 1103 1303 1304 def add_adhoc_networks(self, device): 1305 if self._adhoc_manager is None: 1306 self._adhoc_manager = get_adhoc_manager_instance() 1307 self._adhoc_manager.start_listening(device) 1308 self._add_adhoc_network_icon(1) 1309 self._add_adhoc_network_icon(6) 1310 self._add_adhoc_network_icon(11) 1311 self._adhoc_manager.autoconnect() 1312 1313 def remove_adhoc_networks(self): 1314 for icon in self._adhoc_networks: 1315 icon.disconnect() 1316 self._layout.remove(icon) 1317 self._adhoc_networks = [] 1318 1319 def _add_adhoc_network_icon(self, channel): 1320 icon = SugarAdhocView(channel) 1321 self._layout.add(icon) 1322 self._adhoc_networks.append(icon) 1323 1104 1324 def _add_olpc_mesh_icon(self, mesh_mgr, channel): 1105 1325 icon = OlpcMeshView(mesh_mgr, channel) 1106 1326 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 1 1 sugardir = $(pythondir)/jarabe/model 2 2 sugar_PYTHON = \ 3 adhoc.py \ 3 4 __init__.py \ 4 5 buddy.py \ 5 6 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..65dac01
- + 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 17 import logging 18 19 import dbus 20 import gobject 21 22 from jarabe.model import network 23 from jarabe.model.network import Settings 24 from sugar.util import unique_id 25 from 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_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless' 32 _NM_ACCESSPOINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint' 33 _NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active' 34 35 36 _adhoc_manager_instance = None 37 def get_adhoc_manager_instance(): 38 global _adhoc_manager_instance 39 if _adhoc_manager_instance is None: 40 _adhoc_manager_instance = AdHocManager() 41 return _adhoc_manager_instance 42 43 44 class AdHocManager(gobject.GObject): 45 """To mimic the mesh behavior on devices where mesh hardware is 46 not available we support the creation of an Ad-hoc network on 47 three channels 1, 6, 11. If Sugar sees no "known" network when it 48 starts, it does autoconnect to an Ad-hoc network. 49 50 """ 51 52 __gsignals__ = { 53 'members-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 54 ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])), 55 'state-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 56 ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])) 57 } 58 59 _AUTOCONNECT_TIMEOUT = 30 60 _CHANNEL_1 = 1 61 _CHANNEL_6 = 6 62 _CHANNEL_11 = 11 63 64 def __init__(self): 65 gobject.GObject.__init__(self) 66 67 self._bus = dbus.SystemBus() 68 self._device = None 69 self._idle_source = 0 70 self._listening_called = 0 71 self._device_state = network.DEVICE_STATE_UNKNOWN 72 73 self._current_channel = None 74 self._networks = {self._CHANNEL_1: None, 75 self._CHANNEL_6: None, 76 self._CHANNEL_11: None} 77 78 def start_listening(self, device): 79 self._listening_called += 1 80 if self._listening_called > 1: 81 raise RuntimeError('The start listening method can' \ 82 ' only be called once.') 83 84 self._device = device 85 props = dbus.Interface(device, 86 'org.freedesktop.DBus.Properties') 87 props.Get(_NM_DEVICE_IFACE, 'State', 88 reply_handler=self.__get_device_state_reply_cb, 89 error_handler=self.__get_state_error_cb) 90 91 self._bus.add_signal_receiver(self.__device_state_changed_cb, 92 signal_name='StateChanged', 93 path=self._device.object_path, 94 dbus_interface=_NM_DEVICE_IFACE) 95 96 self._bus.add_signal_receiver(self.__wireless_properties_changed_cb, 97 signal_name='PropertiesChanged', 98 path=self._device.object_path, 99 dbus_interface=_NM_WIRELESS_IFACE) 100 101 def stop_listening(self): 102 self._bus.remove_signal_receiver(self.__device_state_changed_cb, 103 signal_name='StateChanged', 104 path=self._device.object_path, 105 dbus_interface=_NM_DEVICE_IFACE) 106 self._bus.remove_signal_receiver(self.__wireless_properties_changed_cb, 107 signal_name='PropertiesChanged', 108 path=self._device.object_path, 109 dbus_interface=_NM_WIRELESS_IFACE) 110 111 def __get_state_error_cb(self, err): 112 logging.debug('Error getting the device state: %s', err) 113 114 def __get_device_state_reply_cb(self, state): 115 self._device_state = state 116 117 def __device_state_changed_cb(self, new_state, old_state, reason): 118 self._device_state = new_state 119 self._update_state() 120 121 def __wireless_properties_changed_cb(self, properties): 122 if 'ActiveAccessPoint' in properties and \ 123 properties['ActiveAccessPoint'] != '/': 124 active_ap = self._bus.get_object(_NM_SERVICE, 125 properties['ActiveAccessPoint']) 126 props = dbus.Interface(active_ap, dbus.PROPERTIES_IFACE) 127 props.GetAll(_NM_ACCESSPOINT_IFACE, byte_arrays=True, 128 reply_handler=self.__get_all_ap_props_reply_cb, 129 error_handler=self.__get_all_ap_props_error_cb) 130 131 def __get_all_ap_props_reply_cb(self, properties): 132 if properties['Mode'] == network.NM_802_11_MODE_ADHOC and \ 133 'Frequency' in properties: 134 frequency = properties['Frequency'] 135 self._current_channel = network.frequency_to_channel(frequency) 136 else: 137 self._current_channel = None 138 self._update_state() 139 140 def __get_all_ap_props_error_cb(self, err): 141 logging.error('Error getting the access point properties: %s', err) 142 143 def _update_state(self): 144 self.emit('state-changed', self._current_channel, self._device_state) 145 146 def _have_configured_connections(self): 147 return len(network.get_settings().connections) > 0 148 149 def autoconnect(self): 150 """Autoconnect to an Ad-hoc network""" 151 if self._have_configured_connections(): 152 self._autoconnect_adhoc_timer() 153 else: 154 self._autoconnect_adhoc() 155 156 def _autoconnect_adhoc_timer(self): 157 """Start a timer which basically looks for 30 seconds of inactivity 158 on the device, then does autoconnect to an Ad-hoc network. 159 160 """ 161 if self._idle_source != 0: 162 gobject.source_remove(self._idle_source) 163 self._idle_source = gobject.timeout_add_seconds( \ 164 self._AUTOCONNECT_TIMEOUT, self.__idle_check_cb) 165 166 def __idle_check_cb(self): 167 if self._device_state == network.DEVICE_STATE_DISCONNECTED: 168 logging.debug("Connect to Ad-hoc network due to inactivity.") 169 self._autoconnect_adhoc() 170 return False 171 172 def _autoconnect_adhoc(self): 173 """First we try if there is an Ad-hoc network that is used by other 174 learners in the area, if not we default to channel 1. 175 176 """ 177 if self._networks[self._CHANNEL_1] is not None: 178 self._connect(self._CHANNEL_1) 179 elif self._networks[self._CHANNEL_6] is not None: 180 self._connect(self._CHANNEL_6) 181 elif self._networks[self._CHANNEL_11] is not None: 182 self._connect(self._CHANNEL_11) 183 else: 184 self._connect(self._CHANNEL_1) 185 186 def activate_channel(self, channel): 187 """Activate a sugar Ad-hoc network. 188 189 Keyword arguments: 190 channel -- Channel to connect to (should be 1, 6, 11) 191 192 """ 193 self._connect(channel) 194 195 def _connect(self, channel): 196 name = "Ad-hoc Network %d" % channel 197 connection = network.find_connection_by_ssid(name) 198 if connection is None: 199 settings = Settings() 200 settings.connection.id = name 201 settings.connection.uuid = unique_id() 202 settings.connection.type = '802-11-wireless' 203 settings.wireless.ssid = dbus.ByteArray(name) 204 settings.wireless.band = 'bg' 205 settings.wireless.channel = channel 206 settings.wireless.mode = 'adhoc' 207 settings.ip4_config = IP4Config() 208 settings.ip4_config.method = 'link-local' 209 210 connection = network.add_connection(name, settings) 211 212 obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) 213 netmgr = dbus.Interface(obj, _NM_IFACE) 214 215 netmgr.ActivateConnection(network.SETTINGS_SERVICE, 216 connection.path, 217 self._device.object_path, 218 '/', 219 reply_handler=self.__activate_reply_cb, 220 error_handler=self.__activate_error_cb) 221 222 def deactivate_active_channel(self): 223 """Deactivate the current active channel.""" 224 obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) 225 netmgr = dbus.Interface(obj, _NM_IFACE) 226 227 netmgr_props = dbus.Interface(netmgr, dbus.PROPERTIES_IFACE) 228 netmgr_props.Get(_NM_IFACE, 'ActiveConnections', \ 229 reply_handler=self.__get_active_connections_reply_cb, 230 error_handler=self.__get_active_connections_error_cb) 231 232 def __get_active_connections_reply_cb(self, active_connections_o): 233 for connection_o in active_connections_o: 234 obj = self._bus.get_object(_NM_IFACE, connection_o) 235 props = dbus.Interface(obj, dbus.PROPERTIES_IFACE) 236 state = props.Get(_NM_ACTIVE_CONN_IFACE, 'State') 237 if state == network.NM_ACTIVE_CONNECTION_STATE_ACTIVATED: 238 access_point_o = props.Get(_NM_ACTIVE_CONN_IFACE, 239 'SpecificObject') 240 if access_point_o != '/': 241 obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) 242 netmgr = dbus.Interface(obj, _NM_IFACE) 243 netmgr.DeactivateConnection(connection_o) 244 245 def __get_active_connections_error_cb(self, err): 246 logging.error('Error getting the active connections: %s', err) 247 248 def __activate_reply_cb(self, connection): 249 logging.debug('Ad-hoc network created: %s', connection) 250 251 def __activate_error_cb(self, err): 252 logging.error('Failed to create Ad-hoc network: %s', err) 253 254 def add_access_point(self, access_point): 255 """Add an access point to a network and notify the view to idicate 256 the member change. 257 258 Keyword arguments: 259 access_point -- Access Point 260 261 """ 262 if access_point.name.endswith(' 1'): 263 self._networks[self._CHANNEL_1] = access_point 264 self.emit('members-changed', self._CHANNEL_1, True) 265 elif access_point.name.endswith(' 6'): 266 self._networks[self._CHANNEL_6] = access_point 267 self.emit('members-changed', self._CHANNEL_6, True) 268 elif access_point.name.endswith('11'): 269 self._networks[self._CHANNEL_11] = access_point 270 self.emit('members-changed', self._CHANNEL_11, True) 271 272 def is_sugar_adhoc_access_point(self, ap_object_path): 273 """Checks whether an access point is part of a sugar Ad-hoc network. 274 275 Keyword arguments: 276 ap_object_path -- Access Point object path 277 278 Return: Boolean 279 280 """ 281 for access_point in self._networks.values(): 282 if access_point is not None: 283 if access_point.model.object_path == ap_object_path: 284 return True 285 return False 286 287 def remove_access_point(self, ap_object_path): 288 """Remove an access point from a sugar Ad-hoc network. 289 290 Keyword arguments: 291 ap_object_path -- Access Point object path 292 293 """ 294 for channel in self._networks: 295 if self._networks[channel] is not None: 296 if self._networks[channel].model.object_path == ap_object_path: 297 self.emit('members-changed', channel, False) 298 self._networks[channel] = None 299 break -
src/jarabe/model/network.py
diff --git a/src/jarabe/model/network.py b/src/jarabe/model/network.py index 47db43f..984da67 100644
a b 1 1 # Copyright (C) 2008 Red Hat, Inc. 2 2 # Copyright (C) 2009 Tomeu Vizoso, Simon Schampijer 3 # Copyright (C) 2009 One Laptop per Child3 # Copyright (C) 2009-2010 One Laptop per Child 4 4 # Copyright (C) 2009 Paraguay Educa, Martin Abente 5 5 # Copyright (C) 2010 Plan Ceibal, Daniel Castelo 6 6 # … … GSM_PUK_PATH = '/desktop/sugar/network/gsm/puk' 100 100 _nm_settings = None 101 101 _conn_counter = 0 102 102 103 104 def frequency_to_channel(frequency): 105 """Returns the channel matching a given radio channel frequency. If a 106 frequency is not in the dictionary channel 1 will be returned. 107 108 Keyword arguments: 109 frequency -- The radio channel frequency in MHz. 110 111 Return: Channel 112 113 """ 114 ftoc = {2412: 1, 2417: 2, 2422: 3, 2427: 4, 115 2432: 5, 2437: 6, 2442: 7, 2447: 8, 116 2452: 9, 2457: 10, 2462: 11, 2467: 12, 117 2472: 13} 118 if frequency not in ftoc: 119 logging.warning("The frequency %s can not be mapped to a channel, " \ 120 "defaulting to channel 1.", frequncy) 121 return 1 122 return ftoc[frequency] 123 124 def is_sugar_adhoc_network(ssid): 125 """Checks whether an access point is a sugar Ad-hoc network. 126 127 Keyword arguments: 128 ssid -- Ssid of the access point. 129 130 Return: Boolean 131 132 """ 133 return ssid.startswith('Ad-hoc Network') 134 135 103 136 class WirelessSecurity(object): 104 137 def __init__(self): 105 138 self.key_mgmt = None … … class Wireless(object): 127 160 self.security = None 128 161 self.mode = None 129 162 self.band = None 163 self.channel = None 130 164 131 165 def get_dict(self): 132 166 wireless = {'ssid': self.ssid} … … class Wireless(object): 136 170 wireless['mode'] = self.mode 137 171 if self.band: 138 172 wireless['band'] = self.band 173 if self.channel: 174 wireless['channel'] = self.channel 139 175 return wireless 140 176 141 177 … … class AccessPoint(gobject.GObject): 476 512 self.wpa_flags = 0 477 513 self.rsn_flags = 0 478 514 self.mode = 0 515 self.channel = 0 479 516 480 517 def initialize(self): 481 518 model_props = dbus.Interface(self.model, … … class AccessPoint(gobject.GObject): 545 582 self.rsn_flags = properties['RsnFlags'] 546 583 if 'Mode' in properties: 547 584 self.mode = properties['Mode'] 585 if 'Frequency' in properties: 586 self.channel = frequency_to_channel(properties['Frequency']) 587 548 588 self._initialized = True 549 589 self.emit('props-changed', old_hash) 550 590