Ejemplo n.º 1
0
def lambda_websocket_to_response(wscontext):
    # meta to remove?
    meta_remove = set()
    for k, v in six.iteritems(wscontext.orig_meta):
        found = False
        for nk, nv in six.iteritems(wscontext.meta):
            if nk.lower() == k:
                found = True
                break
        if not found:
            meta_remove.add(k)

    # meta to set?
    meta_set = {}
    for k, v in six.iteritems(wscontext.meta):
        lname = k.lower()
        need_set = True
        for ok, ov in six.iteritems(wscontext.orig_meta):
            if lname == ok and v == ov:
                need_set = False
                break
        if need_set:
            meta_set[lname] = v

    events = []
    if wscontext.accepted:
        events.append(WebSocketEvent('OPEN'))
    events.extend(wscontext.out_events)
    if wscontext.closed:
        events.append(
            WebSocketEvent('CLOSE', pack('>H', wscontext.out_close_code)))

    headers = {'Content-Type': 'application/websocket-events'}
    if wscontext.accepted:
        headers['Sec-WebSocket-Extensions'] = 'grip'
    for k in meta_remove:
        headers['Set-Meta-' + k] = ''
    for k, v in six.iteritems(meta_set):
        headers['Set-Meta-' + k] = v

    body = encode_websocket_events(events)

    return {
        'isBase64Encoded': True,
        'statusCode': 200,
        'headers': headers,
        'body': b64encode(body).decode('utf-8')
    }
Ejemplo n.º 2
0
    def recv(self):
        e = None
        while e is None and self.read_index < len(self.in_events):
            if self.in_events[self.read_index].type in ('TEXT', 'BINARY',
                                                        'CLOSE', 'DISCONNECT'):
                e = self.in_events[self.read_index]
            elif self.in_events[self.read_index].type == 'PING':
                self.out_events.append(WebSocketEvent('PONG'))
            self.read_index += 1
        if e is None:
            raise IndexError('read from empty buffer')

        if e.type == 'TEXT':
            if e.content:
                return e.content.decode('utf-8')
            else:
                return u''
        elif e.type == 'BINARY':
            if e.content:
                return e.content
            else:
                return ''
        elif e.type == 'CLOSE':
            if e.content and len(e.content) == 2:
                self.close_code = unpack('>H', e.content)[0]
            return None
        else:  # DISCONNECT
            raise IOError('client disconnected unexpectedly')
Ejemplo n.º 3
0
    def reply_message(self):

        # Open the WebSocket and subscribe it to a channel:
        request_body = self.rfile.read(int(self.headers.get('Content-Length')))
        cookies = SimpleCookie(self.headers.get('Cookie'))
        token = cookies['SP_SSO_JWT_COOKIE'].value
        if (not verify_cookie(token)):
            self.send_response(401)
            return ;

        # Set the headers required by the GRIP proxy:
        self.send_response(200)
        self.send_header('Sec-WebSocket-Extensions', 'grip; message-prefix=""')
        self.send_header('Content-Type', 'application/websocket-events')
        self.end_headers()
        in_events = decode_websocket_events(request_body)
        if in_events[0].type == 'OPEN':
            out_events = []
            out_events.append(WebSocketEvent('OPEN'))
            self.wfile.write(encode_websocket_events(out_events))
            logger.info("Connection Opened with Client")
            print("Connection Opened with Client")
        if in_events[0].type == 'TEXT':
            print("Text received from client")
            message = in_events[0].content
            print(message)
            cname = get_channel_name(message)
            print(cname)
            if cname != "all":
                try:
                    create_siddhi_common(message, cname)
                except Exception as e:
                    logger.info("Exception occurred:" +  str(e))
                    print("Exception occurred:" +  str(e))
                    threading.Thread(target=self.publish_message(cname, 'Error while creating the Siddhi app')).start()
                else:
                    logger.info("Siddhi app created")
                    print("Siddhi app created")
                    threading.Thread(target=self.publish_message(cname, 'Created Siddhi app: ' + cname)).start()
            else:
                threading.Thread(target=self.publish_message(cname, 'Please publish a valid Json.' )).start()
                print("Invalid JSON")
            out_events = []
            out_events.append(WebSocketEvent('TEXT', 'c:' + websocket_control_message('subscribe', {'channel': cname})))
            self.wfile.write(encode_websocket_events(out_events))
            print("End of the response")
Ejemplo n.º 4
0
    def post(self, channel: str) -> Response:

        try:
            # in_events = decode_websocket_events(request.get_data())
            in_events = decode_websocket_events(request.get_data())
        except ValueError as e:
            log.error(e)
            raise BadRequest("Cannot decode websocket request: invalid format")

        if in_events is None or len(in_events) <= 0:
            log.error("Websocket request: {}", request.data)
            raise BadRequest(
                "Cannot decode websocket request: invalid in_event")
        in_events = in_events[0]

        event_type = None

        try:
            event_type = in_events.type
        except BaseException as e:  # pragma: no cover
            log.error(e)
            raise BadRequest("Cannot decode websocket request: invalid type")

        if event_type is None:  # pragma: no cover
            raise BadRequest("Cannot decode websocket request, no event type")

        out_events = []
        if event_type == "OPEN":
            ctrl_msg = websocket_control_message("subscribe",
                                                 {"channel": channel})
            out_events.append(WebSocketEvent("OPEN"))
            out_events.append(WebSocketEvent(
                "TEXT",
                f"c:{ctrl_msg}",
            ))
            headers = {"Sec-WebSocket-Extensions": "grip"}
            resp = FlaskResponse(
                encode_websocket_events(out_events),
                mimetype="application/websocket-events",
                headers=headers,
            )
            return resp

        log.error("Unknkown event type: {}", event_type)
        raise BadRequest("Cannot understand websocket request")
Ejemplo n.º 5
0
    def post(self, channel):

        in_events = decode_websocket_events(request.data)
        if in_events is None or len(in_events) <= 0:
            log.error("Websocket request: {}", request.data)
            raise RestApiException("Cannot decode websocket request")
        in_events = in_events[0]

        event_type = None

        try:
            event_type = in_events.type
        except BaseException as e:
            log.error(e)
            raise RestApiException("Cannot decode websocket request")

        if event_type is None:
            log.error("Event type is None")
            raise RestApiException("Cannot decode websocket request")

        out_events = []
        if event_type == 'OPEN':
            out_events.append(WebSocketEvent('OPEN'))
            out_events.append(
                WebSocketEvent(
                    'TEXT',
                    'c:' + websocket_control_message('subscribe',
                                                     {'channel': channel}),
                ))
            headers = {'Sec-WebSocket-Extensions': 'grip'}
            resp = Response(
                encode_websocket_events(out_events),
                mimetype='application/websocket-events',
                headers=headers,
            )
            return resp

        log.error("Unknkown event type: {}", event_type)
        raise RestApiException("Cannot understand websocket request")
Ejemplo n.º 6
0
    def process_response(self, request, response):
        # if this was a successful websocket-events request, then hijack the
        #   response
        if (getattr(request, 'wscontext', None) and response.status_code == 200
                and len(response.content) == 0):
            wscontext = request.wscontext

            # meta to remove?
            meta_remove = set()
            for k, v in six.iteritems(wscontext.orig_meta):
                found = False
                for nk, nv in wscontext.meta:
                    if nk.lower() == k:
                        found = True
                        break
                if not found:
                    meta_remove.add(k)

            # meta to set?
            meta_set = {}
            for k, v in six.iteritems(wscontext.meta):
                lname = k.lower()
                need_set = True
                for ok, ov in wscontext.orig_meta:
                    if lname == ok and v == ov:
                        need_set = False
                        break
                if need_set:
                    meta_set[lname] = v

            events = []
            if wscontext.accepted:
                events.append(WebSocketEvent('OPEN'))
            events.extend(wscontext.out_events)
            if wscontext.closed:
                events.append(
                    WebSocketEvent('CLOSE', pack('>H',
                                                 wscontext.out_close_code)))

            response = HttpResponse(
                encode_websocket_events(events),
                content_type='application/websocket-events')
            if wscontext.accepted:
                response['Sec-WebSocket-Extensions'] = 'grip'
            for k in meta_remove:
                response['Set-Meta-' + k] = ''
            for k, v in six.iteritems(meta_set):
                response['Set-Meta-' + k] = v
        else:
            instruct = request.grip.instruct

            if instruct:
                if (not request.grip.proxied
                        and getattr(settings, 'GRIP_PROXY_REQUIRED', False)):
                    return HttpResponse('Not Implemented\n', status=501)

                if instruct.hold:
                    # code 304 only allows certain headers. if the webserver
                    #   strictly enforces this, then we won't be able to use
                    #   Grip- headers to talk to the proxy. switch to code
                    #   200 and use Grip-Status to specify intended status
                    if response.status_code == 304:
                        response.status_code = 200
                        response.reason_phrase = 'OK'
                        response['Grip-Status'] = '304'

                    response['Grip-Hold'] = instruct.hold

                # apply prefix to channels if needed
                prefix = _get_prefix()
                if prefix:
                    for c in instruct.channels:
                        c.name = prefix + c.name

                response['Grip-Channel'] = create_grip_channel_header(
                    instruct.channels)

                if instruct.hold:
                    if instruct.timeout > 0:
                        response['Grip-Timeout'] = str(instruct.timeout)

                    if instruct.keep_alive:
                        response['Grip-Keep-Alive'] = _keep_alive_header(
                            instruct.keep_alive, instruct.keep_alive_timeout)

                    if instruct.meta:
                        response['Grip-Set-Meta'] = _set_meta_header(
                            instruct.meta)

                if instruct.next_link:
                    hvalue = '<%s>; rel=next' % instruct.next_link
                    if instruct.next_link_timeout > 0:
                        hvalue += '; timeout=%d' % instruct.next_link_timeout
                    response['Grip-Link'] = hvalue

        return response
Ejemplo n.º 7
0
    def post(self):
        #####################################
        # FIXME add connection last seen timestamp
        connection_id = self.request.headers['Connection-Id']
        in_events = decode_websocket_events(self.request.body)
        out_events = []
        if len(in_events) == 0:
            return

        logger.debug(in_events[0].type)
        if in_events[0].type == 'OPEN':
            out_events.append(WebSocketEvent('OPEN'))
            out_events.append(
                WebSocketEvent('TEXT', 'm:' +
                               json.dumps({'__restream_type': 'ready'})))
        elif in_events[0].type == 'TEXT':
            msg = in_events[0].content
            logger.debug(msg)
            command = parse_message(msg)
            if command['__restream_type'] == 'error':
                out_events.append(
                    WebSocketEvent('TEXT', 'm:' + json.dumps(command)))
            elif command['action'] == 'subscribe':
                if connection_id in connection_channels and command[
                        'channel_id'] in connection_channels[connection_id]:
                    logger.info(
                        "Connection {} already subscribed to {}".format(
                            connection_id, command['channel_id']))
                else:
                    out_events.append(
                        WebSocketEvent(
                            'TEXT',
                            'm:' + json.dumps({
                                '__restream_type': 'subscribe',
                                'channel': command['channel']
                            })))
                    out_events.append(
                        WebSocketEvent(
                            'TEXT', 'c:' + websocket_control_message(
                                'subscribe',
                                {'channel': command['channel_id']})))
                    process_subscribe(command, self.channel_fetchers,
                                      connection_id)
                    logger.info('subscribe {} to {}'.format(
                        connection_id, command['channel_id']))
            elif command['action'] == 'unsubscribe':
                if connection_id not in connection_channels or command[
                        'channel_id'] not in connection_channels[connection_id]:
                    logger.info(
                        "Connection {} not subscribed to {}; won't unsubscribe"
                        .format(connection_id, command['channel_id']))
                else:
                    out_events.append(
                        WebSocketEvent(
                            'TEXT',
                            'm:' + json.dumps({
                                '__restream_type': 'unsubscribe',
                                'channel': command['channel']
                            })))
                    out_events.append(
                        WebSocketEvent(
                            'TEXT', 'c:' + websocket_control_message(
                                'unsubscribe',
                                {'channel': command['channel_id']})))
                    process_unsubscribe(command['channel_id'], connection_id)
                    logger.info('unsubscribe {} from {}'.format(
                        connection_id, command['channel_id']))
        elif in_events[0].type == 'DISCONNECT' or in_events[0].type == 'CLOSE':
            out_events.append(WebSocketEvent(in_events[0].type))
            if connection_id in connection_channels:
                disconnect_all(connection_id)
        else:
            logger.info('event type not recognized: ' + in_events[0].type)

        self.write(encode_websocket_events(out_events))
        self.set_header('Sec-WebSocket-Extensions', 'grip')
        self.set_header('Content-Type', 'application/websocket-events')
        self.finish()
Ejemplo n.º 8
0
    def process_response(self, request, response):
        # if this was a successful websocket-events request, then hijack the response
        if getattr(request, 'wscontext',
                   None) and response.status_code == 200 and len(
                       response.content) == 0:
            wscontext = request.wscontext

            # meta to remove?
            meta_remove = set()
            for k, v in wscontext.orig_meta.iteritems():
                found = False
                for nk, nv in wscontext.meta:
                    if nk.lower() == k:
                        found = True
                        break
                if not found:
                    meta_remove.add(k)

            # meta to set?
            meta_set = dict()
            for k, v in wscontext.meta.iteritems():
                lname = k.lower()
                need_set = True
                for ok, ov in wscontext.orig_meta:
                    if lname == ok and v == ov:
                        need_set = False
                        break
                if need_set:
                    meta_set[lname] = v

            events = list()
            if wscontext.accepted:
                events.append(WebSocketEvent('OPEN'))
            events.extend(wscontext.out_events)
            if wscontext.closed:
                events.append(
                    WebSocketEvent('CLOSE', pack('>H',
                                                 wscontext.out_close_code)))

            response = HttpResponse(
                encode_websocket_events(events),
                content_type='application/websocket-events')
            if wscontext.accepted:
                response['Sec-WebSocket-Extensions'] = 'grip'
            for k in meta_remove:
                response['Set-Meta-' + k] = ''
            for k, v in meta_set.iteritems():
                response['Set-Meta-' + k] = v
        else:
            grip_info = None
            if hasattr(request, 'grip_info'):
                grip_info = request.grip_info
            elif hasattr(response, 'grip_info'):
                # old django-grip versions required passing an HttpResponse to the
                #   set_hold_* methods, so fall back to that for backwards compat
                grip_info = response.grip_info

            if grip_info:
                if not request.grip_proxied and getattr(
                        settings, 'GRIP_PROXY_REQUIRED', False):
                    return HttpResponse('Not Implemented\n', status=501)

                channels = grip_info['channels']

                # apply prefix to channels if needed
                prefix = _get_prefix()
                if prefix:
                    for c in channels:
                        c.name = prefix + c.name

                # code 304 only allows certain headers. if the webserver
                #   strictly enforces this, then we won't be able to use
                #   Grip- headers to talk to the proxy. work around this by
                #   using body instructions instead.
                if response.status_code == 304:
                    headers = list()
                    for k, v in response.items():
                        headers.append([k, v])
                    iresponse = Response(code=response.status_code,
                                         reason=getattr(
                                             response, 'reason_phrase', None),
                                         headers=headers,
                                         body=response.content)
                    body = create_hold(grip_info['hold'],
                                       channels,
                                       iresponse,
                                       timeout=grip_info.get('timeout'))
                    response = HttpResponse(
                        body + '\n', content_type='application/grip-instruct')
                else:
                    response['Grip-Hold'] = grip_info['hold']
                    response['Grip-Channel'] = create_grip_channel_header(
                        channels)
                    if 'timeout' in grip_info:
                        response['Grip-Timeout'] = str(grip_info['timeout'])

        return response
Ejemplo n.º 9
0
 def send_control(self, message):
     if isinstance(message, unicode):
         message = message.encode('utf-8')
     self.out_events.append(WebSocketEvent('TEXT', 'c:' + message))
Ejemplo n.º 10
0
 def send_binary(self, message):
     if isinstance(message, unicode):
         message = message.encode('utf-8')
     self.out_events.append(WebSocketEvent('BINARY', 'm:' + message))
Ejemplo n.º 11
0
out_headers = []
out = []
for e in decode_websocket_events(sys.stdin.read()):
    if e.type == 'OPEN':
        if not opening:
            opening = True

            # enable GRIP
            out_headers.append(('Sec-WebSocket-Extensions', 'grip'))

            # ack the open
            out.append(e)

            # subscribe connection to channel
            cm = {'type': 'subscribe', 'channel': 'room'}
            out.append(WebSocketEvent('TEXT', 'c:%s' % json.dumps(cm)))
    elif e.type == 'CLOSE':
        out.append(e)  # ack
        break
    elif e.type == 'TEXT':
        # broadcast to everyone
        pub.publish('room', Item(WebSocketMessageFormat(e.content)))

out_headers.append(('Content-Type', 'application/websocket-events'))

for header in out_headers:
    cm = {
        'type': 'setHeader',
        'payload': {
            'name': header[0],
            'value': header[1]