Пример #1
0
 def parse_request(self, data):
     """ Attempts to load the request, validates it, and calls it. """
     try:
         obj = json.loads(data)
     except ValueError:
         return json.dumps(ProtocolError(-32700).generate_error())
     if not obj:
         return json.dumps(ProtocolError(-32600).generate_error())
     batch = True
     if type(obj) is not list:
         batch = False
         obj = [obj,]
     responses = []
     for req in obj:
         request_error = ProtocolError(-32600)
         if type(req) is not dict:
             responses.append(request_error.generate_error())
         elif 'method' not in req.keys() or \
             type(req['method']) not in types.StringTypes:
             responses.append(request_error.generate_error())
         else:
             result = self.parse_call(req)
             if req.has_key('id'):
                 response = generate_response(result, id=req.get('id'))
                 responses.append(response)
     if not responses:
         # It's either a batch of notifications or a single
         # notification, so return nothing.
         return ''
     else:
         if not batch:
             # Single request
             responses = responses[0]
         return json.dumps(responses)
Пример #2
0
 def _parse_response(self, response):
     if response == '':
         return None
     try:
         obj = json.loads(response)
     except ValueError:
         raise ProtocolError(-32700)
     if obj == dict() and 'error' in obj:
         raise ProtocolError(
             obj.get('error').get('code'),
             obj.get('error').get('message'),
             obj.get('error').get('data', None))
     return obj
Пример #3
0
 def _parse_response(self, response):
     if response == '':
         return None
     try:
         obj = json.loads(response)
     except ValueError:
         raise ProtocolError(-32700)
     if type(obj) is dict and obj.has_key('error'):
         raise ProtocolError(
             obj.get('error').get('code'),
             obj.get('error').get('message'),
             obj.get('error').get('data', None))
     return obj
Пример #4
0
    def process(self, sock, addr):
        """
        Retrieves the data stream from the socket and validates it.
        """
        self.socket = sock
        self.socket.settimeout(config.timeout)
        self.client_address = addr
        requestlines = []
        while True:
            data = self.get_data()
            if not data:
                break
            if type(data) != type('data'):
                data = data.decode('utf-8')
            requestlines.append(data)
            if len(data) < config.buffer:
                break
        request = ''.join(requestlines)
        response = ''
        crypt_error = False
        if config.secret:
            crypt = config.crypt.new(config.secret)
            try:
                request = crypt.decrypt(request)
            except ValueError:
                crypt_error = True
                error = ProtocolError(-32700, 'Could not decrypt request.')
                response = json.dumps(error.generate_error())
        history.request = request
        logger.debug('SERVER | REQUEST: %s' % request)
        if self.socket_error:
            self.socket.close()
        else:
            if not crypt_error:
                response = self.parse_request(request)
            history.response = response
            logger.debug('SERVER | RESPONSE: %s' % response)
            if config.secret:
                length = config.crypt_chunk_size
                pad_length = length - (len(response) % length)
                response = crypt.encrypt('%s%s' % (response, ' ' * pad_length))

            if type(response) == type('response'):
                response = response.encode('utf-8')
            self.socket.send(response)
        self.socket.close()
Пример #5
0
    def _send_and_receive(self, message, batch=False, notify=False):
        """
        Handles the socket connection, sends the JSON request, and
        (if not a notification) retrieves the response and decodes the
        JSON text.
        """
        # Starting with a clean history
        history.request = message
        logger.debug('CLIENT | REQUEST: %s' % message)

        if self._key:
            crypt = config.crypt.new(self._key)
            length = config.crypt_chunk_size
            pad_length = length - (len(message) % length)
            message = crypt.encrypt('%s%s' % (message, ' ' * pad_length))
        print(message)
        if type(message) == type("message"):  # encode
            message = message.encode("utf-8")

        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(config.timeout)
        sock.connect(self._addr)
        sock.send(message)

        responselist = []
        if notify:
            # single notification, we don't need a response.
            sock.close()
        else:
            while True:
                try:
                    data = sock.recv(config.buffer)
                except socket.timeout:
                    break
                if not data:
                    break
                if type(data) != type("data"):
                    data = data.decode("utf-8")
                responselist.append(data)
                if len(data) < config.buffer:
                    break
            sock.close()
        response = ''.join(responselist)
        if self._key:
            try:
                response = crypt.decrypt(response)
            except ValueError:
                # What exactly is an intuitive response to a poorly- or
                # not-encrypted response to an encrypted request?
                raise ProtocolError(-32700, 'Response not encrypted properly.')
            # Should we do a preliminary json.loads here to verify that the
            # decryption succeeded?
        logger.debug('CLIENT | RESPONSE: %s' % response)
        history.response = response
        return response
Пример #6
0
    def _parse_response(self, response):
        if response == '':
            self._close()
            raise ProtocolError(-32700)
        try:
            obj = json.loads(response)
        except ValueError:
            self._close()
            raise ProtocolError(-32700)

        if type(obj) is dict and ('error' in obj) and obj.get('error') != None:
            self._close()
            if isinstance(obj.get('error'), str):
                raise ProtocolError(-1, obj.get('error'), None)
            else:
                raise ProtocolError(
                    obj.get('error').get('code'),
                    obj.get('error').get('message'),
                    obj.get('error').get('data', None))
        return obj
Пример #7
0
 def process(self, sock, addr):
     """
     Retrieves the data stream from the socket and validates it.
     """
     self.socket = sock
     self.socket.settimeout(config.timeout)
     self.client_address = addr
     requestlines = []
     while True:
         data = self.get_data()
         if not data: 
             break
         requestlines.append(data)
         if len(data) < config.buffer: 
             break
     request = ''.join(requestlines)
     response = ''
     crypt_error = False
     if config.secret:
         crypt = config.crypt.new(config.secret)
         try:
             request = crypt.decrypt(request)
         except ValueError:
             crypt_error = True
             error = ProtocolError(-32700, 'Could not decrypt request.')
             response = json.dumps(error.generate_error())
     history.request = request
     logger.debug('SERVER | REQUEST: %s' % request)
     if self.socket_error:
         self.socket.close()
     else:
         if not crypt_error:
             response = self.parse_request(request)
         history.response = response
         logger.debug('SERVER | RESPONSE: %s' % response)
         if config.secret:
             length = config.crypt_chunk_size
             pad_length = length - (len(response) % length)
             response = crypt.encrypt('%s%s' % (response, ' '*pad_length))
         self.socket.send(response)
     self.socket.close()
Пример #8
0
 def parse_request(self, data):
     """ Attempts to load the request, validates it, and calls it. """
     try:
         obj = json.loads(data)
     except ValueError:
         return json.dumps(ProtocolError(-32700).generate_error())
     if not obj:
         return json.dumps(ProtocolError(-32600).generate_error())
     batch = True
     if type(obj) is not list:
         batch = False
         obj = [obj,]
     responses = []
     for req in obj:
         request_error = ProtocolError(-32600)
         if type(req) is not dict:
             responses.append(request_error.generate_error())
         elif 'method' not in req.keys() or \
             type(req['method']) not in types.StringTypes:
             responses.append(request_error.generate_error())
         else:
             result = self.parse_call(req)
             if req.has_key('id'):
                 response = generate_response(result, id=req.get('id'))
                 responses.append(response)
     if not responses:
         # It's either a batch of notifications or a single
         # notification, so return nothing.
         return ''
     else:
         if not batch:
             # Single request
             responses = responses[0]
         return json.dumps(responses)
Пример #9
0
    def parse_call(self, obj):
        """
        Parses a JSON request.
        """

        # Get ID, Notification if None
        # This is actually incorrect, as IDs can be null by spec (rare)
        request_id = obj.get('id', None)

        # Check for required parameters
        jsonrpc = obj.get('jsonrpc', None)
        method = obj.get('method', None)
        if not jsonrpc or not method:
            return ProtocolError(-32600)

        # Validate parameters
        params = obj.get('params', [])
        if type(params) not in (list, dict):
            return ProtocolError(-32602)

        # Parse Request
        kwargs = {}
        if type(params) is dict:
            kwargs = params
            params = []
        handler = self.json_request.get_handler(method)
        error_code = None
        message = None
        if handler:
            try:
                response = handler(*params, **kwargs)
                return response
            except Exception:
                logger.error('Error calling handler %s' % method)
                message = traceback.format_exc().splitlines()[-1]
                error_code = -32603
        else:
            error_code = -32601
        return ProtocolError(error_code, message=message)
Пример #10
0
def validate_response(response):
    """
    Parses the returned JSON object, verifies that it follows
    the JSON-RPC spec, and checks for errors, raising exceptions
    as necessary.
    """
    jsonrpc = response.has_key('jsonrpc')
    response_id = response.has_key('id')
    result = response.has_key('result')
    error = response.has_key('error')
    if not jsonrpc or not response_id or (not result and not error):
        raise Exception('Server returned invalid response.')
    if error:
        raise ProtocolError(response['error']['code'],
                            response['error']['message'])
Пример #11
0
def validate_response(response):
    """
    Parses the returned JSON object, verifies that it follows
    the JSON-RPC spec, and checks for errors, raising exceptions
    as necessary.
    """
    jsonrpc = 'jsonrpc' in response
    response_id = 'id' in response
    result = 'result' in response
    error = 'error' in response and response.get('error') != None

    if not response_id or (not result and not error):
        raise Exception('Server returned invalid response.')
    if error:
        raise ProtocolError(response['error']['code'],
                            response['error']['message'])