Separate a service's address into source address and the service address, and explicitly set each when required
This commit is contained in:
parent
ae1b278d7a
commit
cf35d9f374
@ -93,7 +93,7 @@ class Buddy(object):
|
|||||||
self._activities = {}
|
self._activities = {}
|
||||||
|
|
||||||
self._nick_name = service.get_name()
|
self._nick_name = service.get_name()
|
||||||
self._address = service.get_publisher_address()
|
self._address = service.get_source_address()
|
||||||
self._valid = False
|
self._valid = False
|
||||||
self._icon = None
|
self._icon = None
|
||||||
self._icon_tries = 0
|
self._icon_tries = 0
|
||||||
@ -142,9 +142,9 @@ class Buddy(object):
|
|||||||
True if the service was successfully added, and False if it was not."""
|
True if the service was successfully added, and False if it was not."""
|
||||||
if service.get_name() != self._nick_name:
|
if service.get_name() != self._nick_name:
|
||||||
return False
|
return False
|
||||||
publisher_addr = service.get_publisher_address()
|
source_addr = service.get_source_address()
|
||||||
if publisher_addr != self._address:
|
if source_addr != self._address:
|
||||||
logging.error('Service publisher and buddy address doesnt match: %s %s' % (publisher_addr, self._address))
|
logging.error("Service source and buddy address doesn't match: %s %s" % (source_addr, self._address))
|
||||||
return False
|
return False
|
||||||
stype = service.get_type()
|
stype = service.get_type()
|
||||||
if stype in self._services.keys():
|
if stype in self._services.keys():
|
||||||
@ -169,7 +169,6 @@ class Buddy(object):
|
|||||||
if activity in self._activities.values():
|
if activity in self._activities.values():
|
||||||
raise RuntimeError("Tried to add activity twice")
|
raise RuntimeError("Tried to add activity twice")
|
||||||
found = False
|
found = False
|
||||||
logging.debug("Buddy %s looking for actid %s" % (self._nick_name, activity.get_id()))
|
|
||||||
for serv in self._services.values():
|
for serv in self._services.values():
|
||||||
if serv.get_activity_id() == activity.get_id():
|
if serv.get_activity_id() == activity.get_id():
|
||||||
found = True
|
found = True
|
||||||
@ -177,13 +176,12 @@ class Buddy(object):
|
|||||||
if not found:
|
if not found:
|
||||||
raise RuntimeError("Tried to add activity for which we had no service")
|
raise RuntimeError("Tried to add activity for which we had no service")
|
||||||
self._activities[actid] = activity
|
self._activities[actid] = activity
|
||||||
print "Buddy (%s) joined activity %s." % (self._nick_name, actid)
|
|
||||||
self._dbus_helper.JoinedActivity(activity.object_path())
|
self._dbus_helper.JoinedActivity(activity.object_path())
|
||||||
|
|
||||||
def remove_service(self, service):
|
def remove_service(self, service):
|
||||||
"""Remove a service from a buddy; ie, the activity was closed
|
"""Remove a service from a buddy; ie, the activity was closed
|
||||||
or the buddy went away."""
|
or the buddy went away."""
|
||||||
if service.get_publisher_address() != self._address:
|
if service.get_source_address() != self._address:
|
||||||
return
|
return
|
||||||
if service.get_name() != self._nick_name:
|
if service.get_name() != self._nick_name:
|
||||||
return
|
return
|
||||||
|
@ -177,9 +177,24 @@ class PresenceServiceDBusHelper(dbus.service.Object):
|
|||||||
raise NotFoundError("Not found")
|
raise NotFoundError("Not found")
|
||||||
return owner.object_path()
|
return owner.object_path()
|
||||||
|
|
||||||
|
@dbus.service.method(_PRESENCE_DBUS_INTERFACE,
|
||||||
|
in_signature="os", out_signature="o")
|
||||||
|
def joinActivity(self, activity_op, stype):
|
||||||
|
found_activity = None
|
||||||
|
acts = self._parent.get_activities()
|
||||||
|
for act in acts:
|
||||||
|
if act.object_path() == activity_op:
|
||||||
|
found_activity = act
|
||||||
|
break
|
||||||
|
if not found_activity:
|
||||||
|
raise NotFoundError("The activity %s was not found." % activity_op)
|
||||||
|
return self._parent.join_activity(found_activity, stype)
|
||||||
|
|
||||||
@dbus.service.method(_PRESENCE_DBUS_INTERFACE,
|
@dbus.service.method(_PRESENCE_DBUS_INTERFACE,
|
||||||
in_signature="ssa{ss}sis", out_signature="o")
|
in_signature="ssa{ss}sis", out_signature="o")
|
||||||
def shareActivity(self, activity_id, stype, properties, address, port, domain):
|
def shareActivity(self, activity_id, stype, properties, address, port, domain):
|
||||||
|
if not len(address):
|
||||||
|
address = None
|
||||||
service = self._parent.share_activity(activity_id, stype, properties, address,
|
service = self._parent.share_activity(activity_id, stype, properties, address,
|
||||||
port, domain)
|
port, domain)
|
||||||
return service.object_path()
|
return service.object_path()
|
||||||
@ -187,6 +202,8 @@ class PresenceServiceDBusHelper(dbus.service.Object):
|
|||||||
@dbus.service.method(_PRESENCE_DBUS_INTERFACE,
|
@dbus.service.method(_PRESENCE_DBUS_INTERFACE,
|
||||||
in_signature="ssa{ss}sis", out_signature="o")
|
in_signature="ssa{ss}sis", out_signature="o")
|
||||||
def registerService(self, name, stype, properties, address, port, domain):
|
def registerService(self, name, stype, properties, address, port, domain):
|
||||||
|
if not len(address):
|
||||||
|
address = None
|
||||||
service = self._parent.register_service(name, stype, properties, address,
|
service = self._parent.register_service(name, stype, properties, address,
|
||||||
port, domain)
|
port, domain)
|
||||||
return service.object_path()
|
return service.object_path()
|
||||||
@ -319,9 +336,9 @@ class PresenceService(object):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
# Should this service mark the owner?
|
# Should this service mark the owner?
|
||||||
owner_nick = env.get_nick_name()
|
owner_nick = env.get_nick_name()
|
||||||
publisher_addr = service.get_publisher_address()
|
source_addr = service.get_source_address()
|
||||||
objid = self._get_next_object_id()
|
objid = self._get_next_object_id()
|
||||||
if name == owner_nick and publisher_addr in self._local_addrs.values():
|
if name == owner_nick and source_addr in self._local_addrs.values():
|
||||||
buddy = Buddy.Owner(self._bus_name, objid, service)
|
buddy = Buddy.Owner(self._bus_name, objid, service)
|
||||||
self._owner = buddy
|
self._owner = buddy
|
||||||
logging.debug("Owner is '%s'." % name)
|
logging.debug("Owner is '%s'." % name)
|
||||||
@ -385,15 +402,17 @@ class PresenceService(object):
|
|||||||
objid = self._get_next_object_id()
|
objid = self._get_next_object_id()
|
||||||
service = Service.Service(self._bus_name, objid, name=full_name,
|
service = Service.Service(self._bus_name, objid, name=full_name,
|
||||||
stype=stype, domain=domain, address=address, port=port,
|
stype=stype, domain=domain, address=address, port=port,
|
||||||
properties=txt)
|
properties=txt, source_address=address)
|
||||||
self._services[key] = service
|
self._services[key] = service
|
||||||
else:
|
else:
|
||||||
|
# Already tracking this service; likely we were the one that shared it
|
||||||
|
# in the first place, and therefore the source address would have been
|
||||||
|
# set yet
|
||||||
service = self._services[key]
|
service = self._services[key]
|
||||||
|
if not service.get_source_address():
|
||||||
|
service.set_source_address(address)
|
||||||
if not service.get_address():
|
if not service.get_address():
|
||||||
set_addr = service.get_one_property('address')
|
service.set_address(address)
|
||||||
if not set_addr:
|
|
||||||
set_addr = address
|
|
||||||
service.set_address(set_addr)
|
|
||||||
adv.set_service(service)
|
adv.set_service(service)
|
||||||
|
|
||||||
# Merge the service into our buddy and activity lists, if needed
|
# Merge the service into our buddy and activity lists, if needed
|
||||||
@ -549,6 +568,14 @@ class PresenceService(object):
|
|||||||
def _new_domain_cb_glue(self, interface, protocol, domain, flags=0):
|
def _new_domain_cb_glue(self, interface, protocol, domain, flags=0):
|
||||||
gobject.idle_add(self._new_domain_cb, interface, protocol, domain, flags)
|
gobject.idle_add(self._new_domain_cb, interface, protocol, domain, flags)
|
||||||
|
|
||||||
|
def join_activity(self, activity, stype):
|
||||||
|
services = activity.get_services_of_type(stype)
|
||||||
|
if not len(services):
|
||||||
|
raise NotFoundError("The service type %s was not present within the activity %s" % (stype, activity.object_path()))
|
||||||
|
act_service = services[0]
|
||||||
|
return self._share_activity(activity.get_id(), stype, act_service.get_properties(),
|
||||||
|
act_service.get_address(), act_service.get_port(), act_service.get_domain())
|
||||||
|
|
||||||
def share_activity(self, activity_id, stype, properties=None, address=None, port=-1, domain=u"local"):
|
def share_activity(self, activity_id, stype, properties=None, address=None, port=-1, domain=u"local"):
|
||||||
"""Convenience function to share an activity with other buddies."""
|
"""Convenience function to share an activity with other buddies."""
|
||||||
if not util.validate_activity_id(activity_id):
|
if not util.validate_activity_id(activity_id):
|
||||||
@ -557,9 +584,9 @@ class PresenceService(object):
|
|||||||
real_name = Service.compose_service_name(owner_nick, activity_id)
|
real_name = Service.compose_service_name(owner_nick, activity_id)
|
||||||
if address and type(address) != type(u""):
|
if address and type(address) != type(u""):
|
||||||
raise ValueError("address must be a unicode string.")
|
raise ValueError("address must be a unicode string.")
|
||||||
if address == None:
|
if address == None or not len(address):
|
||||||
# Use random currently unassigned multicast address
|
# Use random currently unassigned multicast address
|
||||||
address = "232.%d.%d.%d" % (random.randint(0, 254), random.randint(1, 254),
|
address = u"232.%d.%d.%d" % (random.randint(0, 254), random.randint(1, 254),
|
||||||
random.randint(1, 254))
|
random.randint(1, 254))
|
||||||
if port and port != -1 and (type(port) != type(1) or port <= 1024 or port >= 65535):
|
if port and port != -1 and (type(port) != type(1) or port <= 1024 or port >= 65535):
|
||||||
raise ValueError("port must be a number between 1024 and 65535")
|
raise ValueError("port must be a number between 1024 and 65535")
|
||||||
@ -574,6 +601,8 @@ class PresenceService(object):
|
|||||||
raise RuntimeError("Tried to register a service that didn't have Owner nick as the service name!")
|
raise RuntimeError("Tried to register a service that didn't have Owner nick as the service name!")
|
||||||
if not domain or not len(domain):
|
if not domain or not len(domain):
|
||||||
domain = u"local"
|
domain = u"local"
|
||||||
|
if not port or port == -1:
|
||||||
|
port = random.randint(4000, 65000)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
obj = self._system_bus.get_object(avahi.DBUS_NAME, self._mdns_service.EntryGroupNew())
|
obj = self._system_bus.get_object(avahi.DBUS_NAME, self._mdns_service.EntryGroupNew())
|
||||||
@ -581,24 +610,22 @@ class PresenceService(object):
|
|||||||
|
|
||||||
# Add properties; ensure they are converted to ByteArray types
|
# Add properties; ensure they are converted to ByteArray types
|
||||||
# because python sometimes can't figure that out
|
# because python sometimes can't figure that out
|
||||||
info = []
|
info = dbus.Array([])
|
||||||
for k, v in properties.items():
|
for k, v in properties.items():
|
||||||
info.append(dbus.types.ByteArray("%s=%s" % (k, v)))
|
info.append(dbus.types.ByteArray("%s=%s" % (k, v)))
|
||||||
|
|
||||||
objid = self._get_next_object_id()
|
objid = self._get_next_object_id()
|
||||||
service = Service.Service(self._bus_name, objid, name=name,
|
service = Service.Service(self._bus_name, objid, name=name,
|
||||||
stype=stype, domain=domain, address=address, port=port,
|
stype=stype, domain=domain, address=address, port=port,
|
||||||
properties=properties)
|
properties=properties, source_address=None)
|
||||||
self._services[(name, stype)] = service
|
self._services[(name, stype)] = service
|
||||||
port = service.get_port()
|
port = service.get_port()
|
||||||
|
|
||||||
if address and len(address):
|
|
||||||
info.append("address=%s" % (address))
|
|
||||||
logging.debug("PS: Will register service with name='%s', stype='%s'," \
|
logging.debug("PS: Will register service with name='%s', stype='%s'," \
|
||||||
" domain='%s', port=%d, info='%s'" % (name, stype, domain, port, info))
|
" domain='%s', address='%s', port=%d, info='%s'" % (name, stype, domain, address, port, info))
|
||||||
group.AddService(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, 0, name, stype,
|
group.AddService(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, 0, dbus.String(name),
|
||||||
domain, "", # let Avahi figure the 'host' out
|
dbus.String(stype), dbus.String(domain), dbus.String(""), # let Avahi figure the 'host' out
|
||||||
dbus.UInt16(port), info,)
|
dbus.UInt16(port), info)
|
||||||
group.Commit()
|
group.Commit()
|
||||||
except dbus.exceptions.DBusException, exc:
|
except dbus.exceptions.DBusException, exc:
|
||||||
# FIXME: ignore local name collisions, since that means
|
# FIXME: ignore local name collisions, since that means
|
||||||
|
@ -84,7 +84,7 @@ class ServiceDBusHelper(dbus.service.Object):
|
|||||||
addr = self._parent.get_address()
|
addr = self._parent.get_address()
|
||||||
if addr:
|
if addr:
|
||||||
pary['address'] = addr
|
pary['address'] = addr
|
||||||
source_addr = self._parent.get_publisher_address()
|
source_addr = self._parent.get_source_address()
|
||||||
if source_addr:
|
if source_addr:
|
||||||
pary['sourceAddress'] = source_addr
|
pary['sourceAddress'] = source_addr
|
||||||
return pary
|
return pary
|
||||||
@ -103,7 +103,8 @@ class ServiceDBusHelper(dbus.service.Object):
|
|||||||
class Service(object):
|
class Service(object):
|
||||||
"""Encapsulates information about a specific ZeroConf/mDNS
|
"""Encapsulates information about a specific ZeroConf/mDNS
|
||||||
service as advertised on the network."""
|
service as advertised on the network."""
|
||||||
def __init__(self, bus_name, object_id, name, stype, domain=u"local", address=None, port=-1, properties=None):
|
def __init__(self, bus_name, object_id, name, stype, domain=u"local",
|
||||||
|
address=None, port=-1, properties=None, source_address=None):
|
||||||
if not bus_name:
|
if not bus_name:
|
||||||
raise ValueError("DBus bus name must be valid")
|
raise ValueError("DBus bus name must be valid")
|
||||||
if not object_id or type(object_id) != type(1):
|
if not object_id or type(object_id) != type(1):
|
||||||
@ -136,14 +137,19 @@ class Service(object):
|
|||||||
self.set_port(port)
|
self.set_port(port)
|
||||||
self._properties = {}
|
self._properties = {}
|
||||||
self.set_properties(properties)
|
self.set_properties(properties)
|
||||||
# Publisher address is the unicast source IP
|
|
||||||
self._publisher_address = address
|
# Source address is the unicast source IP
|
||||||
|
self._source_address = None
|
||||||
|
if source_address is not None:
|
||||||
|
self.set_source_address(source_address)
|
||||||
|
|
||||||
# Address is the published address, could be multicast or unicast
|
# Address is the published address, could be multicast or unicast
|
||||||
self._address = None
|
self._address = None
|
||||||
if self._properties.has_key('address'):
|
if self._properties.has_key('address'):
|
||||||
self.set_address(self._properties['address'])
|
self.set_address(self._properties['address'])
|
||||||
else:
|
elif address is not None:
|
||||||
self.set_address(address)
|
self.set_address(address)
|
||||||
|
self._properties['address'] = address
|
||||||
|
|
||||||
# Ensure that an ActivityID tag, if given, matches
|
# Ensure that an ActivityID tag, if given, matches
|
||||||
# what we expect from the service type
|
# what we expect from the service type
|
||||||
@ -230,25 +236,27 @@ class Service(object):
|
|||||||
return self._port
|
return self._port
|
||||||
|
|
||||||
def set_port(self, port):
|
def set_port(self, port):
|
||||||
if port == -1:
|
|
||||||
port = random.randint(4000, 65000)
|
|
||||||
if type(port) != type(1) or (port <= 1024 and port > 65536):
|
if type(port) != type(1) or (port <= 1024 and port > 65536):
|
||||||
raise ValueError("must specify a valid port number between 1024 and 65536.")
|
raise ValueError("must specify a valid port number between 1024 and 65536.")
|
||||||
self._port = port
|
self._port = port
|
||||||
|
|
||||||
def get_publisher_address(self):
|
def get_source_address(self):
|
||||||
return self._publisher_address
|
return self._source_address
|
||||||
|
|
||||||
|
def set_source_address(self, address):
|
||||||
|
if not address or type(address) != type(u""):
|
||||||
|
raise ValueError("address must be unicode")
|
||||||
|
self._source_address = address
|
||||||
|
|
||||||
def get_address(self):
|
def get_address(self):
|
||||||
return self._address
|
return self._address
|
||||||
|
|
||||||
def set_address(self, address):
|
def set_address(self, address):
|
||||||
if address is not None:
|
if not address or type(address) != type(u""):
|
||||||
if type(address) != type(u""):
|
raise ValueError("address must be a unicode string")
|
||||||
raise ValueError("address must be unicode")
|
|
||||||
self._address = address
|
self._address = address
|
||||||
if not self._publisher_address:
|
self._properties['address'] = address
|
||||||
self._publisher_address = address
|
|
||||||
|
|
||||||
def get_domain(self):
|
def get_domain(self):
|
||||||
"""Return the ZeroConf/mDNS domain the service was found in."""
|
"""Return the ZeroConf/mDNS domain the service was found in."""
|
||||||
|
Loading…
Reference in New Issue
Block a user