Beispiel #1
0
 def serve_handler(self, handler, values):
     def invoke_handler(handler, sock):
         try:
             handler(sock, **values)
         finally:
             sock.close()
     th = Thread(target=invoke_handler, args=(handler, self,))
     th.setDaemon(True)
     th.start()
     try:
         fd = uwsgi.connection_fd()
         while not self.evt_close.is_set():
             uwsgi.wait_fd_read(fd, 0.3)
             uwsgi.suspend()
             _fd = uwsgi.ready_fd()
             msg = uwsgi.websocket.recv_nb()
             if msg:
                 self.q_recv.put(msg)
             try:
                 msg = self.q.get(True, 0.1)
                 if msg:
                     uwsgi.websocket_send(msg)
             except Empty:
                 pass
     finally:
         self.close()
         th.join()
     return []
Beispiel #2
0
def application(env, start_response):
    # complete the handshake
    uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', ''))

    r = redis.StrictRedis(host='redis-gandamu', port=6379, db=0)
    channel = r.pubsub()
    channel.subscribe('portfolio')
    websocket_fd = uwsgi.connection_fd()
    redis_fd = channel.connection._sock.fileno()

    while True:
        uwsgi.wait_fd_read(websocket_fd, 3)
        uwsgi.wait_fd_read(redis_fd)
        uwsgi.suspend()
        fd = uwsgi.ready_fd()
        if fd > -1:
            if fd == websocket_fd:
                msg = uwsgi.websocket_recv_nb()
                if msg:
                    r.publish('portfolio', msg)
            elif fd == redis_fd:
                msg = channel.parse_response()
                # only interested in user messages
                t = 'message'
                if sys.version_info[0] > 2:
                    t = b'message'
                if msg[0] == t:
                    json = msg[2].decode('utf-8')
                    uwsgi.websocket_send("%s" % json)
                    # uwsgi.websocket_send("[%s] %s" % (time.time(), msg))
        else:
            # on timeout call websocket_recv_nb again to manage ping/pong
            msg = uwsgi.websocket_recv_nb()
            if msg:
                r.publish('portfolio', msg)
Beispiel #3
0
 def wait(self):
     # Remove context as we are switching between green thread
     # (and therefore websocket request)
     self.ws._pop_context()
     uwsgi.wait_fd_read(self.websocket_fd, 3)
     uwsgi.wait_fd_read(self.db_fd, 5)
     uwsgi.suspend()
     # Restoring request context for all other operations
     self.ws._push_context()
     fd = uwsgi.ready_fd()
     if fd == self.websocket_fd:
         return "websocket"
     if fd == self.db_fd:
         return "db"
     # Try ping / ponging the websocket in case of error
     return "timeout"
Beispiel #4
0
 def recv(server, sock):
     while not sock.evt_open.is_set():
         time.sleep(0.05)
     if hasattr(server, 'on_open'):
         server.on_open(self)
     try:
         fd = uwsgi.connection_fd()
         while not sock.evt_close.is_set():
             uwsgi.wait_fd_read(fd, 1.0)
             uwsgi.suspend()
             _fd = uwsgi.ready_fd()
             msg = uwsgi.websocket_recv_nb()
             if msg:
                 frame = (1, OP_TEXT, msg)
                 server.on_message(sock, frame)
     finally:
         sock.evt_close.set()
Beispiel #5
0
 def wsSubData_nb(self):
     """Websocket subscribe redis pubsub nonbolocking.
        Keepalive websocket connection with client."""
     uwsgi.websocket_handshake(self.environ['HTTP_SEC_WEBSOCKET_KEY'], self.environ.get('HTTP_ORIGIN', ''))
     channel = self.r.pubsub()
     channel.subscribe(self.channel)
     channel.parse_response()
     websocket_fd = uwsgi.connection_fd()
     redis_fd = channel.connection._sock.fileno()
     while True:
         uwsgi.wait_fd_read(websocket_fd, 3)
         uwsgi.wait_fd_read(redis_fd)
         uwsgi.suspend()
         fd = uwsgi.ready_fd()
         if fd > -1:
             if fd == websocket_fd:
                 uwsgi.websocket_recv_nb()
             elif fd == redis_fd:
                 wsdata = channel.parse_response()[2]
                 uwsgi.websocket_send(wsdata)
         else:
             uwsgi.websocket_recv_nb()
             time.sleep(1)
Beispiel #6
0
def application(env, start_response):
    request = Request(env)

    try:
        uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'],
                                  env.get('HTTP_ORIGIN', ''))
    except OSError as err:
        logging.info('handshake_failed')

    else:
        with cursor_for_request(request) as cursor:
            db_connection = cursor.connection
            db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)

            db_conn_fd = db_connection.fileno()
            websocket_fd = uwsgi.connection_fd()

            logging.info('connection established')

            try:
                while True:
                    uwsgi.wait_fd_read(websocket_fd)
                    uwsgi.wait_fd_read(db_conn_fd)
                    uwsgi.suspend()

                    fd = uwsgi.ready_fd()

                    if fd == websocket_fd:
                        cmd_json = uwsgi.websocket_recv_nb()

                        if cmd_json:
                            cmd = json.loads(cmd_json.decode('utf-8'))

                            if cmd:
                                try:
                                    if cmd['method'] != 'ping':
                                        logging.info('command received: %s' % cmd['method'])

                                    if cmd['method'] == 'request':
                                        request_method(cmd, cursor)

                                    elif cmd['method'] == 'attach':
                                        attach_method(cmd, cursor, db_connection, env)

                                    elif cmd['method'] == 'detach':
                                        detach_method(cmd, cursor, db_connection, env)

                                except Warning as err:
                                    logging.error(str(err))
#                                    uwsgi.websocket_send(json.dumps({
#                                        "method": "log",
#                                        "args": {
#                                            "level": "warning",
#                                            "message": err.diag.message_primary
#                                        }
#                                    }))

                    elif fd == db_conn_fd:
                        handle_db_notifications(db_connection)

                    else:
                        logging.info('timeout reached') # This is never reached

                        # handle timeout of above wait_fd_read for ping/pong
                        uwsgi.websocket_recv_nb()

            except (OSError, IOError) as err:
                logging.info('connection closed (role: %s)' % env['DB_USER'])

        return []
Beispiel #7
0
def application(env, sr):

    ws_scheme = 'ws'
    if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https':
        ws_scheme = 'wss'

    if env['PATH_INFO'] == '/':
        sr('200 OK', [('Content-Type','text/html')])
        output = """
    <!doctype html>
    <html>
      <head>
          <meta charset="utf-8">
          <script language="Javascript">
            var s = new WebSocket("%s://%s/foobar/");
            s.onopen = function() {
              console.log("connected !!!");
              s.send("hello");
            };
            s.onmessage = function(e) {
        var bb = document.getElementById('blackboard')
        var html = bb.innerHTML;
        bb.innerHTML = html + '<br/>' + e.data;
            };

        s.onerror = function(e) {
            console.log(e);
        }

    s.onclose = function(e) {
        console.log("connection closed");
    }

            function invia() {
              var value = document.getElementById('testo').value;
              s.send(value);
            }
          </script>
     </head>
    <body>
        <h1>WebSocket</h1>
        <input type="text" id="testo"/>
        <input type="button" value="invia" onClick="invia();"/>
    <div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto">
    </div>
    </body>
    </html>
        """ % (ws_scheme, env['HTTP_HOST'])
        return output.encode()
    elif env['PATH_INFO'] == '/favicon.ico':
        return ""
    elif env['PATH_INFO'] == '/foobar/':
        uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', ''))
        print("websockets...")
        msg_srv_fd = uwsgi.async_connect("127.0.0.1:8888")
        websocket_fd = uwsgi.connection_fd()
        while True:
            uwsgi.wait_fd_read(websocket_fd, 3)
            uwsgi.wait_fd_read(msg_srv_fd)
            uwsgi.suspend()
            fd = uwsgi.ready_fd()
            if fd > -1:
                if fd == websocket_fd:
                    msg = uwsgi.websocket_recv_nb()
                    print("got message over ws: {}".format(msg))
                    if msg:
                        uwsgi.send(msg_srv_fd, msg)
                elif fd == msg_srv_fd:
                    msg = uwsgi.recv(msg_srv_fd)
                    print("got message over msg_srv: {}".format(msg))
                    uwsgi.websocket_send("[%s] %s" % (time.time(), msg.decode()))
            else:
                # on timeout call websocket_recv_nb again to manage ping/pong
                msg = uwsgi.websocket_recv_nb()
                print("ws ping/pong")
                if msg:
                    print("got message over ws: {}".format(msg))
                    uwsgi.send(msg_srv_fd, msg)
Beispiel #8
0
def uwsgi_pypy_wait_fd_read(fd, timeout=0):
    wsgi_req = uwsgi_pypy_current_wsgi_req();
    if lib.async_add_fd_read(wsgi_req, fd, timeout) < 0:
        raise Exception("unable to add fd %d to the event queue" % fd)
uwsgi.wait_fd_read = uwsgi_pypy_wait_fd_read

"""
uwsgi.wait_fd_write(fd, timeout=0)
"""
def uwsgi_pypy_wait_fd_write(fd, timeout=0):
    wsgi_req = uwsgi_pypy_current_wsgi_req();
    if lib.async_add_fd_write(wsgi_req, fd, timeout) < 0:
        raise Exception("unable to add fd %d to the event queue" % fd)
uwsgi.wait_fd_write = uwsgi_pypy_wait_fd_write

"""
uwsgi.ready_fd()
"""
def uwsgi_pypy_ready_fd():
    wsgi_req = uwsgi_pypy_current_wsgi_req();
    return lib.uwsgi_ready_fd(wsgi_req)
uwsgi.ready_fd = uwsgi_pypy_ready_fd
    

"""
uwsgi.send(fd=None,data)
"""
def uwsgi_pypy_send(*args):
    if len(args) == 0:
        raise ValueError("uwsgi.send() takes at least 1 argument")
    elif len(args) == 1:
def application(env, sr):

    ws_scheme = 'ws'
    if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https':
        ws_scheme = 'wss'

    if env['PATH_INFO'] == '/':
        sr('200 OK', [('Content-Type', 'text/html')])
        output = """
    <html>
      <head>
          <script language="Javascript">
            var s = new WebSocket("%s://%s/foobar/");
            s.onopen = function() {
              alert("connected !!!");
              s.send("ciao");
            };
            s.onmessage = function(e) {
                var bb = document.getElementById('blackboard')
                var html = bb.innerHTML;
                bb.innerHTML = html + '<br/>' + e.data;
            };

            s.onerror = function(e) {
                        alert(e);
                }

        s.onclose = function(e) {
                alert("connection closed");
        }

            function invia() {
              var value = document.getElementById('testo').value;
              s.send(value);
            }
          </script>
     </head>
    <body>
        <h1>WebSocket</h1>
        <input type="text" id="testo"/>
        <input type="button" value="invia" onClick="invia();"/>
        <div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto">
        </div>
    </body>
    </html>
        """ % (ws_scheme, env['HTTP_HOST'])
        if sys.version_info[0] > 2:
            return output.encode('latin1')
        return output
    elif env['PATH_INFO'] == '/favicon.ico':
        return ""
    elif env['PATH_INFO'] == '/foobar/':
        uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'],
                                  env.get('HTTP_ORIGIN', ''))
        print("websockets...")
        r = redis.StrictRedis(host='localhost', port=6379, db=0)
        channel = r.pubsub()
        channel.subscribe('foobar')

        websocket_fd = uwsgi.connection_fd()
        redis_fd = channel.connection._sock.fileno()

        while True:
            uwsgi.wait_fd_read(websocket_fd, 3)
            uwsgi.wait_fd_read(redis_fd)
            uwsgi.suspend()
            fd = uwsgi.ready_fd()
            if fd > -1:
                if fd == websocket_fd:
                    msg = uwsgi.websocket_recv_nb()
                    if msg:
                        r.publish('foobar', msg)
                elif fd == redis_fd:
                    msg = channel.parse_response()
                    print(msg)
                    # only interested in user messages
                    t = 'message'
                    if sys.version_info[0] > 2:
                        t = b'message'
                    if msg[0] == t:
                        uwsgi.websocket_send("[%s] %s" % (time.time(), msg))
            else:
                # on timeout call websocket_recv_nb again to manage ping/pong
                msg = uwsgi.websocket_recv_nb()
                if msg:
                    r.publish('foobar', msg)
Beispiel #10
0
def uwsgi_pypy_wait_fd_read(fd, timeout=0):
    wsgi_req = uwsgi_pypy_current_wsgi_req();
    if lib.async_add_fd_read(wsgi_req, fd, timeout) < 0:
        raise Exception("unable to add fd %d to the event queue" % fd)
uwsgi.wait_fd_read = uwsgi_pypy_wait_fd_read

"""
uwsgi.wait_fd_write(fd, timeout=0)
"""
def uwsgi_pypy_wait_fd_write(fd, timeout=0):
    wsgi_req = uwsgi_pypy_current_wsgi_req();
    if lib.async_add_fd_write(wsgi_req, fd, timeout) < 0:
        raise Exception("unable to add fd %d to the event queue" % fd)
uwsgi.wait_fd_write = uwsgi_pypy_wait_fd_write

"""
uwsgi.ready_fd()
"""
def uwsgi_pypy_ready_fd():
    wsgi_req = uwsgi_pypy_current_wsgi_req();
    return lib.uwsgi_ready_fd(wsgi_req)
uwsgi.ready_fd = uwsgi_pypy_ready_fd
    

"""
uwsgi.send(fd=None,data)
"""
def uwsgi_pypy_send(*args):
    if len(args) == 0:
        raise ValueError("uwsgi.send() takes at least 1 argument")
    elif len(args) == 1:
Beispiel #11
0
def application(env, sr):

    ws_scheme = 'ws'
    if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https':
        ws_scheme = 'wss'

    if env['PATH_INFO'] == '/':
        sr('200 OK', [('Content-Type', 'text/html')])
        output = """
    <html>
      <head>
          <script language="Javascript">
            var s = new WebSocket("%s://%s/foobar/");
            s.onopen = function() {
              alert("connected !!!");
              s.send("ciao");
            };
            s.onmessage = function(e) {
                var bb = document.getElementById('blackboard')
                var html = bb.innerHTML;
                bb.innerHTML = html + '<br/>' + e.data;
            };

            s.onerror = function(e) {
                        alert(e);
                }

        s.onclose = function(e) {
                alert("connection closed");
        }

            function invia() {
              var value = document.getElementById('testo').value;
              s.send(value);
            }
          </script>
     </head>
    <body>
        <h1>WebSocket</h1>
        <input type="text" id="testo"/>
        <input type="button" value="invia" onClick="invia();"/>
        <div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto">
        </div>
    </body>
    </html>
        """ % (ws_scheme, env['HTTP_HOST'])
        if sys.version_info[0] > 2:
            return output.encode('latin1')
        return output
    elif env['PATH_INFO'] == '/favicon.ico':
        return ""
    elif env['PATH_INFO'] == '/foobar/':
        uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', ''))
        print("websockets...")
        r = redis.StrictRedis(host='localhost', port=6379, db=0)
        channel = r.pubsub()
        channel.subscribe('foobar')

        websocket_fd = uwsgi.connection_fd()
        redis_fd = channel.connection._sock.fileno()

        while True:
            uwsgi.wait_fd_read(websocket_fd, 3)
            uwsgi.wait_fd_read(redis_fd)
            uwsgi.suspend()
            fd = uwsgi.ready_fd()
            if fd > -1:
                if fd == websocket_fd:
                    msg = uwsgi.websocket_recv_nb()
                    if msg:
                        r.publish('foobar', msg)
                elif fd == redis_fd:
                    msg = channel.parse_response()
                    print(msg)
                    # only interested in user messages
                    t = 'message'
                    if sys.version_info[0] > 2:
                        t = b'message'
                    if msg[0] == t:
                        uwsgi.websocket_send("[%s] %s" % (time.time(), msg))
            else:
                # on timeout call websocket_recv_nb again to manage ping/pong
                msg = uwsgi.websocket_recv_nb()
                if msg:
                    r.publish('foobar', msg)
Beispiel #12
0
def application(env, start_response):
    request = Request(env)

    try:
        uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'],
                                  env.get('HTTP_ORIGIN', ''))
    except OSError as err:
        logging.info('handshake_failed')

    else:
        with cursor_for_request(request) as cursor:
            db_connection = cursor.connection
            db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)

            db_conn_fd = db_connection.fileno()
            websocket_fd = uwsgi.connection_fd()

            logging.info('connection established')

            try:
                while True:
                    uwsgi.wait_fd_read(websocket_fd)
                    uwsgi.wait_fd_read(db_conn_fd)
                    uwsgi.suspend()

                    fd = uwsgi.ready_fd()

                    if fd == websocket_fd:
                        cmd_json = uwsgi.websocket_recv_nb()

                        if cmd_json:
                            cmd = json.loads(cmd_json.decode('utf-8'))

                            if cmd:
                                try:
                                    if cmd['method'] != 'ping':
                                        logging.info('command received: %s' %
                                                     cmd['method'])

                                    if cmd['method'] == 'request':
                                        request_method(cmd, cursor)

                                    elif cmd['method'] == 'attach':
                                        attach_method(cmd, cursor,
                                                      db_connection, env)

                                    elif cmd['method'] == 'detach':
                                        detach_method(cmd, cursor,
                                                      db_connection, env)

                                except Warning as err:
                                    logging.error(str(err))
#                                    uwsgi.websocket_send(json.dumps({
#                                        "method": "log",
#                                        "args": {
#                                            "level": "warning",
#                                            "message": err.diag.message_primary
#                                        }
#                                    }))

                    elif fd == db_conn_fd:
                        handle_db_notifications(db_connection)

                    else:
                        logging.info(
                            'timeout reached')  # This is never reached

                        # handle timeout of above wait_fd_read for ping/pong
                        uwsgi.websocket_recv_nb()

            except (OSError, IOError) as err:
                logging.info('connection closed (role: %s)' % env['DB_USER'])

        return []
Beispiel #13
0
def application(env, start_response):
    request = Request(env)

    try:
        uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'],
                                  env.get('HTTP_ORIGIN', ''))
    except OSError as err:
        logging.info('handshake_failed')

    else:
        with cursor_for_request(request) as cursor:
            db_connection = cursor.connection
            db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)

            session_id = get_session_id(request, cursor)

            logging.info('event/table/session/row/%s:connected (role: %s)' % (session_id, env['DB_USER']))

            db_conn_fd = db_connection.fileno()
            websocket_fd = uwsgi.connection_fd()

            cursor.execute('listen "event/table/session/rows/%i"' % session_id)

            try:
                while True:
                    uwsgi.wait_fd_read(websocket_fd)
                    uwsgi.wait_fd_read(db_conn_fd)
                    uwsgi.suspend()

                    fd = uwsgi.ready_fd()

                    if fd == websocket_fd:
                        cmd_json = uwsgi.websocket_recv_nb()

                        if cmd_json:
                            cmd = json.loads(cmd_json.decode('utf-8'))

                            if cmd:
                                try:
                                    if cmd['method'] == 'subscribe':
                                        selector, type = cmd['args']['selector'].rsplit(':', 1)
                                        cursor.execute("select event.subscribe_session(%s, %s, %s);", (session_id, selector, type))

                                    elif cmd['method'] == 'unsubscribe':
                                        selector, type = cmd['args']['selector'].rsplit(':', 1)
                                        cursor.execute("select event.unsubscribe_session(%s, %s, %s);", (session_id, selector, type))

                                except Warning as err:
                                    logging.error(str(err))
                                    uwsgi.websocket_send(json.dumps({
                                        "method": "log",
                                        "args": {
                                            "level": "warning",
                                            "message": err.diag.message_primary
                                        }
                                    }))

                    elif fd == db_conn_fd:
                        db_connection.poll()

                        if db_connection.notifies:
                            del db_connection.notifies[:]

                            cursor.execute('''
                                select *
                                from event.session_queued_events_json(%s)
                            ''', (session_id,))

                            qe_ids = []
                            logging.info('event/table/session/row/%s:flushing_queue (role: %s)' % (session_id, env['DB_USER']))

                            for row in cursor:
                                uwsgi.websocket_send(json.dumps(row.event_json))
                                logging.info('event/table/session/row/%s:sent_json (role: %s)' % (session_id, env['DB_USER']))
                                qe_ids.append(row.queued_event_id)

                            cursor.execute('''
                                delete from event.queued_event qe
                                where qe.id = any(%s)
                            ''', (qe_ids,))
                    else:
                        # handle timeout of above wait_fd_read for ping/pong
                        uwsgi.websocket_recv_nb()

            except OSError as err:
                logging.info('event/table/session/row/%s:disconnected (role: %s)' % (session_id, env['DB_USER']))

        return []
Beispiel #14
0
def application(env, start_response):
    request = Request(env)

    try:
        uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'],
                                  env.get('HTTP_ORIGIN', ''))
    except OSError as err:
        logging.info('handshake_failed')

    else:
        with cursor_for_request(request) as cursor:
            db_connection = cursor.connection
            db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)

            session_id = get_session_id(request, cursor)

            logging.info('event/table/session/row/%s:connected (role: %s)' %
                         (session_id, env['DB_USER']))

            db_conn_fd = db_connection.fileno()
            websocket_fd = uwsgi.connection_fd()

            cursor.execute('listen "event/table/session/rows/%i"' % session_id)

            try:
                while True:
                    uwsgi.wait_fd_read(websocket_fd)
                    uwsgi.wait_fd_read(db_conn_fd)
                    uwsgi.suspend()

                    fd = uwsgi.ready_fd()

                    if fd == websocket_fd:
                        cmd_json = uwsgi.websocket_recv_nb()

                        if cmd_json:
                            cmd = json.loads(cmd_json.decode('utf-8'))

                            if cmd:
                                try:
                                    if cmd['method'] == 'subscribe':
                                        selector, type = cmd['args'][
                                            'selector'].rsplit(':', 1)
                                        cursor.execute(
                                            "select event.subscribe_session(%s, %s, %s);",
                                            (session_id, selector, type))

                                    elif cmd['method'] == 'unsubscribe':
                                        selector, type = cmd['args'][
                                            'selector'].rsplit(':', 1)
                                        cursor.execute(
                                            "select event.unsubscribe_session(%s, %s, %s);",
                                            (session_id, selector, type))

                                except Warning as err:
                                    logging.error(str(err))
                                    uwsgi.websocket_send(
                                        json.dumps({
                                            "method": "log",
                                            "args": {
                                                "level": "warning",
                                                "message":
                                                err.diag.message_primary
                                            }
                                        }))

                    elif fd == db_conn_fd:
                        db_connection.poll()

                        if db_connection.notifies:
                            del db_connection.notifies[:]

                            cursor.execute(
                                '''
                                select *
                                from event.session_queued_events_json(%s)
                            ''', (session_id, ))

                            qe_ids = []
                            logging.info(
                                'event/table/session/row/%s:flushing_queue (role: %s)'
                                % (session_id, env['DB_USER']))

                            for row in cursor:
                                uwsgi.websocket_send(json.dumps(
                                    row.event_json))
                                logging.info(
                                    'event/table/session/row/%s:sent_json (role: %s)'
                                    % (session_id, env['DB_USER']))
                                qe_ids.append(row.queued_event_id)

                            cursor.execute(
                                '''
                                delete from event.queued_event qe
                                where qe.id = any(%s)
                            ''', (qe_ids, ))
                    else:
                        # handle timeout of above wait_fd_read for ping/pong
                        uwsgi.websocket_recv_nb()

            except OSError as err:
                logging.info(
                    'event/table/session/row/%s:disconnected (role: %s)' %
                    (session_id, env['DB_USER']))

        return []
Beispiel #15
0
    def get(self):
        def handle_request(r, msg):
            """Handle request for more messages received from websocket."""

            request = json.loads(msg)
            first = int(request["first_id"])
            last = int(request["last_id"])
            # Don't fetch more than 50 messages at once:
            if (last > 0 and (last - 50 > first)) or (last < 0):
                first = last - 50
            pickled_messages = r.lrange(REDIS_MESSAGES_KEY, first, last)
            messages = []
            for pickled_message in pickled_messages:
                message = pickle.loads(pickled_message)
                messages.append(message)

            uwsgi.websocket_send(encode_messages(messages))

        # The first thing we need to do is take what seems like a normal HTTP
        # request and upgrade it to be a websocket request:
        uwsgi.websocket_handshake(os.getenv('HTTP_SEC_WEBSOCKET_KEY', ''),
                                  os.getenv('HTTP_ORIGIN', ''))

        # Open a connection to the Redis server, and ask to be notified of any
        # messages on the channel REDIS_CHANNEL:
        r = redis.StrictRedis(host='localhost', port=6379, db=0)
        channel = r.pubsub()
        channel.subscribe(REDIS_CHANNEL)

        # We then want to go to sleep and wait for messages either from Redis,
        # or from this websocket.  So we need to know their file descriptors:
        websocket_fd = uwsgi.connection_fd()
        redis_fd = channel.connection._sock.fileno()

        while True:
            # Setup both FDs with epoll so we can wait for messages.  Wake up
            # every 3 seconds to ensure that ping messages get exchanged on the
            # websocket connection to keep it alive:
            uwsgi.wait_fd_read(websocket_fd, 3)
            uwsgi.wait_fd_read(redis_fd)

            # Put thread to sleep until message arrives or timeout.  Note that
            # if you do not use a suspend engine (such as ugreen) this will just
            # immediately return without suspending, nothing will work, and you
            # will get horribly confused.
            uwsgi.suspend()

            fd = uwsgi.ready_fd()
            if fd > -1:
                if fd == websocket_fd:
                    try:
                        msg = uwsgi.websocket_recv_nb()
                        if msg:
                            handle_request(r, msg)

                    except IOError, e:
                        # Websocket has failed in some way (such as a browser
                        # reload), just close it and let the app re-open if it
                        # is still there to do so:
                        return
                elif fd == redis_fd:
                    # Got a message from Redis, pass it on to the browser
                    # through the websocket.
                    msg = channel.parse_response()
                    # Redis sends both control messages and user messages
                    # through this fd.  Send only user-generated messages to all
                    # clients:
                    if msg[0] == b'message':
                        uwsgi.websocket_send(msg[2])
            else:
                # We got a timeout.  Call websocket_recv_nb again to manage
                # ping/pong:
                try:
                    msg = uwsgi.websocket_recv_nb()
                    if msg:
                        handle_request(r, msg)

                except IOError, e:
                    # Websocket has failed in some way (such as a browser
                    # reload), just close it and let the app re-open if it is
                    # still there to do so:
                    return
Beispiel #16
0
def application(env, start_response):
    request = Request(env)

    try:
        uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'],
                                  env.get('HTTP_ORIGIN', ''))
    except OSError as err:
        logging.info('handshake_failed')

    else:
        with cursor_for_request(request) as cursor:
            db_connection = cursor.connection
            db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)

            db_conn_fd = db_connection.fileno()
            websocket_fd = uwsgi.connection_fd()

            logging.info('connection established')

            try:
                while True:
                    uwsgi.wait_fd_read(websocket_fd)
                    uwsgi.wait_fd_read(db_conn_fd)
                    uwsgi.suspend()

                    fd = uwsgi.ready_fd()

                    if fd == websocket_fd:
                        cmd_json = uwsgi.websocket_recv_nb()

                        if cmd_json:
                            cmd = json.loads(cmd_json.decode('utf-8'))

                            if cmd:
                                try:
                                    if cmd['method'] != 'ping':
                                        logging.info('command received: %s' %
                                                     cmd['method'])

                                    if cmd['method'] == 'request':

                                        logging.info(
                                            'websocket endpoint request: %s, %s, %s, %s'
                                            % (
                                                cmd['verb'],  # HTTP method               - GET, POST, PATCH, DELETE
                                                cmd['uri'],  # selector                  - '/relation/widget/dependency_js'
                                                ImmutableMultiDict(
                                                    json.loads(cmd['query'])
                                                ),  # query string arguments    - including event.session id
                                                json.dumps(
                                                    cmd['data'])  # post data
                                            ))

                                        cursor.execute(
                                            'select status, message, response, mimetype from endpoint.request2(%s, %s, %s::json, %s::json);',
                                            (
                                                cmd['verb'],  # HTTP method               - GET, POST, PATCH, DELETE
                                                cmd['uri'],  # selector                  - '/relation/widget/dependency_js'
                                                json.dumps(
                                                    ImmutableMultiDict(
                                                        json.loads(
                                                            cmd['query'])
                                                    ).to_dict(flat=False)
                                                ),  # query string arguments    - including event.session id
                                                json.dumps(
                                                    cmd['data'])  # post data
                                            ))

                                        result = cursor.fetchone()

                                        uwsgi.websocket_send('''{
                                            "method": "response",
                                            "request_id": "%s",
                                            "data": %s
                                        }''' % (cmd['request_id'],
                                                result.response))

                                    elif cmd['method'] == 'attach':
                                        session_id = cmd['session_id']
                                        if session_id is not None:
                                            cursor.execute(
                                                'select event.session_attach(%s);',
                                                (session_id, ))
                                            logging.info(
                                                'session attached: %s (role: %s)'
                                                % (session_id, env['DB_USER']))
                                            handle_db_notifications(
                                                db_connection)

                                            uwsgi.websocket_send('''{
                                                "method": "response",
                                                "request_id": "%s",
                                                "data": "true"
                                            }''' % (cmd['request_id'], ))

                                    elif cmd['method'] == 'detach':
                                        session_id = cmd['session_id']
                                        if session_id is not None:
                                            cursor.execute(
                                                'select event.session_detach(%s);',
                                                (session_id, ))
                                            logging.info(
                                                'session detached: %s (role: %s)'
                                                % (session_id, env['DB_USER']))

                                            uwsgi.websocket_send('''{
                                                "method": "response",
                                                "request_id": "%s",
                                                "data": "true"
                                            }''' % (cmd['request_id'], ))

                                    #uwsgi.websocket_send('''{
                                    #    "method": "response",
                                    #    "request_id": "%s",
                                    #    "data": %s
                                    #}''' % (cmd['request_id'], result.response))

                                except Warning as err:
                                    logging.error(str(err))
#                                    uwsgi.websocket_send(json.dumps({
#                                        "method": "log",
#                                        "args": {
#                                            "level": "warning",
#                                            "message": err.diag.message_primary
#                                        }
#                                    }))

                    elif fd == db_conn_fd:
                        handle_db_notifications(db_connection)

                    else:
                        logging.info(
                            'timeout reached')  # This is never reached

                        # handle timeout of above wait_fd_read for ping/pong
                        uwsgi.websocket_recv_nb()

            except (OSError, IOError) as err:
                logging.info('connection closed (role: %s)' % env['DB_USER'])

        return []