mirror of git://git.psyced.org/git/pypsyc
106 lines
3.5 KiB
Python
106 lines
3.5 KiB
Python
"""
|
|
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()
|