""" pypsyc.server ~~~~~~~~~~~~~ :copyright: 2010 by Manuel Jacob :license: MIT """ import signal from pkg_resources import iter_entry_points from twisted.internet import reactor from pypsyc.core.mmp import Uni, Header from pypsyc.core.psyc import PSYCObject, PSYCPacket from pypsyc.server.db import Database from pypsyc.server.routing import _TreeNode, Routing from pypsyc.server.multicast import ContextMaster from pypsyc.server.webif import run_webif from pypsyc.util import schedule class Entity(PSYCObject, _TreeNode): def __init__(self, parent=None, name='', server=None): _TreeNode.__init__(self, parent, name) self.server = (server or self._root.server) if parent is None: uni = Uni('psyc://%s/' % self.server.hostname) else: uni = parent.uni.chain(name) PSYCObject.__init__(self, self.server.routing.route_singlecast, uni) self.context_master = ContextMaster(self) self.packages = {} def castmsg(self, packet=None, header=None, **kwds): if packet is None: packet = PSYCPacket.from_kwds(**kwds) header = Header() if header is None else Header(header) header['_context'] = self.uni header._init() self.server.routing.route_multicast(header, packet.render()) class Server(object): def __init__(self, hostname, interface, psyc_port, webif_port, db_file): self.hostname = hostname self.routing = Routing(hostname, interface) self.root = Entity(server=self) self.routing.init(self.root) if psyc_port: self.routing.listen(psyc_port) self.database = Database(db_file) schedule(self._load_entities) if webif_port: schedule(run_webif, self, interface, webif_port, None) signal.signal(signal.SIGINT, self.shutdown) signal.signal(signal.SIGTERM, self.shutdown) try: signal.signal(signal.SIGBREAK, self.shutdown) except AttributeError: pass def _load_entities(self): self.database.execute( 'CREATE TABLE IF NOT EXISTS packages (' 'entity TEXT, package TEXT, PRIMARY KEY (entity, package))') entities = self.database.fetch('SELECT entity, package FROM packages') for entity_name, package_name in entities: self._load_package(entity_name, package_name) def _load_package(self, entity_name, package_name): if entity_name is None: entity = self.root else: try: entity = self.root.children[entity_name] except KeyError: entity = Entity(self.root, entity_name) assert package_name not in entity.packages l = list(iter_entry_points('pypsyc.server.packages', package_name)) assert len(l) == 1 package = l[0].load()(entity) entity.packages[package_name] = package return package def add_package(self, entity_name, package_name): package = self._load_package(entity_name, package_name) self.database.execute('INSERT INTO packages VALUES (?, ?)', entity_name, package_name) return package def add_place(self, name): return self.add_package('@' + name, 'place') def register_person(self, name, password): person = self.add_package('~' + name, 'person') person.register(password) return person def shutdown(self, signum=None, frame=None): self.database.stop() reactor.stop()