Add buddy ip4-address property (temporary)
This commit is contained in:
parent
0ebba0d454
commit
570c7e6052
@ -47,6 +47,9 @@ _PROP_COLOR = "color"
|
|||||||
_PROP_OWNER = "owner"
|
_PROP_OWNER = "owner"
|
||||||
_PROP_VALID = "valid"
|
_PROP_VALID = "valid"
|
||||||
|
|
||||||
|
# Will go away soon
|
||||||
|
_PROP_IP4_ADDRESS = "ip4-address"
|
||||||
|
|
||||||
class Buddy(DBusGObject):
|
class Buddy(DBusGObject):
|
||||||
"""Person on the network (tracks properties and shared activites)
|
"""Person on the network (tracks properties and shared activites)
|
||||||
|
|
||||||
@ -86,7 +89,8 @@ class Buddy(DBusGObject):
|
|||||||
_PROP_COLOR : (str, None, None, None, gobject.PARAM_READWRITE),
|
_PROP_COLOR : (str, None, None, None, gobject.PARAM_READWRITE),
|
||||||
_PROP_CURACT : (str, None, None, None, gobject.PARAM_READWRITE),
|
_PROP_CURACT : (str, None, None, None, gobject.PARAM_READWRITE),
|
||||||
_PROP_VALID : (bool, None, None, False, gobject.PARAM_READABLE),
|
_PROP_VALID : (bool, None, None, False, gobject.PARAM_READABLE),
|
||||||
_PROP_OWNER : (bool, None, None, False, gobject.PARAM_READABLE)
|
_PROP_OWNER : (bool, None, None, False, gobject.PARAM_READABLE),
|
||||||
|
_PROP_IP4_ADDRESS : (str, None, None, None, gobject.PARAM_READWRITE)
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, bus_name, object_id, **kwargs):
|
def __init__(self, bus_name, object_id, **kwargs):
|
||||||
@ -120,11 +124,12 @@ class Buddy(DBusGObject):
|
|||||||
self._current_activity = None
|
self._current_activity = None
|
||||||
self._nick = None
|
self._nick = None
|
||||||
self._color = None
|
self._color = None
|
||||||
|
self._ip4_address = None
|
||||||
|
|
||||||
if not kwargs.get(_PROP_KEY):
|
if not kwargs.get(_PROP_KEY):
|
||||||
raise ValueError("key required")
|
raise ValueError("key required")
|
||||||
|
|
||||||
_ALLOWED_INIT_PROPS = [_PROP_NICK, _PROP_KEY, _PROP_ICON, _PROP_CURACT, _PROP_COLOR]
|
_ALLOWED_INIT_PROPS = [_PROP_NICK, _PROP_KEY, _PROP_ICON, _PROP_CURACT, _PROP_COLOR, _PROP_IP4_ADDRESS]
|
||||||
for (key, value) in kwargs.items():
|
for (key, value) in kwargs.items():
|
||||||
if key not in _ALLOWED_INIT_PROPS:
|
if key not in _ALLOWED_INIT_PROPS:
|
||||||
logging.debug("Invalid init property '%s'; ignoring..." % key)
|
logging.debug("Invalid init property '%s'; ignoring..." % key)
|
||||||
@ -155,6 +160,8 @@ class Buddy(DBusGObject):
|
|||||||
return self._valid
|
return self._valid
|
||||||
elif pspec.name == _PROP_OWNER:
|
elif pspec.name == _PROP_OWNER:
|
||||||
return self._owner
|
return self._owner
|
||||||
|
elif pspec.name == _PROP_IP4_ADDRESS:
|
||||||
|
return self._ip4_address
|
||||||
|
|
||||||
def do_set_property(self, pspec, value):
|
def do_set_property(self, pspec, value):
|
||||||
"""Set given property
|
"""Set given property
|
||||||
@ -177,7 +184,11 @@ class Buddy(DBusGObject):
|
|||||||
elif pspec.name == _PROP_CURACT:
|
elif pspec.name == _PROP_CURACT:
|
||||||
self._current_activity = value
|
self._current_activity = value
|
||||||
elif pspec.name == _PROP_KEY:
|
elif pspec.name == _PROP_KEY:
|
||||||
|
if self._key:
|
||||||
|
raise RuntimeError("Key already set.")
|
||||||
self._key = value
|
self._key = value
|
||||||
|
elif pspec.name == _PROP_IP4_ADDRESS:
|
||||||
|
self._ip4_address = value
|
||||||
|
|
||||||
self._update_validity()
|
self._update_validity()
|
||||||
|
|
||||||
@ -259,6 +270,12 @@ class Buddy(DBusGObject):
|
|||||||
props[_PROP_OWNER] = self.props.owner
|
props[_PROP_OWNER] = self.props.owner
|
||||||
props[_PROP_KEY] = self.props.key
|
props[_PROP_KEY] = self.props.key
|
||||||
props[_PROP_COLOR] = self.props.color
|
props[_PROP_COLOR] = self.props.color
|
||||||
|
|
||||||
|
if self.props.ip4_address:
|
||||||
|
props[_PROP_IP4_ADDRESS] = self.props.ip4_address
|
||||||
|
else:
|
||||||
|
props[_PROP_IP4_ADDRESS] = ""
|
||||||
|
|
||||||
if self.props.current_activity:
|
if self.props.current_activity:
|
||||||
props[_PROP_CURACT] = self.props.current_activity
|
props[_PROP_CURACT] = self.props.current_activity
|
||||||
else:
|
else:
|
||||||
@ -346,6 +363,12 @@ class Buddy(DBusGObject):
|
|||||||
self._current_activity = curact
|
self._current_activity = curact
|
||||||
changed_props[_PROP_CURACT] = curact
|
changed_props[_PROP_CURACT] = curact
|
||||||
changed = True
|
changed = True
|
||||||
|
if _PROP_IP4_ADDRESS in properties.keys():
|
||||||
|
ip4addr = properties[_PROP_IP4_ADDRESS]
|
||||||
|
if ip4addr != self._ip4_address:
|
||||||
|
self._ip4_address = ip4addr
|
||||||
|
changed_props[_PROP_IP4_ADDRESS] = ip4addr
|
||||||
|
changed = True
|
||||||
|
|
||||||
if not changed or not len(changed_props.keys()):
|
if not changed or not len(changed_props.keys()):
|
||||||
return
|
return
|
||||||
@ -378,6 +401,176 @@ class Buddy(DBusGObject):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
self._valid = False
|
self._valid = False
|
||||||
|
|
||||||
|
|
||||||
|
NM_SERVICE = 'org.freedesktop.NetworkManager'
|
||||||
|
NM_IFACE = 'org.freedesktop.NetworkManager'
|
||||||
|
NM_IFACE_DEVICES = 'org.freedesktop.NetworkManager.Devices'
|
||||||
|
NM_PATH = '/org/freedesktop/NetworkManager'
|
||||||
|
|
||||||
|
class IP4AddressMonitor(gobject.GObject):
|
||||||
|
"""This class, and direct buddy IPv4 address access, will go away quite soon"""
|
||||||
|
|
||||||
|
__gsignals__ = {
|
||||||
|
'address-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||||
|
([gobject.TYPE_PYOBJECT]))
|
||||||
|
}
|
||||||
|
|
||||||
|
__gproperties__ = {
|
||||||
|
'address' : (str, None, None, None, gobject.PARAM_READABLE)
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
gobject.GObject.__init__(self)
|
||||||
|
self._nm_present = False
|
||||||
|
self._matches = []
|
||||||
|
self._addr = None
|
||||||
|
self._nm_obj = None
|
||||||
|
|
||||||
|
sys_bus = dbus.SystemBus()
|
||||||
|
bus_object = sys_bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
|
||||||
|
try:
|
||||||
|
if bus_object.GetNameOwner(NM_SERVICE, dbus_interface='org.freedesktop.DBus'):
|
||||||
|
self._nm_present = True
|
||||||
|
except dbus.DBusException:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if self._nm_present:
|
||||||
|
self._connect_to_nm()
|
||||||
|
else:
|
||||||
|
addr = self._get_address_fallback()
|
||||||
|
self._update_address(addr)
|
||||||
|
|
||||||
|
def do_get_property(self, pspec):
|
||||||
|
if pspec.name == "address":
|
||||||
|
return self._addr
|
||||||
|
|
||||||
|
def _update_address(self, new_addr):
|
||||||
|
if new_addr == "0.0.0.0":
|
||||||
|
new_addr = None
|
||||||
|
if new_addr == self._addr:
|
||||||
|
return
|
||||||
|
|
||||||
|
self._addr = new_addr
|
||||||
|
logging.debug("IP4 address now '%s'" % new_addr)
|
||||||
|
self.emit('address-changed', new_addr)
|
||||||
|
|
||||||
|
def _connect_to_nm(self):
|
||||||
|
"""Connect to NM device state signals to tell when the IPv4 address changes"""
|
||||||
|
try:
|
||||||
|
sys_bus = dbus.SystemBus()
|
||||||
|
proxy = sys_bus.get_object(NM_SERVICE, NM_PATH)
|
||||||
|
self._nm_obj = dbus.Interface(proxy, NM_IFACE)
|
||||||
|
except dbus.DBusException, err:
|
||||||
|
logging.debug("Error finding NetworkManager: %s" % err)
|
||||||
|
self._nm_present = False
|
||||||
|
return
|
||||||
|
|
||||||
|
sys_bus = dbus.SystemBus()
|
||||||
|
match = sys_bus.add_signal_receiver(self._nm_device_active_cb,
|
||||||
|
signal_name="DeviceNowActive",
|
||||||
|
dbus_interface=NM_IFACE)
|
||||||
|
self._matches.append(match)
|
||||||
|
|
||||||
|
match = sys_bus.add_signal_receiver(self._nm_device_no_longer_active_cb,
|
||||||
|
signal_name="DeviceNoLongerActive",
|
||||||
|
dbus_interface=NM_IFACE,
|
||||||
|
named_service=NM_SERVICE)
|
||||||
|
self._matches.append(match)
|
||||||
|
|
||||||
|
match = sys_bus.add_signal_receiver(self._nm_state_change_cb,
|
||||||
|
signal_name="StateChange",
|
||||||
|
dbus_interface=NM_IFACE,
|
||||||
|
named_service=NM_SERVICE)
|
||||||
|
self._matches.append(match)
|
||||||
|
|
||||||
|
state = self._nm_obj.state()
|
||||||
|
if state == 3: # NM_STATE_CONNECTED
|
||||||
|
self._query_devices()
|
||||||
|
|
||||||
|
def _device_properties_cb(self, *props):
|
||||||
|
active = props[4]
|
||||||
|
if not active:
|
||||||
|
return
|
||||||
|
act_stage = props[5]
|
||||||
|
# HACK: OLPC NM has an extra stage, so activated == 8 on OLPC
|
||||||
|
# but 7 everywhere else
|
||||||
|
if act_stage != 8 and act_stage != 7:
|
||||||
|
# not activated
|
||||||
|
return
|
||||||
|
self._update_address(props[6])
|
||||||
|
|
||||||
|
def _device_properties_error_cb(self, err):
|
||||||
|
logging.debug("Error querying device properties: %s" % err)
|
||||||
|
|
||||||
|
def _query_device_properties(self, device):
|
||||||
|
sys_bus = dbus.SystemBus()
|
||||||
|
proxy = sys_bus.get_object(NM_SERVICE, device)
|
||||||
|
dev = dbus.Interface(proxy, NM_IFACE_DEVICES)
|
||||||
|
dev.getProperties(reply_handler=self._device_properties_cb,
|
||||||
|
error_handler=self._device_properties_error_cb)
|
||||||
|
|
||||||
|
def _get_devices_cb(self, ops):
|
||||||
|
"""Query each device's properties"""
|
||||||
|
for op in ops:
|
||||||
|
self._query_device_properties(op)
|
||||||
|
|
||||||
|
def _get_devices_error_cb(self, err):
|
||||||
|
logging.debug("Error getting NetworkManager devices: %s" % err)
|
||||||
|
|
||||||
|
def _query_devices(self):
|
||||||
|
"""Query NM for a list of network devices"""
|
||||||
|
self._nm_obj.getDevices(reply_handler=self._get_devices_cb,
|
||||||
|
error_handler=self._get_devices_error_cb)
|
||||||
|
|
||||||
|
def _nm_device_active_cb(self, device, ssid=None):
|
||||||
|
self._query_device_properties(device)
|
||||||
|
|
||||||
|
def _nm_device_no_longer_active_cb(self, device):
|
||||||
|
self._update_address(None)
|
||||||
|
|
||||||
|
def _nm_state_change_cb(self, new_state):
|
||||||
|
if new_state == 4: # NM_STATE_DISCONNECTED
|
||||||
|
self._update_address(None)
|
||||||
|
|
||||||
|
def handle_name_owner_changed(self, name, old, new):
|
||||||
|
"""Clear state when NM goes away"""
|
||||||
|
if name != NM_SERVICE:
|
||||||
|
return
|
||||||
|
if (old and len(old)) and (not new and not len(new)):
|
||||||
|
# NM went away
|
||||||
|
self._nm_present = False
|
||||||
|
for match in self._matches:
|
||||||
|
match.remove()
|
||||||
|
self._matches = []
|
||||||
|
self._update_address(None)
|
||||||
|
elif (not old and not len(old)) and (new and len(new)):
|
||||||
|
# NM started up
|
||||||
|
self._nm_present = True
|
||||||
|
self._connect_to_nm()
|
||||||
|
|
||||||
|
def _get_iface_address(self, iface):
|
||||||
|
import socket
|
||||||
|
import fcntl
|
||||||
|
import struct
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
fd = s.fileno()
|
||||||
|
SIOCGIFADDR = 0x8915
|
||||||
|
addr = fcntl.ioctl(fd, SIOCGIFADDR, struct.pack('256s', iface[:15]))[20:24]
|
||||||
|
s.close()
|
||||||
|
return socket.inet_ntoa(addr)
|
||||||
|
|
||||||
|
def _get_address_fallback(self):
|
||||||
|
import commands
|
||||||
|
(s, o) = commands.getstatusoutput("/sbin/route -n")
|
||||||
|
if s != 0:
|
||||||
|
return
|
||||||
|
for line in o.split('\n'):
|
||||||
|
fields = line.split(" ")
|
||||||
|
if fields[0] == "0.0.0.0":
|
||||||
|
iface = fields[len(fields) - 1]
|
||||||
|
return self._get_iface_address(iface)
|
||||||
|
return None
|
||||||
|
|
||||||
class GenericOwner(Buddy):
|
class GenericOwner(Buddy):
|
||||||
"""Common functionality for Local User-like objects
|
"""Common functionality for Local User-like objects
|
||||||
|
|
||||||
@ -421,6 +614,23 @@ class GenericOwner(Buddy):
|
|||||||
Buddy.__init__(self, bus_name, object_id, **kwargs)
|
Buddy.__init__(self, bus_name, object_id, **kwargs)
|
||||||
self._owner = True
|
self._owner = True
|
||||||
|
|
||||||
|
self._bus = dbus.SessionBus()
|
||||||
|
self._bus.add_signal_receiver(self._name_owner_changed_cb,
|
||||||
|
signal_name="NameOwnerChanged",
|
||||||
|
dbus_interface="org.freedesktop.DBus")
|
||||||
|
|
||||||
|
self._ip4_addr_monitor = IP4AddressMonitor()
|
||||||
|
self._ip4_addr_monitor.connect("address-changed", self._ip4_address_changed_cb)
|
||||||
|
|
||||||
|
def _ip4_address_changed_cb(self, monitor, address):
|
||||||
|
"""Handle IPv4 address change, set property to generate event"""
|
||||||
|
props = {_PROP_IP4_ADDRESS: address}
|
||||||
|
self.set_properties(props)
|
||||||
|
|
||||||
|
def _name_owner_changed_cb(self, name, old, new):
|
||||||
|
"""Handle D-Bus services we care about appearing and disappearing."""
|
||||||
|
self._ip4_addr_monitor.handle_name_owner_changed(name, old, new)
|
||||||
|
|
||||||
def get_registered(self):
|
def get_registered(self):
|
||||||
"""Retrieve whether owner has registered with presence server"""
|
"""Retrieve whether owner has registered with presence server"""
|
||||||
return self._registered
|
return self._registered
|
||||||
@ -479,11 +689,6 @@ class ShellOwner(GenericOwner):
|
|||||||
color=color, icon=icon, server=server, key_hash=key_hash,
|
color=color, icon=icon, server=server, key_hash=key_hash,
|
||||||
registered=registered)
|
registered=registered)
|
||||||
|
|
||||||
self._bus = dbus.SessionBus()
|
|
||||||
self._bus.add_signal_receiver(self._name_owner_changed_handler,
|
|
||||||
signal_name="NameOwnerChanged",
|
|
||||||
dbus_interface="org.freedesktop.DBus")
|
|
||||||
|
|
||||||
# Connect to the shell to get notifications on Owner object
|
# Connect to the shell to get notifications on Owner object
|
||||||
# property changes
|
# property changes
|
||||||
try:
|
try:
|
||||||
@ -496,13 +701,10 @@ class ShellOwner(GenericOwner):
|
|||||||
if value:
|
if value:
|
||||||
profile.set_server_registered()
|
profile.set_server_registered()
|
||||||
|
|
||||||
def _name_owner_changed_handler(self, name, old, new):
|
def _name_owner_changed_cb(self, name, old, new):
|
||||||
"""Handle DBUS notification of a new / renamed service
|
# chain up to superclass
|
||||||
|
GenericOwner._name_owner_changed_cb(self, name, old, new)
|
||||||
Watches for the _SHELL_SERVICE, i.e. the Sugar Shell,
|
|
||||||
and registers with it if we have not yet registered
|
|
||||||
with it (using _connect_to_shell).
|
|
||||||
"""
|
|
||||||
if name != self._SHELL_SERVICE:
|
if name != self._SHELL_SERVICE:
|
||||||
return
|
return
|
||||||
if (old and len(old)) and (not new and not len(new)):
|
if (old and len(old)) and (not new and not len(new)):
|
||||||
|
@ -164,7 +164,7 @@ class ServerPlugin(gobject.GObject):
|
|||||||
if properties.has_key("nick"):
|
if properties.has_key("nick"):
|
||||||
self._set_self_alias()
|
self._set_self_alias()
|
||||||
|
|
||||||
if properties.has_key("color"):
|
if properties.has_key("color") or properties.has_key("ip4-address"):
|
||||||
self._set_self_olpc_properties()
|
self._set_self_olpc_properties()
|
||||||
|
|
||||||
def _owner_icon_changed_cb(self, owner, icon):
|
def _owner_icon_changed_cb(self, owner, icon):
|
||||||
@ -447,6 +447,11 @@ class ServerPlugin(gobject.GObject):
|
|||||||
props = {}
|
props = {}
|
||||||
props['color'] = self._owner.props.color
|
props['color'] = self._owner.props.color
|
||||||
props['key'] = dbus.ByteArray(self._owner.props.key)
|
props['key'] = dbus.ByteArray(self._owner.props.key)
|
||||||
|
addr = self._owner.props.ip4_address
|
||||||
|
if not addr:
|
||||||
|
props['ip4-address'] = ""
|
||||||
|
else:
|
||||||
|
props['ip4-address'] = addr
|
||||||
self._conn[CONN_INTERFACE_BUDDY_INFO].SetProperties(props,
|
self._conn[CONN_INTERFACE_BUDDY_INFO].SetProperties(props,
|
||||||
reply_handler=self._ignore_success_cb,
|
reply_handler=self._ignore_success_cb,
|
||||||
error_handler=lambda *args: self._log_error_cb("setting properties", *args))
|
error_handler=lambda *args: self._log_error_cb("setting properties", *args))
|
||||||
|
@ -65,7 +65,8 @@ class Buddy(gobject.GObject):
|
|||||||
'nick' : (str, None, None, None, gobject.PARAM_READABLE),
|
'nick' : (str, None, None, None, gobject.PARAM_READABLE),
|
||||||
'color' : (str, None, None, None, gobject.PARAM_READABLE),
|
'color' : (str, None, None, None, gobject.PARAM_READABLE),
|
||||||
'current-activity' : (object, None, None, gobject.PARAM_READABLE),
|
'current-activity' : (object, None, None, gobject.PARAM_READABLE),
|
||||||
'owner' : (bool, None, None, False, gobject.PARAM_READABLE)
|
'owner' : (bool, None, None, False, gobject.PARAM_READABLE),
|
||||||
|
'ip4-address' : (str, None, None, None, gobject.PARAM_READABLE)
|
||||||
}
|
}
|
||||||
|
|
||||||
_PRESENCE_SERVICE = "org.laptop.Sugar.Presence"
|
_PRESENCE_SERVICE = "org.laptop.Sugar.Presence"
|
||||||
@ -134,6 +135,11 @@ class Buddy(gobject.GObject):
|
|||||||
if not self._icon:
|
if not self._icon:
|
||||||
self._icon = _bytes_to_string(self._buddy.GetIcon())
|
self._icon = _bytes_to_string(self._buddy.GetIcon())
|
||||||
return self._icon
|
return self._icon
|
||||||
|
elif pspec.name == "ip4-address":
|
||||||
|
# IPv4 address will go away quite soon
|
||||||
|
if not self._properties.has_key("ip4-address"):
|
||||||
|
return None
|
||||||
|
return self._properties["ip4-address"]
|
||||||
|
|
||||||
def object_path(self):
|
def object_path(self):
|
||||||
"""Retrieve our dbus object path"""
|
"""Retrieve our dbus object path"""
|
||||||
|
Loading…
Reference in New Issue
Block a user