Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAjay Garg <ajay@activitycentral.com>2012-10-14 18:21:26 (GMT)
committer Ajay Garg <ajay@activitycentral.com>2012-10-15 15:48:42 (GMT)
commit9677e9fd273963ecd7be54022d40340c89c2a0c4 (patch)
tree70d93bcd60d4efa9839a0d1c7c22c1675ffc933e
parent81ada148b643f50d645a7ad650608430c1f494cf (diff)
3G-Network sharing.
Signed-off-by: Ajay Garg <ajay@activitycentral.com>
-rw-r--r--extensions/deviceicon/network.py222
-rw-r--r--src/jarabe/model/network.py8
2 files changed, 192 insertions, 38 deletions
diff --git a/extensions/deviceicon/network.py b/extensions/deviceicon/network.py
index 79bc764..8ca9077 100644
--- a/extensions/deviceicon/network.py
+++ b/extensions/deviceicon/network.py
@@ -23,6 +23,8 @@ import logging
import hashlib
import socket
import struct
+import random
+import re
import datetime
import time
from gi.repository import Gtk
@@ -30,6 +32,7 @@ import glib
from gi.repository import GObject
from gi.repository import GConf
import dbus
+import uuid
from sugar3.graphics.icon import get_icon_state
from sugar3.graphics import style
@@ -55,6 +58,14 @@ _GSM_STATE_CONNECTING = 2
_GSM_STATE_CONNECTED = 3
_GSM_STATE_FAILED = 4
+_GSM_SHARING_PRIVATE = 0
+_GSM_SHARING_TRYING = 1
+_GSM_SHARING_NEIGHBORHOOD = 2
+
+_GSM_SHARING_CHANNELS = [2,3,4,5,7,8,9,10,12,13]
+
+_wifi_device = None
+
class WirelessPalette(Palette):
__gtype_name__ = 'SugarWirelessPalette'
@@ -200,6 +211,8 @@ class GsmPalette(Palette):
__gsignals__ = {
'gsm-connect': (GObject.SignalFlags.RUN_FIRST, None, ([])),
'gsm-disconnect': (GObject.SignalFlags.RUN_FIRST, None, ([])),
+ 'gsm-private': (GObject.SignalFlags.RUN_FIRST, None, ([])),
+ 'gsm-neighborhood': (GObject.SignalFlags.RUN_FIRST, None, ([])),
}
def __init__(self):
@@ -208,6 +221,7 @@ class GsmPalette(Palette):
self._current_state = None
self._failed_connection = False
+ self._sharing_state = _GSM_SHARING_PRIVATE
self.info_box = Gtk.VBox()
@@ -216,6 +230,11 @@ class GsmPalette(Palette):
self.info_box.pack_start(self._toggle_state_item, True, True, 0)
self._toggle_state_item.show()
+ self._sharing_box = Gtk.VBox()
+ self.info_box.pack_start(self._sharing_box, True, True, 0)
+ self.__update_sharing_toggle_widget(_('Private (Click to share)'), 'zoom-home')
+ self._sharing_box.hide()
+
self.error_title_label = Gtk.Label(label="")
self.error_title_label.set_alignment(0, 0.5)
self.error_title_label.set_line_wrap(True)
@@ -298,6 +317,9 @@ class GsmPalette(Palette):
icon = Icon(icon_name='media-eject', \
icon_size=Gtk.IconSize.MENU)
self._toggle_state_item.set_image(icon)
+ self.sharing_update_text()
+ self._sharing_toggle_item.show()
+ return
elif self._current_state == _GSM_STATE_FAILED:
message_error = self._get_error_by_nm_reason(reason)
@@ -306,6 +328,8 @@ class GsmPalette(Palette):
raise ValueError('Invalid GSM state while updating label and ' \
'text, %s' % str(self._current_state))
+ self._sharing_toggle_item.hide()
+
def __toggle_state_cb(self, menuitem):
if self._current_state == _GSM_STATE_NOT_READY:
pass
@@ -366,6 +390,50 @@ class GsmPalette(Palette):
message_tuple = (network.get_error_by_reason(reason), message)
return message_tuple
+ def sharing_update_text(self):
+ if self._sharing_state == _GSM_SHARING_PRIVATE:
+ self.__update_sharing_toggle_widget(_('Private (Click to share)'), 'zoom-home')
+
+ elif self._sharing_state == _GSM_SHARING_TRYING:
+ self.__update_sharing_toggle_widget(_('Please wait...'), 'zoom-home')
+
+ elif self._sharing_state == _GSM_SHARING_NEIGHBORHOOD:
+ self.__update_sharing_toggle_widget(_('Neighborhood (Click to unshare)'), 'zoom-neighborhood')
+
+ else:
+ raise ValueError('Invalid GSM sharing state while updating, %s' % \
+ str(self._sharing_state))
+
+ def __update_sharing_toggle_widget(self, label, icon_name):
+ for child_widget in self._sharing_box.get_children():
+ self._sharing_box.remove(child_widget)
+
+ self._sharing_toggle_item = PaletteMenuItem('')
+ self._sharing_toggle_item.connect('activate', self.__sharing_toggle_cb)
+ self._sharing_toggle_item.set_label(label)
+ icon = Icon(icon_name=icon_name, icon_size=Gtk.IconSize.MENU)
+ self._sharing_toggle_item.set_image(icon)
+ icon.show()
+ self._sharing_box.pack_start(self._sharing_toggle_item, True, True, 0)
+ separator = PaletteMenuItemSeparator()
+ self._sharing_box.pack_start(separator, True, True, 0)
+ separator.show()
+ self._sharing_box.show_all()
+
+ def __sharing_toggle_cb(self, menuitem):
+ if self._sharing_state == _GSM_SHARING_PRIVATE:
+ self.emit('gsm-neighborhood')
+
+ elif self._sharing_state == _GSM_SHARING_TRYING:
+ pass
+
+ elif self._sharing_state == _GSM_SHARING_NEIGHBORHOOD:
+ self.emit('gsm-private')
+
+ else:
+ raise ValueError('Invalid GSM sharing state, %s' % \
+ str(self._sharing_state))
+
class WirelessDeviceView(ToolButton):
@@ -527,17 +595,8 @@ class WirelessDeviceView(ToolButton):
else:
state = network.NM_DEVICE_STATE_UNKNOWN
- if self._mode != network.NM_802_11_MODE_ADHOC and \
- network.is_sugar_adhoc_network(self._ssid) == False:
- if state == network.NM_DEVICE_STATE_ACTIVATED:
- icon_name = '%s-connected' % 'network-wireless'
- else:
- icon_name = 'network-wireless'
-
- icon_name = get_icon_state(icon_name, self._strength)
- if icon_name:
- self._icon.props.icon_name = icon_name
- else:
+ if self._mode == network.NM_802_11_MODE_ADHOC and \
+ network.is_sugar_adhoc_network(self._ssid):
channel = network.frequency_to_channel(self._frequency)
if state == network.NM_DEVICE_STATE_ACTIVATED:
self._icon.props.icon_name = 'network-adhoc-%s-connected' \
@@ -729,8 +788,9 @@ class GsmDeviceView(TrayIcon):
def __init__(self, device):
self._connection_time_handler = None
-
self._connection_timestamp = 0
+ self._shared_connection_path = None
+ self._target_dev_path = None
client = GConf.Client.get_default()
color = xocolor.XoColor(client.get_string('/desktop/sugar/user/color'))
@@ -758,6 +818,8 @@ class GsmDeviceView(TrayIcon):
palette.set_group_id('frame')
palette.connect('gsm-connect', self.__gsm_connect_cb)
palette.connect('gsm-disconnect', self.__gsm_disconnect_cb)
+ palette.connect('gsm-neighborhood', self.__gsm_start_sharing_cb)
+ palette.connect('gsm-private', self.__gsm_stop_sharing_cb)
self._palette = palette
@@ -775,42 +837,32 @@ class GsmDeviceView(TrayIcon):
def __gsm_connect_cb(self, palette, data=None):
connection = network.find_gsm_connection()
if connection is not None:
- connection.activate(self._device.object_path,
- reply_handler=self.__connect_cb,
- error_handler=self.__connect_error_cb)
+ network.activate_connection_by_path(connection.get_path(),
+ self._device.object_path,
+ reply_handler=self._connect_cb,
+ error_handler=self._connect_error_cb)
else:
self._palette.add_alert(_('No GSM connection available.'), \
_('Create a connection in the ' \
'control panel.'))
- def __connect_cb(self, active_connection):
+ def _connect_cb(self, active_connection_path):
+ self._base_gsm_connection_path = active_connection_path
logging.debug('Connected successfully to gsm device, %s',
- active_connection)
+ active_connection_path)
- def __connect_error_cb(self, error):
+ def _connect_error_cb(self, error):
raise RuntimeError('Error when connecting to gsm device, %s' % error)
def __gsm_disconnect_cb(self, palette, data=None):
- obj = self._bus.get_object(network.NM_SERVICE, network.NM_PATH)
- netmgr = dbus.Interface(obj, network.NM_IFACE)
- netmgr_props = dbus.Interface(netmgr, dbus.PROPERTIES_IFACE)
- active_connections_o = netmgr_props.Get(network.NM_IFACE, 'ActiveConnections')
+ network.get_manager().DeactivateConnection(self._base_gsm_connection_path,
+ reply_handler=self._disconnect_cb,
+ error_handler=self._disconnect_error_cb)
- for conn_o in active_connections_o:
- obj = self._bus.get_object(network.NM_IFACE, conn_o)
- props = dbus.Interface(obj, dbus.PROPERTIES_IFACE)
- devices = props.Get(network.NM_ACTIVE_CONN_IFACE, 'Devices')
- if self._device.object_path in devices:
- netmgr.DeactivateConnection(
- conn_o,
- reply_handler=self.__disconnect_cb,
- error_handler=self.__disconnect_error_cb)
- break
-
- def __disconnect_cb(self):
+ def _disconnect_cb(self):
logging.debug('Disconnected successfully gsm device')
- def __disconnect_error_cb(self, error):
+ def _disconnect_error_cb(self, error):
raise RuntimeError('Error when disconnecting gsm device, %s' % error)
def __state_changed_cb(self, new_state, old_state, reason):
@@ -831,6 +883,10 @@ class GsmDeviceView(TrayIcon):
gsm_state = _GSM_STATE_CONNECTED
connection = network.find_gsm_connection()
if connection is not None:
+ # Introspect the settings's keys once; else sometimes
+ # the key 'timestamp' gets missed.
+ connection.get_settings('connection').keys()
+
self._connection_timestamp = time.time() - \
connection.get_settings('connection')['timestamp']
self._connection_time_handler = GObject.timeout_add_seconds( \
@@ -879,6 +935,95 @@ class GsmDeviceView(TrayIcon):
self._palette.update_connection_time(connection_time)
return True
+ def __gsm_start_sharing_cb(self, palette):
+ if self._palette._sharing_state == _GSM_SHARING_PRIVATE:
+ logging.debug('GSM will start sharing now')
+ self._palette._sharing_state = _GSM_SHARING_TRYING
+ self._palette.sharing_update_text()
+
+ self._target_device = _wifi_device
+ self._target_device_path = self._target_device.object_path
+
+ client = GConf.Client.get_default()
+ nick = client.get_string('/desktop/sugar/user/nick')
+ nick = re.sub('\W', '', nick)
+
+ name_format = '%s network'
+ format_length = len(name_format) - len('%s')
+ nick_length = 31 - format_length
+ name = name_format % nick[:nick_length]
+
+ connection = network.find_connection_by_ssid(name)
+ if connection == None:
+ settings = network.Settings()
+ settings.connection.id = name
+ settings.connection.uuid = str(uuid.uuid4())
+ settings.connection.type = '802-11-wireless'
+ settings.wireless.ssid = dbus.ByteArray(name)
+ settings.wireless.mode = 'adhoc'
+ settings.wireless.band = 'bg'
+ chosen_channel = random.randrange(len(_GSM_SHARING_CHANNELS))
+ settings.wireless.channel = _GSM_SHARING_CHANNELS[chosen_channel]
+ settings.ip4_config = network.IP4Config()
+ settings.ip4_config.method = 'shared'
+ network.add_and_activate_connection(self._target_device,
+ settings,
+ '/',
+ self._gsm_sharing_ok_cb_for_add_and_activate,
+ self._gsm_sharing_error_cb)
+ else:
+ network.activate_connection_by_path(connection.get_path(),
+ self._target_device,
+ self._gsm_sharing_ok_cb,
+ self._gsm_sharing_error_cb)
+
+ def _gsm_sharing_ok_cb_for_add_and_activate(self,
+ new_connection_path,
+ active_connection_path):
+ self._gsm_sharing_ok_cb(active_connection_path)
+
+ def _gsm_sharing_ok_cb(self, connection_path):
+ logging.debug('GSM sharing is enabled')
+ self._shared_connection_path = connection_path
+ self._bus.add_signal_receiver(self._gsm_sharing_changed_cb,
+ signal_name='StateChanged',
+ path=self._target_device_path,
+ dbus_interface=network.NM_DEVICE_IFACE)
+ self._palette._sharing_state = _GSM_SHARING_NEIGHBORHOOD
+ self._palette.sharing_update_text()
+
+ def _gsm_sharing_changed_cb(self, new_state, old_state, reason):
+ if new_state == network.NM_DEVICE_STATE_DISCONNECTED:
+ self._gsm_sharing_reset()
+
+ def _gsm_sharing_reset(self):
+ logging.debug('GSM sharing is disabled')
+ if self._target_dev_path != None:
+ self._bus.remove_signal_receiver(self._gsm_sharing_changed_cb,
+ signal_name='StateChanged',
+ path=self._target_dev_path,
+ dbus_interface=network.NM_DEVICE_IFACE)
+ self._shared_connection_path = None
+ self._target_dev_path = None
+ self._palette._sharing_state = _GSM_SHARING_PRIVATE
+ self._palette.sharing_update_text()
+
+ def _gsm_sharing_error_cb(self, error):
+ logging.debug('GSM sharing could not start: %s' % str(error))
+ self._gsm_sharing_reset()
+
+ def __gsm_stop_sharing_cb(self, palette):
+ logging.debug('GSM will stop sharing now')
+ network.get_manager().DeactivateConnection(self._shared_connection_path,
+ reply_handler=self._gsm_stop_sharing_ok_cb,
+ error_handler=self._gsm_stop_sharing_error_cb)
+
+ def _gsm_stop_sharing_ok_cb(self):
+ self._gsm_sharing_reset()
+
+ def _gsm_stop_sharing_error_cb(self):
+ logging.debug('GSM sharing could not stop')
+
class WirelessDeviceObserver(object):
def __init__(self, device, tray):
@@ -1056,6 +1201,8 @@ class NetworkManagerObserver(object):
device = WiredDeviceObserver(nm_device, self._tray)
self._devices[device_op] = device
elif device_type == network.NM_DEVICE_TYPE_WIFI:
+ global _wifi_device
+ _wifi_device = nm_device
device = WirelessDeviceObserver(nm_device, self._tray)
self._devices[device_op] = device
elif device_type == network.NM_DEVICE_TYPE_OLPC_MESH:
@@ -1075,5 +1222,10 @@ class NetworkManagerObserver(object):
del self._devices[device_op]
+def get_wifi_device():
+ global _wifi_device
+ return _wifi_device
+
+
def setup(tray):
device_observer = NetworkManagerObserver(tray)
diff --git a/src/jarabe/model/network.py b/src/jarabe/model/network.py
index fa7acba..c60f6af 100644
--- a/src/jarabe/model/network.py
+++ b/src/jarabe/model/network.py
@@ -910,12 +910,14 @@ def activate_connection_by_path(connection, device_o,
error_handler=error_handler)
-def add_and_activate_connection(device_o, settings, specific_object):
+def add_and_activate_connection(device_o, settings, specific_object,
+ reply_handler=_add_and_activate_reply_cb,
+ error_handler=_add_and_activate_error_cb):
manager = get_manager()
manager.AddAndActivateConnection(settings.get_dict(), device_o,
specific_object,
- reply_handler=_add_and_activate_reply_cb,
- error_handler=_add_and_activate_error_cb)
+ reply_handler=reply_handler,
+ error_handler=error_handler)
def _migrate_old_wifi_connections():