Make shareActivity work

This commit is contained in:
Dan Williams 2006-07-25 19:04:15 -05:00
parent e5065263a9
commit 164add907d
13 changed files with 84 additions and 82 deletions

View File

@ -65,7 +65,7 @@ class BrowserActivity(Activity):
self._initial_service.get_activity_id())
self._pservice.join_shared_activity(self._initial_service)
def _service_appeared_cb(self, pservice, buddy, service):
def _service_appeared_cb(self, pservice, service):
# Make sure the service is for our activity
if service.get_activity_id() != self._activity_id:
return

View File

@ -9,13 +9,13 @@ class ActivityInfo:
self._service = service
def get_id(self):
activity_id = self._service.get_one_property('activity_id')
activity_id = self._service.get_activity_id()
def get_type(self):
return self._service.get_type()
def get_title(self):
escaped_title = self._service.get_one_property('Title')
escaped_title = self._service.get_published_value('Title')
title = xml.sax.saxutils.unescape(escaped_title)
return title
@ -46,7 +46,8 @@ class ActivitiesModel(gobject.GObject):
def __iter__(self):
return self._activities.__iter__()
def _on_activity_announced_cb(self, pservice, service, buddy):
def _on_activity_announced_cb(self, pservice, activity):
# FIXME We should not hard code activity types here
if service.get_type() == "_web_olpc._udp":
self.add_activity(service)
services = activity.get_services_of_type("_web_olpc._udp")
if len(services) > 0:
self.add_activity(services[0])

View File

@ -13,13 +13,14 @@ class ShellOwner(object):
runs in the shell and serves up the buddy icon and other stuff. It's the
server portion of the Owner, paired with the client portion in Buddy.py."""
def __init__(self):
nick = env.get_nick_name()
self._nick = env.get_nick_name()
user_dir = env.get_user_dir()
if not os.path.exists(user_dir):
try:
os.makedirs(user_dir)
except OSError:
print "Could not create user directory."
try:
os.makedirs(user_dir)
except OSError, exc:
if exc[0] != 17: # file exists
print "Could not create user directory %s: (%d) %s" % (user_dir, exc[0], exc[1])
self._icon = None
for fname in os.listdir(user_dir):
@ -30,10 +31,12 @@ class ShellOwner(object):
fd.close()
break
# Create and announce our presence
self._pservice = PresenceService.PresenceService()
self._service = self._pservice.register_service(nick, PRESENCE_SERVICE_TYPE)
print "Owner '%s' using port %d" % (nick, self._service.get_port())
def announce(self):
# Create and announce our presence
self._service = self._pservice.register_service(self._nick, PRESENCE_SERVICE_TYPE)
print "Owner '%s' using port %d" % (self._nick, self._service.get_port())
self._icon_stream = Stream.Stream.new_from_service(self._service)
self._icon_stream.register_reader_handler(self._handle_buddy_icon_request, "get_buddy_icon")

View File

@ -1,5 +1,9 @@
import dbus
PRESENCE_SERVICE_TYPE = "_presence_olpc._tcp"
ACTIVITY_DBUS_OBJECT_PATH = "/org/laptop/Presence/Activities/"
ACTIVITY_DBUS_INTERFACE = "org.laptop.Presence.Activity"
class NotFoundError(Exception):
pass
@ -10,7 +14,7 @@ class ActivityDBusHelper(dbus.service.Object):
self._object_path = object_path
dbus.service.Object.__init__(self, bus_name, self._object_path)
@dbus.service.method(BUDDY_DBUS_INTERFACE,
@dbus.service.method(ACTIVITY_DBUS_INTERFACE,
in_signature="s", out_signature="ao")
def getServicesOfType(self, stype):
services = self._parent.get_services_of_type(stype)
@ -21,7 +25,7 @@ class ActivityDBusHelper(dbus.service.Object):
ret.append(serv.object_path())
return ret
@dbus.service.method(BUDDY_DBUS_INTERFACE,
@dbus.service.method(ACTIVITY_DBUS_INTERFACE,
in_signature="", out_signature="ao")
def getServices(self):
services = self._parent.get_services()
@ -32,12 +36,12 @@ class ActivityDBusHelper(dbus.service.Object):
ret.append(serv.object_path())
return ret
@dbus.service.method(BUDDY_DBUS_INTERFACE,
@dbus.service.method(ACTIVITY_DBUS_INTERFACE,
in_signature="", out_signature="s")
def getId(self):
return self._parent.get_id()
@dbus.service.method(BUDDY_DBUS_INTERFACE,
@dbus.service.method(ACTIVITY_DBUS_INTERFACE,
in_signature="", out_signature="ao")
def getJoinedBuddies(self):
buddies = self._parent.get_joined_buddies()
@ -48,40 +52,41 @@ class ActivityDBusHelper(dbus.service.Object):
ret.append(buddy.object_path())
return ret
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
@dbus.service.signal(ACTIVITY_DBUS_INTERFACE,
signature="o")
def ServiceAppeared(self, object_path):
pass
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
@dbus.service.signal(ACTIVITY_DBUS_INTERFACE,
signature="o")
def ServiceDisappeared(self, object_path):
pass
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
@dbus.service.signal(ACTIVITY_DBUS_INTERFACE,
signature="o")
def BuddyJoined(self, object_path):
pass
@dbus.service.signal(BUDDY_DBUS_INTERFACE,
@dbus.service.signal(ACTIVITY_DBUS_INTERFACE,
signature="o")
def BuddyLeft(self, object_path):
pass
class Activity(object):
def __init__(self, bus_name, object_id, activity_id):
if not activity_id:
def __init__(self, bus_name, object_id, initial_service):
if not initial_service.get_activity_id():
raise ValueError("Service must have a valid Activity ID")
self._activity_id = activity_id
self._activity_id = initial_service.get_activity_id()
self._buddies = []
self._services = {} # service type -> list of Services
self._services[service.get_type()] = []
self._object_id = object_id
self._object_path = "/org/laptop/Presence/Activities/%d" % self._object_id
self._dbus_helper = ActivityDBusHelper(self, bus_name, self._object_path)
self.add_service(initial_service)
def object_path(self):
return dbus.ObjectPath(self._object_path)
@ -99,8 +104,11 @@ class Activity(object):
def get_joined_buddies(self):
buddies = []
for serv in self._services.values():
buddies.append(serv.get_owner())
for serv_list in self._services.values():
for serv in serv_list:
owner = serv.get_owner()
if not owner in buddies:
buddies.append(owner)
return buddies
def add_service(self, service):

View File

@ -71,7 +71,7 @@ class BuddyDBusHelper(dbus.service.Object):
in_signature="", out_signature="a{sv}")
def getProperties(self):
props = {}
props['name'] = self._parent.get_nick_name()
props['name'] = self._parent.get_name()
props['ip4_address'] = self._parent.get_address()
props['owner'] = self._parent.is_owner()
return props
@ -149,6 +149,7 @@ class Buddy(object):
stype = service.get_type()
if stype in self._services.keys():
return False
logging.debug("Buddy %s added service type %s id %s" % (self._nick_name, service.get_type(), service.get_activity_id()))
self._services[stype] = service
service.set_owner(self)
@ -168,6 +169,7 @@ class Buddy(object):
if activity in self._activities.values():
raise RuntimeError("Tried to add activity twice")
found = False
logging.debug("Buddy %s looking for actid %s" % (self._nick_name, activity.get_id()))
for serv in self._services.values():
if serv.get_activity_id() == activity.get_id():
found = True
@ -239,7 +241,7 @@ class Buddy(object):
def get_address(self):
return self._address
def get_nick_name(self):
def get_name(self):
return self._nick_name
def _set_icon(self, icon):
@ -310,7 +312,7 @@ class BuddyTestCase(unittest.TestCase):
self._DEF_ADDRESS, self._DEF_PORT)
objid = _next_objid()
buddy = Buddy(self._bus_name, objid, service)
assert buddy.get_nick_name() == self._DEF_NAME, "buddy name wasn't correct after init."
assert buddy.get_name() == self._DEF_NAME, "buddy name wasn't correct after init."
assert buddy.get_address() == self._DEF_ADDRESS, "buddy address wasn't correct after init."
assert buddy.object_path() == BUDDY_DBUS_OBJECT_PATH + str(objid)

View File

@ -1,6 +1,7 @@
import avahi, dbus, dbus.glib, gobject
import Buddy
import Service
import Activity
import random
import logging
from sugar import env
@ -178,13 +179,15 @@ class PresenceServiceDBusHelper(dbus.service.Object):
@dbus.service.method(_PRESENCE_DBUS_INTERFACE,
in_signature="ssa{ss}sis", out_signature="o")
def registerService(self, name, stype, properties, address, port, domain):
service = self._parent.register_service(name, stype, properties, address,
def shareActivity(self, activity_id, stype, properties, address, port, domain):
service = self._parent.share_activity(activity_id, stype, properties, address,
port, domain)
return service.object_path()
def shareActivity(self, activity_id, stype, properties, address, port, domain):
service = self._parent.share_activity(name, stype, properties, address,
@dbus.service.method(_PRESENCE_DBUS_INTERFACE,
in_signature="ssa{ss}sis", out_signature="o")
def registerService(self, name, stype, properties, address, port, domain):
service = self._parent.register_service(name, stype, properties, address,
port, domain)
return service.object_path()
@ -440,7 +443,7 @@ class PresenceService(object):
self._local_addrs[interface] = addr
# Decompose service name if we can
(actid, buddy_name) = Service._decompose_service_name(full_name)
(actid, buddy_name) = Service.decompose_service_name(full_name)
# If we care about the service right now, resolve it
resolve = False
@ -475,7 +478,7 @@ class PresenceService(object):
return False
# Decompose service name if we can
(actid, buddy_name) = Service._decompose_service_name(full_name)
(actid, buddy_name) = Service.decompose_service_name(full_name)
# Remove the service from the buddy
try:
@ -546,34 +549,28 @@ class PresenceService(object):
def _new_domain_cb_glue(self, interface, protocol, domain, flags=0):
gobject.idle_add(self._new_domain_cb, interface, protocol, domain, flags)
def share_activity(self, activity_id, stype, properties=None, address=None, port=None, 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."""
if not util.validate_activity_id(activity_id):
raise ValueError("invalid activity id")
owner_nick = self._owner.get_nick_name()
real_name = Service.compose_service_name(owner_nick, actid)
owner_nick = self._owner.get_name()
real_name = Service.compose_service_name(owner_nick, activity_id)
if address and type(address) != type(u""):
raise ValueError("address must be a unicode string.")
if address == None:
# Use random currently unassigned multicast address
address = "232.%d.%d.%d" % (random.randint(0, 254), random.randint(1, 254),
random.randint(1, 254))
if port 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")
if not port:
# random port #
port = random.randint(5000, 65535)
# Mark the activity as shared
if stype == activity.get_default_type():
activity.set_shared()
logging.debug('Share activity %s, type %s, address %s, port %d, properties %s' % (activity_id, stype, address, port, properties))
return self.register_service(real_name, stype, properties, address, port, domain)
def register_service(self, name, stype, properties={}, address=None, port=None, domain=u"local"):
def register_service(self, name, stype, properties={}, address=None, port=-1, domain=u"local"):
"""Register a new service, advertising it to other Buddies on the network."""
if self.get_owner() and name != self.get_owner().get_nick_name():
(actid, person_name) = Service.decompose_service_name(name)
if self.get_owner() and person_name != self.get_owner().get_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):
domain = u"local"

View File

@ -34,7 +34,7 @@ def compose_service_name(name, activity_id):
composed = "%s [%s]" % (name, activity_id)
return composed
def _decompose_service_name(name):
def decompose_service_name(name):
"""Break a service name into the name and activity ID, if we can."""
if type(name) != type(u""):
raise ValueError("name must be a valid unicode string.")
@ -127,7 +127,7 @@ class Service(object):
if domain and domain != "local":
raise ValueError("must use the 'local' domain (for now).")
(actid, real_name) = _decompose_service_name(name)
(actid, real_name) = decompose_service_name(name)
self._name = real_name
self._full_name = name
self._stype = stype

View File

@ -56,7 +56,8 @@ class Shell:
bus_name = dbus.service.BusName('com.redhat.Sugar.Shell', bus=session_bus)
ShellDbusService(self, bus_name)
#self._owner = ShellOwner()
self._owner = ShellOwner()
self._owner.announce()
self._registry = ActivityRegistry()
self._registry.scan_directory(env.get_activities_dir())

View File

@ -192,11 +192,6 @@ class Activity(gtk.Window):
def get_default_type(self):
return self._default_type
def set_shared(self):
"""Mark the activity as 'shared'."""
if not self._shared:
self._shared = True
def get_shared(self):
return self._shared
@ -205,7 +200,9 @@ class Activity(gtk.Window):
return self._has_focus
def _internal_on_share_cb(self):
"""Callback when the dbus service object tells us the user has shared our activity."""
"""Callback when the dbus service object tells us the user wishes to share our activity."""
if not self._shared:
self._shared = True
self.share()
def get_id(self):

View File

@ -18,9 +18,9 @@ class ActivityChat(GroupChat):
if ps_activity is not None:
service = ps_activity.get_service_of_type(ActivityChat.SERVICE_TYPE)
if service is not None:
self._service_appeared_cb(self._pservice, None, service)
self._service_appeared_cb(self._pservice, service)
def _service_appeared_cb(self, pservice, buddy, service):
def _service_appeared_cb(self, pservice, service):
if service.get_activity_id() != self._activity.get_id():
return
if service.get_type() != ActivityChat.SERVICE_TYPE:

View File

@ -44,16 +44,7 @@ class LocalModel(AbstractModel):
# FIXME this is duplicated with StreamReader
def _setup_server(self, service):
started = False
tries = 10
port = service.get_port()
while not started and tries > 0:
try:
logging.debug('Start model server on port %d' % (port))
p2p_server = network.GlibXMLRPCServer(("", port))
p2p_server.register_instance(ModelRequestHandler(self))
started = True
except(socket.error):
port = port + 1
tries = tries - 1
service.set_port(port)
logging.debug('Start model server on port %d' % (port))
p2p_server = network.GlibXMLRPCServer(("", port))
p2p_server.register_instance(ModelRequestHandler(self))

View File

@ -66,13 +66,6 @@ class Activity(gobject.GObject):
def get_icon(self):
return self._buddy.getIcon()
def get_service_of_type(self, stype):
try:
object_path = self._buddy.getServiceOfType(stype)
except dbus.exceptions.DBusException:
return None
return self._ps_new_object(object_path)
def get_services(self):
resp = self._activity.getServices()
servs = []

View File

@ -181,7 +181,16 @@ class PresenceService(gobject.GObject):
return None
return self._new_object(owner_op)
def register_service(self, name, stype, properties={"":""}, address="", port=-1, domain=u"local"):
def share_activity(self, activity, stype, properties={}, address=None, port=-1, domain=u"local"):
actid = activity.get_id()
if address == None:
address = u""
serv_op = self._ps.shareActivity(actid, stype, properties, address, port, domain)
return self._new_object(serv_op)
def register_service(self, name, stype, properties={}, address=None, port=-1, domain=u"local"):
if address == None:
address = u""
serv_op = self._ps.registerService(name, stype, properties, address, port, domain)
return self._new_object(serv_op)