annot-server/websockets.py
author ymh <ymh.work@gmail.com>
Wed, 08 Oct 2014 15:14:58 +0200
changeset 0 e1d4d7a8255a
child 23 16a1925df2df
permissions -rw-r--r--
First shareable version


#
# See LICENCE for detail
# Copyright (c) 2014 IRI
#

import json

from autobahn.twisted.websocket import WebSocketServerFactory, \
                                       WebSocketServerProtocol
from autobahn.websocket import http

from baseserver import BaseProtocol
import utils

class BroadcastServerProtocol(WebSocketServerProtocol):

    def onConnect(self, request):
        if request.params:
            self.factory.registerFilter(self, request.params)

    def onOpen(self):
        self.factory.register(self)

    def onMessage(self, payload, isBinary):
        if not isBinary:
            msg = "{} from {}".format(payload.decode('utf8'), self.peer)
            self.factory.broadcast(msg)

    def connectionLost(self, reason):
        WebSocketServerProtocol.connectionLost(self, reason)
        self.factory.unregister(self)


class BroadcastServerFactory(WebSocketServerFactory):
    """
    Simple broadcast server broadcasting any message it receives to all
    currently connected clients.
    """

    def __init__(self, url, debug = False, debugCodePaths = False):
        WebSocketServerFactory.__init__(self, url, debug = debug, debugCodePaths = debugCodePaths)
        self.clients = []
        self.filters = {}
        self.protocol = BroadcastServerProtocol

    def registerFilter(self, client, filter):
        print("registered filter {} for client {}".format(repr(filter),client.peer))
        self.filters[client] = filter

    def register(self, client):
        if not client in self.clients:
             print("registered client {}".format(client.peer))
             self.clients.append(client)

    def unregister(self, client):
        if client in self.clients:
            print("unregistered client {}".format(client.peer))
            self.clients.remove(client)
        if client in self.filters:
            self.filters.pop(client, None)

    def broadcast(self, msg, filter):
        print("broadcasting prepared message '{}' ..".format(msg))
        #preparedMsg = self.prepareMessage(msg)
        for c in self.clients:
            preparedMsg = self.prepareMessage(msg)
            if all([ (k in filter and filter[k] in v) for k,v in self.filters.get(c, {}).items()]):
                c.sendPreparedMessage(preparedMsg)
                print("prepared message sent to {}".format(c.peer))


class AnnotationServerProtocol(WebSocketServerProtocol, BaseProtocol):

    def onConnect(self, request):
        event_ids = request.params.get('event', [])
        if not event_ids or not event_ids[0]:
            raise http.HttpException(400, "The event parameter is missing")
        self.event = event_ids[0]
        self._init_props(self.factory.ws_factory, self.factory.conn)

    #TODO: add error handling
    def onMessage(self, payload, isBinary):
        if isBinary:
            return
        msg = payload.decode('utf8')
        params_annot = json.loads(msg)

        params = {
            'event': self.event,
            'channel' : utils.ANNOTATION_CHANNEL,
            'content' : params_annot
        }

        def error_callback(failure):
            raise http.HttpException(500,"Error when processing message : %r" % failure)

        def annot_callback(res):
            if 'ts' in res:
                res['ts'] = res['ts'].isoformat()+'Z'
            if 'uuid' in res:
                res['uuid'] = str(res['uuid'])
            self.sendMessage(json.dumps(res))


        defer = self.process_annotation(params)
        defer.addErrback(error_callback)
        defer.addCallback(annot_callback)


class AnotationServerFactory(WebSocketServerFactory):

    def __init__(self, url, ws_factory, conn, debug = False, debugCodePaths = False):
        WebSocketServerFactory.__init__(self, url, debug = debug, debugCodePaths = debugCodePaths)
        self.ws_factory = ws_factory
        self.conn = conn
        self.clients = {}
        self.protocol = AnnotationServerProtocol