annot-server/websockets.py
author ymh <ymh.work@gmail.com>
Fri, 17 Apr 2015 15:20:46 +0200
changeset 165 7dfdafb88968
parent 93 79ae42ad97d4
permissions -rw-r--r--
add ts_server
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
#
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
# See LICENCE for detail
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
# Copyright (c) 2014 IRI
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
#
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
import json
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
from autobahn.twisted.websocket import WebSocketServerFactory, \
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
                                       WebSocketServerProtocol
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
from autobahn.websocket import http
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
from baseserver import BaseProtocol
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
import utils
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
class BroadcastServerProtocol(WebSocketServerProtocol):
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
    def onConnect(self, request):
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
        if request.params:
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
            self.factory.registerFilter(self, request.params)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
    def onOpen(self):
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
        self.factory.register(self)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
    def onMessage(self, payload, isBinary):
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
        if not isBinary:
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
            msg = "{} from {}".format(payload.decode('utf8'), self.peer)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
            self.factory.broadcast(msg)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
    def connectionLost(self, reason):
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
        WebSocketServerProtocol.connectionLost(self, reason)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
        self.factory.unregister(self)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
class BroadcastServerFactory(WebSocketServerFactory):
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
    """
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
    Simple broadcast server broadcasting any message it receives to all
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
    currently connected clients.
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
    """
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
    def __init__(self, url, debug = False, debugCodePaths = False):
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
        WebSocketServerFactory.__init__(self, url, debug = debug, debugCodePaths = debugCodePaths)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
        self.clients = []
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
        self.filters = {}
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
        self.protocol = BroadcastServerProtocol
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
    def registerFilter(self, client, filter):
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
        print("registered filter {} for client {}".format(repr(filter),client.peer))
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
        self.filters[client] = filter
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
    def register(self, client):
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
        if not client in self.clients:
93
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 76
diff changeset
    52
            print("registered client {}".format(client.peer))
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 76
diff changeset
    53
            self.clients.append(client)
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
    def unregister(self, client):
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
        if client in self.clients:
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
            print("unregistered client {}".format(client.peer))
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
            self.clients.remove(client)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
        if client in self.filters:
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
            self.filters.pop(client, None)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
93
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 76
diff changeset
    62
    def broadcast(self, msg, filter_list):
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
        print("broadcasting prepared message '{}' ..".format(msg))
76
029cdbeebf03 filter pianoroll annotation by channel & event
ymh <ymh.work@gmail.com>
parents: 66
diff changeset
    64
        preparedMsg = self.prepareMessage(msg)
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
        for c in self.clients:
93
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 76
diff changeset
    66
            if all([ (k in filter_list and filter_list[k] in v) for k,v in self.filters.get(c, {}).items()]):
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
                c.sendPreparedMessage(preparedMsg)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
                print("prepared message sent to {}".format(c.peer))
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
class AnnotationServerProtocol(WebSocketServerProtocol, BaseProtocol):
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
    def onConnect(self, request):
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
        event_ids = request.params.get('event', [])
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
        if not event_ids or not event_ids[0]:
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
            raise http.HttpException(400, "The event parameter is missing")
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
        self.event = event_ids[0]
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
        self._init_props(self.factory.ws_factory, self.factory.conn)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
66
658561ea9e65 export sync code in utils, and add button to synchronize annotation on eventsessionview
ymh <ymh.work@gmail.com>
parents: 42
diff changeset
    80
    def clean_annot(self, annot):
658561ea9e65 export sync code in utils, and add button to synchronize annotation on eventsessionview
ymh <ymh.work@gmail.com>
parents: 42
diff changeset
    81
        if 'ts' in annot:
658561ea9e65 export sync code in utils, and add button to synchronize annotation on eventsessionview
ymh <ymh.work@gmail.com>
parents: 42
diff changeset
    82
            annot['ts'] = annot['ts'].isoformat()
658561ea9e65 export sync code in utils, and add button to synchronize annotation on eventsessionview
ymh <ymh.work@gmail.com>
parents: 42
diff changeset
    83
        if 'uuid' in annot:
658561ea9e65 export sync code in utils, and add button to synchronize annotation on eventsessionview
ymh <ymh.work@gmail.com>
parents: 42
diff changeset
    84
            annot['uuid'] = str(annot['uuid'])
658561ea9e65 export sync code in utils, and add button to synchronize annotation on eventsessionview
ymh <ymh.work@gmail.com>
parents: 42
diff changeset
    85
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
    #TODO: add error handling
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
    def onMessage(self, payload, isBinary):
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
        if isBinary:
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
            return
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
        msg = payload.decode('utf8')
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
        params_annot = json.loads(msg)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
        params = {
42
926f0426ce78 add event + event session + admin + category json management. Must rebuild database
ymh <ymh.work@gmail.com>
parents: 23
diff changeset
    94
            'event_code': self.event,
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
            'channel' : utils.ANNOTATION_CHANNEL,
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
            'content' : params_annot
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
        }
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
        def error_callback(failure):
23
16a1925df2df add status to annotation creation. Improve error management for annotation creation
ymh <ymh.work@gmail.com>
parents: 0
diff changeset
   100
            res = params.copy()
66
658561ea9e65 export sync code in utils, and add button to synchronize annotation on eventsessionview
ymh <ymh.work@gmail.com>
parents: 42
diff changeset
   101
            self.clean_annot(res)
23
16a1925df2df add status to annotation creation. Improve error management for annotation creation
ymh <ymh.work@gmail.com>
parents: 0
diff changeset
   102
            res['status'] = 'KO'
16a1925df2df add status to annotation creation. Improve error management for annotation creation
ymh <ymh.work@gmail.com>
parents: 0
diff changeset
   103
            res['failure'] = str(failure)
16a1925df2df add status to annotation creation. Improve error management for annotation creation
ymh <ymh.work@gmail.com>
parents: 0
diff changeset
   104
            self.sendMessage(json.dumps(res))
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
        def annot_callback(res):
66
658561ea9e65 export sync code in utils, and add button to synchronize annotation on eventsessionview
ymh <ymh.work@gmail.com>
parents: 42
diff changeset
   107
            self.clean_annot(res)
23
16a1925df2df add status to annotation creation. Improve error management for annotation creation
ymh <ymh.work@gmail.com>
parents: 0
diff changeset
   108
            res['status'] = 'OK'
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
            self.sendMessage(json.dumps(res))
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
        defer = self.process_annotation(params)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
        defer.addErrback(error_callback)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
        defer.addCallback(annot_callback)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
class AnotationServerFactory(WebSocketServerFactory):
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
    def __init__(self, url, ws_factory, conn, debug = False, debugCodePaths = False):
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
        WebSocketServerFactory.__init__(self, url, debug = debug, debugCodePaths = debugCodePaths)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
        self.ws_factory = ws_factory
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
        self.conn = conn
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
        self.clients = {}
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
        self.protocol = AnnotationServerProtocol