More presence service rework

This commit is contained in:
Dan Williams
2006-06-12 18:31:26 -04:00
parent d931dca579
commit 17c371119d
10 changed files with 381 additions and 224 deletions
+82 -62
View File
@@ -1,46 +1,108 @@
import pwd
import os
import base64
import pygtk
pygtk.require('2.0')
import gtk
import gtk, gobject
from sugar.p2p import Stream
from sugar.p2p import network
#from sugar import env
PRESENCE_SERVICE_TYPE = "_presence_olpc._tcp"
class Buddy(object):
class Buddy(gobject.GObject):
"""Represents another person on the network and keeps track of the
activities and resources they make available for sharing."""
__gsignals__ = {
'icon-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([])),
'service-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
'service-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT]))
}
def __init__(self, service):
gobject.GObject.__init__(self)
self._services = {}
self._nick_name = service.get_name()
self._address = service.get_address()
self._valid = False
self._icon = None
self._icon_tries = 0
self._owner = False
self.add_service(service)
def _request_buddy_icon_cb(self, result_status, response, user_data):
"""Callback when icon request has completed."""
icon = response
service = user_data
if result_status == network.RESULT_SUCCESS:
if icon and len(icon):
icon = base64.b64decode(icon)
print "Buddy icon for '%s' is size %d" % (self._nick_name, len(icon))
self.set_icon(icon)
if (result_status == network.RESULT_FAILED or not icon) and self._icon_tries < 3:
self._icon_tries = self._icon_tries + 1
print "Failed to retrieve buddy icon for '%s' on try %d of %d" % (self._nick_name, \
self._icon_tries, 3)
gobject.timeout_add(1000, self._request_buddy_icon, service)
return False
def _request_buddy_icon(self, service):
"""Contact the buddy to retrieve the buddy icon."""
buddy_stream = Stream.Stream.new_from_service(service, start_reader=False)
writer = buddy_stream.new_writer(service)
success = writer.custom_request("get_buddy_icon", self._request_buddy_icon_cb, service)
if not success:
del writer, buddy_stream
gobject.timeout_add(1000, self._request_buddy_icon, service)
return False
def add_service(self, service):
"""Adds a new service to this buddy's service list."""
"""Adds a new service to this buddy's service list, returning
True if the service was successfully added, and False if it was not."""
if service.get_name() != self._nick_name:
return False
if service.get_address() != self._address:
return False
if service.get_type() in self._services.keys():
return
self._services.keys[service.get_type()] = service
# FIXME: send out signal for new service found
return False
self._services[service.get_type()] = service
if self._valid:
self.emit("service-added", service)
if service.get_type() == PRESENCE_SERVICE_TYPE:
# A buddy isn't valid until its official presence
# service has been found and resolved
self._valid = True
self._request_buddy_icon(service)
return True
def remove_service(self, service):
"""Remove a service from a buddy; ie, the activity was closed
or the buddy went away."""
if service.get_type() in self._services.keys():
if service.get_address() != self._address:
return
if service.get_name() != self._nick_name:
return
if self._services.has_key(service.get_type()):
if self._valid:
self.emit("service-removed", service)
del self._services[service.get_type()]
if service.get_type() == PRESENCE_SERVICE_TYPE:
self._valid = False
def get_service_of_type(self, stype):
"""Return a service of a certain type, or None if the buddy
doesn't provide that service."""
if self._services.has_key(stype):
return self._services[stype]
return None
def is_valid(self):
"""Return whether the buddy is valid or not. A buddy is
not valid until its official presence service has been found
@@ -63,65 +125,23 @@ class Buddy(object):
def get_address(self):
return self._address
def add_service(self, service):
if service.get_name() != self._nick_name:
return False
if service.get_address() != self._address:
return False
if self._services.has_key(service.get_type()):
return False
self._services[service.get_type()] = service
def remove_service(self, stype):
if self._services.has_key(stype):
del self._services[stype]
def get_service(self, stype):
if self._services.has_key(stype):
return self._services[stype]
return None
def get_nick_name(self):
return self._nick_name
def set_icon(self, icon):
"""Can only set icon for other buddies. The Owner
takes care of setting it's own icon."""
self._icon = icon
# FIXME: do callbacks for icon-changed
if icon != self._icon:
self._icon = icon
self.emit("icon-changed")
def is_owner(self):
return self._owner
class Owner(Buddy):
"""Class representing the owner of this machine/instance."""
def __init__(self):
nick = env.get_nick_name()
if not nick:
nick = pwd.getpwuid(os.getuid())[0]
if not nick or not len(nick):
nick = "n00b"
Buddy.__init__(self)
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.'
for fname in os.listdir(user_dir):
if not fname.startswith("buddy-icon."):
continue
fd = open(os.path.join(user_dir, fname), "r")
self._icon = fd.read()
fd.close()
break
def set_icon(self, icon):
"""Can only set icon in constructor for now."""
pass
def add_service(self, service):
"""Do nothing here, since all services we need to know about
are registered with us by our group."""
pass
"""Class representing the owner of the machine. This is the client
portion of the Owner, paired with the server portion in Owner.py."""
def __init__(self, service):
Buddy.__init__(self, service)
self._owner = True