def run_callback(self, obj, args=None):
     try:
         assert hasattr(self, 'on%s' % obj)
         f = getattr(self, 'on%s' % obj)
         if args is not None:
             return f(args)
         else:
             return f()
     except WebSocketError as e:
         if is_ws_error_abnormal(e):
             log.warn('WebSocket fault: %s' % e.message)
             log.error(format_exception(e, None),
                       extra=self.channel_history)
             report_exception(e, extra=self.channel_history)
     except Exception as e:
         self.onerror(e)
         if not self.ws.closed:
             try:
                 self.ws.close()
             except WebSocketError as e:
                 if is_ws_error_abnormal(e):
                     log.error('WebSocket fault: %s' % e.message,
                               extra=self.channel_history)
     finally:
         if USE_ALCHEMY_MW:
             session_handler.close()
예제 #2
0
 def run_callback(self, obj, args=None):
     try:
         assert hasattr(self, 'on%s' % obj)
         f = getattr(self, 'on%s' % obj)
         if args is not None:
             return f(args)
         else:
             return f()
     except WebSocketError as e:
         if is_ws_error_abnormal(e):
             log.warn('WebSocket fault: %s' % e.message)
             log.error(format_exception(e, None),
                       extra=self.channel_history)
             report_exception(e, extra=self.channel_history)
     except Exception as e:
         self.onerror(e)
         if not self.ws.closed:
             try:
                 self.ws.close()
             except WebSocketError as e:
                 if is_ws_error_abnormal(e):
                     log.error('WebSocket fault: %s' % e.message,
                               extra=self.channel_history)
     finally:
         if USE_ALCHEMY_MW:
             session_handler.close()
예제 #3
0
    def close(self, data):
        if not data.get('channel'):
            raise Exception('No channel name, exit')

        handler = self.channel_handlers.get(data['channel'])

        if not handler:
            return self.channel_404(data['channel'])

        if self.check_permissions and not self.validate_close(data['channel']):
            return self.send_error_code(403, 'open', data['channel'])

        if not handler.closable and not self.ws.closed:
            try:
                self.ws.send(
                    json.dumps({
                        'pkg': {
                            'action': 'close',
                            'data': {
                                'channel': data['channel'],
                                'result': 501
                            },
                        },
                    }))
            except WebSocketError as e:
                if is_ws_error_abnormal(e):
                    log.error('WebSocket fault: %s' % e.message,
                              extra=self.channel_history)
            return

        handler.onclose()
        del self.channel_handlers[data['channel']]

        if not self.ws.closed:
            try:
                self.ws.send(
                    json.dumps({
                        'pkg': {
                            'action': 'close',
                            'data': {
                                'channel': data['channel'],
                                'result': 200
                            },
                        },
                    }))
            except WebSocketError as e:
                if is_ws_error_abnormal(e):
                    log.error('WebSocket fault: %s' % e.message,
                              extra=self.channel_history)
 def onerror(self, e):
     """Send here Exception and traceback by Error channel
     """
     f = Formatter()
     history = json.dumps(self.channel_history,
                          indent=2,
                          default=datahandler)
     data = (history, xml_escape(f.formatException(sys.exc_info())),)
     if EXCEPTION_FLAVOR == 'html':
         traceback = '<pre>%s\n\n%s</pre>' % data
     else:
         traceback = '%s\n%s' % data
     if DEBUG:
         err_message = {'channel': WS_CHANNELS['ERROR_CHID'],
                        'pkg': {'exception': repr(e), 'tb': traceback}}
     else:
         err_message = {'channel': WS_CHANNELS['ERROR_CHID'],
                        'pkg': {'exception': 'error 500',
                                'tb': 'an error occurred'}}
     log.error(format_exception(e, None), extra=self.channel_history)
     report_exception(e, extra=self.channel_history)
     if not self.ws.closed:
         try:
             self.ws.send(json.dumps(err_message, separators=(', ', ':')))
         except WebSocketError as e:
             if is_ws_error_abnormal(e):
                 log.error('WebSocket fault: %s' % e.message,
                           extra=self.channel_history)
 def channel_404(self, channel):
     try:
         return self.ws.send(json.dumps({'channel': channel,
                                         'action': 'no-such-channel',
                                         'note': 'Channel with ID=%s not '
                                                 'found' % channel,
                                         }))
     except WebSocketError as e:
         if is_ws_error_abnormal(e):
             log.error('WebSocket fault: %s' % e.message,
                       extra=self.channel_history)
    def close(self, data):
        if not data.get('channel'):
            raise Exception('No channel name, exit')

        handler = self.channel_handlers.get(data['channel'])

        if not handler:
            return self.channel_404(data['channel'])

        if self.check_permissions and not self.validate_close(data['channel']):
            return self.send_error_code(403, 'open', data['channel'])

        if not handler.closable and not self.ws.closed:
            try:
                self.ws.send(
                    json.dumps({'pkg': {'action': 'close',
                                        'data': {'channel': data['channel'],
                                                 'result': 501},
                                        },
                                }))
            except WebSocketError as e:
                if is_ws_error_abnormal(e):
                    log.error('WebSocket fault: %s' % e.message,
                              extra=self.channel_history)
            return

        handler.onclose()
        del self.channel_handlers[data['channel']]

        if not self.ws.closed:
            try:
                self.ws.send(
                    json.dumps({'pkg': {'action': 'close',
                                        'data': {'channel': data['channel'],
                                                 'result': 200},
                                        },
                                }))
            except WebSocketError as e:
                if is_ws_error_abnormal(e):
                    log.error('WebSocket fault: %s' % e.message,
                              extra=self.channel_history)
예제 #7
0
 def channel_404(self, channel):
     try:
         return self.ws.send(
             json.dumps({
                 'channel': channel,
                 'action': 'no-such-channel',
                 'note': 'Channel with ID=%s not '
                 'found' % channel,
             }))
     except WebSocketError as e:
         if is_ws_error_abnormal(e):
             log.error('WebSocket fault: %s' % e.message,
                       extra=self.channel_history)
 def bad_request(self, message="Bad request"):
     if not self.ws.closed:
         try:
             self.ws.send(
                 json.dumps({'pkg': {'action': 'open',
                                     'data': {'result': 400,
                                              'message': message,
                                              },
                                     },
                             }))
         except WebSocketError as e:
             if is_ws_error_abnormal(e):
                 log.error('WebSocket fault: %s' % e.message,
                           extra=self.channel_history)
 def send_error_code(self, code, act, channel):
     if not self.ws.closed:
         try:
             self.ws.send(json.dumps({'pkg': {'action': act,
                                      'data': {'channel': channel,
                                               'result': code,
                                               },
                                              },
                                      }))
             self.ws.close()
         except WebSocketError as e:
             if is_ws_error_abnormal(e):
                 log.error('WebSocket fault: %s' % e.message,
                           extra=self.channel_history)
 def _send_ws(self, data):
     if type(data) != dict:
         raise TypeError("data is %s not dict" % type(data))
     package_to_send = {'channel': self.channel,
                        'pkg': data,
                        'session_params': self.session.params,
                        }
     data = json.dumps(package_to_send, default=datahandler)
     try:
         self.ws.send(data)
     except WebSocketError as e:
         if is_ws_error_abnormal(e):
             log.error('WebSocket fault: %s' % e.message,
                       extra=self.channel_history)
         self.onclose()
예제 #11
0
 def _send_ws(self, data):
     if type(data) != dict:
         raise TypeError("data is %s not dict" % type(data))
     package_to_send = {
         'channel': self.channel,
         'pkg': data,
         'session_params': self.session.params,
     }
     data = json.dumps(package_to_send, default=datahandler)
     try:
         self.ws.send(data)
     except WebSocketError as e:
         if is_ws_error_abnormal(e):
             log.error('WebSocket fault: %s' % e.message,
                       extra=self.channel_history)
         self.onclose()
예제 #12
0
 def bad_request(self, message="Bad request"):
     if not self.ws.closed:
         try:
             self.ws.send(
                 json.dumps({
                     'pkg': {
                         'action': 'open',
                         'data': {
                             'result': 400,
                             'message': message,
                         },
                     },
                 }))
         except WebSocketError as e:
             if is_ws_error_abnormal(e):
                 log.error('WebSocket fault: %s' % e.message,
                           extra=self.channel_history)
예제 #13
0
    def open(self, data):
        self.propagate_greenlet_data(data)
        if not data.get('token'):
            self.bad_request(message='No access token, exit')
            return

        if not data.get('channel'):
            self.bad_request(message='No channel name')
            return

        self.access_token = data.get('token')
        self.reopen = data.get('reopen', False)
        self.pre_open()
        handler = self.allowed_channels.get(data.get('channel'))
        if not handler:
            return self.channel_404(data['channel'])

        if self.check_permissions \
                and not self.validate_open(data.get('channel')):
            return self.send_error_code(403, 'open', data.get('channel'))
        if not self.is_auth:
            return self.send_error_code(403, 'open', data.get('channel'))

        handler = self.register_channel(data.get('channel'), handler)
        self.run_callback('open')
        pkg = {
            'action': 'open',
            'data': {
                'closable': handler.closable,
                'result': 200
            },
        }
        package_to_send = {
            'channel': data.get('channel'),
            'pkg': pkg,
            'session_params': self.session.params
        }
        raw_data = json.dumps(package_to_send, default=datahandler)
        self.after_open()
        try:
            self.ws.send(raw_data)
        except WebSocketError as e:
            if is_ws_error_abnormal(e):
                log.error('WebSocket fault: %s' % e.message,
                          extra=self.channel_history)
예제 #14
0
 def send_error_code(self, code, act, channel):
     if not self.ws.closed:
         try:
             self.ws.send(
                 json.dumps({
                     'pkg': {
                         'action': act,
                         'data': {
                             'channel': channel,
                             'result': code,
                         },
                     },
                 }))
             self.ws.close()
         except WebSocketError as e:
             if is_ws_error_abnormal(e):
                 log.error('WebSocket fault: %s' % e.message,
                           extra=self.channel_history)
예제 #15
0
 def onerror(self, e):
     """Send here Exception and traceback by Error channel
     """
     f = Formatter()
     history = json.dumps(self.channel_history,
                          indent=2,
                          default=datahandler)
     data = (
         history,
         xml_escape(f.formatException(sys.exc_info())),
     )
     if EXCEPTION_FLAVOR == 'html':
         traceback = '<pre>%s\n\n%s</pre>' % data
     else:
         traceback = '%s\n%s' % data
     if DEBUG:
         err_message = {
             'channel': WS_CHANNELS['ERROR_CHID'],
             'pkg': {
                 'exception': repr(e),
                 'tb': traceback
             }
         }
     else:
         err_message = {
             'channel': WS_CHANNELS['ERROR_CHID'],
             'pkg': {
                 'exception': 'error 500',
                 'tb': 'an error occurred'
             }
         }
     log.error(format_exception(e, None), extra=self.channel_history)
     report_exception(e, extra=self.channel_history)
     if not self.ws.closed:
         try:
             self.ws.send(json.dumps(err_message, separators=(', ', ':')))
         except WebSocketError as e:
             if is_ws_error_abnormal(e):
                 log.error('WebSocket fault: %s' % e.message,
                           extra=self.channel_history)
    def open(self, data):
        self.propagate_greenlet_data(data)
        if not data.get('token'):
            self.bad_request(message='No access token, exit')
            return

        if not data.get('channel'):
            self.bad_request(message='No channel name')
            return

        self.access_token = data.get('token')
        self.reopen = data.get('reopen', False)
        self.pre_open()
        handler = self.allowed_channels.get(data.get('channel'))
        if not handler:
            return self.channel_404(data['channel'])

        if self.check_permissions \
                and not self.validate_open(data.get('channel')):
            return self.send_error_code(403, 'open', data.get('channel'))
        if not self.is_auth:
            return self.send_error_code(403, 'open', data.get('channel'))

        handler = self.register_channel(data.get('channel'), handler)
        self.run_callback('open')
        pkg = {'action': 'open',
               'data': {'closable': handler.closable,
                        'result': 200},
               }
        package_to_send = {'channel': data.get('channel'),
                           'pkg': pkg,
                           'session_params': self.session.params}
        raw_data = json.dumps(package_to_send, default=datahandler)
        self.after_open()
        try:
            self.ws.send(raw_data)
        except WebSocketError as e:
            if is_ws_error_abnormal(e):
                log.error('WebSocket fault: %s' % e.message,
                          extra=self.channel_history)
예제 #17
0
    def __call__(self, env, start_response):
        websocket = env.get('wsgi.websocket')
        if not websocket:
            self.bad_request()
        self.ws = websocket
        # Endless event loop
        while 1:
            try:
                data = self.ws.receive()
                self.clear_test_data()
            except WebSocketError as e:
                if is_ws_error_abnormal(e):
                    log.error('WebSocket fault: %s' % e.message,
                              extra=self.channel_history)
                break
            except Exception:
                f = Formatter()
                traceback = f.formatException(sys.exc_info())
                log.error('Servlet fault: \n%s' % traceback,
                          extra=self.channel_history)
                break

            if data:
                jd = json.loads(data)
                if jd.get('pkg') \
                        and jd['pkg'].get('data') \
                        and isinstance(jd['pkg']['data'], dict)\
                        and jd['pkg']['data'].get('testData'):
                    self.write_test_data(jd['pkg']['data']['testData'])
                    del jd['pkg']['data']['testData']
                self.channel_history['messages'].append(jd)
                if hasattr(self.session, 'sess') and self.session.sess:
                    self.channel_history['session_id'] = self.session.sess.id
                    self.channel_history['user_id'] = self.session.sess.user_id
                if not jd.get('channel') and jd.get('pkg'):
                    act = jd['pkg'].get('action')
                    assert not act.startswith('_'), "security violation"
                    try:
                        handler = getattr(self, act)
                    except WebSocketError as e:
                        if is_ws_error_abnormal(e):
                            f = Formatter()
                            traceback = f.formatException(sys.exc_info())
                            log.error('Global channel action error: \n%s' %
                                      traceback,
                                      extra=self.channel_history)
                        break
                    assert handler.__name__ == "action_wrapper", \
                        "%s is not allowed to be executed externally." % act
                    handler(jd['pkg']['data'])
                    continue
                if self.check_permissions \
                        and not self.validate_send(jd.get('channel')):
                    jd['result'] = 403
                    if not self.ws.closed:
                        try:
                            self.ws.send(json.dumps(jd))
                        except WebSocketError as e:
                            if is_ws_error_abnormal(e):
                                log.error('WebSocket fault: %s' % e.message,
                                          extra=self.channel_history)
                    continue
                else:
                    self.run_callback('message', ApiSocketMessage(data))
            else:
                log.debug('Web Socket is disconnected')
                self.close_event.set()
            if self.close_event.is_set():
                break
        self.run_callback('close')
    def __call__(self, env, start_response):
        websocket = env.get('wsgi.websocket')
        if not websocket:
            self.bad_request()
        self.ws = websocket
        # Endless event loop
        while 1:
            try:
                data = self.ws.receive()
                self.clear_test_data()
            except WebSocketError as e:
                if is_ws_error_abnormal(e):
                    log.error('WebSocket fault: %s' % e.message,
                              extra=self.channel_history)
                break
            except Exception:
                f = Formatter()
                traceback = f.formatException(sys.exc_info())
                log.error('Servlet fault: \n%s' % traceback,
                          extra=self.channel_history)
                break

            if data:
                jd = json.loads(data)
                if jd.get('pkg') \
                        and jd['pkg'].get('data') \
                        and isinstance(jd['pkg']['data'], dict)\
                        and jd['pkg']['data'].get('testData'):
                    self.write_test_data(jd['pkg']['data']['testData'])
                    del jd['pkg']['data']['testData']
                self.channel_history['messages'].append(jd)
                if hasattr(self.session, 'sess') and self.session.sess:
                    self.channel_history['session_id'] = self.session.sess.id
                    self.channel_history['user_id'] = self.session.sess.user_id
                if not jd.get('channel') and jd.get('pkg'):
                    act = jd['pkg'].get('action')
                    assert not act.startswith('_'), "security violation"
                    try:
                        handler = getattr(self, act)
                    except WebSocketError as e:
                        if is_ws_error_abnormal(e):
                            f = Formatter()
                            traceback = f.formatException(sys.exc_info())
                            log.error('Global channel action error: \n%s'
                                      % traceback, extra=self.channel_history)
                        break
                    assert handler.__name__ == "action_wrapper", \
                        "%s is not allowed to be executed externally." % act
                    handler(jd['pkg']['data'])
                    continue
                if self.check_permissions \
                        and not self.validate_send(jd.get('channel')):
                    jd['result'] = 403
                    if not self.ws.closed:
                        try:
                            self.ws.send(json.dumps(jd))
                        except WebSocketError as e:
                            if is_ws_error_abnormal(e):
                                log.error('WebSocket fault: %s' % e.message,
                                          extra=self.channel_history)
                    continue
                else:
                    self.run_callback('message', ApiSocketMessage(data))
            else:
                log.debug('Web Socket is disconnected')
                self.close_event.set()
            if self.close_event.is_set():
                break
        self.run_callback('close')