예제 #1
0
    def parse_response(self, byte_stream, response_class):
        '''Parses a Hadoop RPC response.

        The RpcResponseHeaderProto contains a status field that marks SUCCESS or ERROR.
        The Hadoop RPC protocol looks like the diagram below for receiving SUCCESS requests.
        +-----------------------------------------------------------+
        |  Length of the RPC resonse (4 bytes/32 bit int)           |
        +-----------------------------------------------------------+
        |  Delimited serialized RpcResponseHeaderProto              |
        +-----------------------------------------------------------+
        |  Serialized delimited RPC response                        |
        +-----------------------------------------------------------+

        In case of an error, the header status is set to ERROR and the error fields are set.
        '''

        log.debug("############## PARSING ##############")
        log.debug("Payload class: %s" % response_class)

        # Read first 4 bytes to get the total length
        len_bytes = byte_stream.read(4)
        total_length = struct.unpack("!I", len_bytes)[0]
        log.debug("Total response length: %s" % total_length)

        header = RpcResponseHeaderProto()
        (header_len, header_bytes) = get_delimited_message_bytes(byte_stream)

        log.debug("Header read %d" % header_len)
        header.ParseFromString(header_bytes)
        log_protobuf_message("RpcResponseHeaderProto", header)

        if header.status == 0:
            log.debug("header: %s, total: %s" % (header_len, total_length))
            if header_len >= total_length:
                return
            response = response_class()
            response_bytes = get_delimited_message_bytes(
                byte_stream, total_length - header_len)[1]
            if len(response_bytes) > 0:
                response.ParseFromString(response_bytes)
                if log.getEffectiveLevel() == logging.DEBUG:
                    log_protobuf_message("Response", response)
                return response
        else:
            self.handle_error(header)
예제 #2
0
    def unwrap_response(self, response_bytes, response_class):
        '''Parse a Hadoop RPC response from a byte array.

        This is useful when SASL QOP is requested and the Hadoop RPC
        response is wrapped/encrypted in a SASL RPC message.
        '''

        # Read the first 4 bytes to get the total length
        len_bytes = response_bytes[:4]
        total_length = struct.unpack("!I", len_bytes)[0]
        log.debug("Total response length: %s" % total_length)
        # Read the next 4 bytes to get the length of
        # the RPC Response header.
        # Caveat: the value can take up to 4 bytes, but usually
        # it may be less.
        (header_length, pos) = decoder._DecodeVarint32(response_bytes[4:8], 0)
        log.debug("Delimited message length (pos %d): %d" %
                  (pos, header_length))
        current = 4 + pos
        header = RpcResponseHeaderProto()
        header.ParseFromString(response_bytes[current:current + header_length])
        log_protobuf_message("RpcResponseHeaderProto", header)
        current += header_length
        # Read the next 4 bytes to get the length of the RPC Response body.
        # Caveat: the value can take up to 4 bytes, but usually
        # it may be less.
        (msg_length,
         pos2) = decoder._DecodeVarint32(response_bytes[current:current + 4],
                                         0)
        log.debug("Delimited message length (pos %d): %d" % (pos2, msg_length))
        response = response_class()
        current += pos2
        response.ParseFromString(response_bytes[current:])
        if log.getEffectiveLevel() == logging.DEBUG:
            log_protobuf_message("Response", response)
        return response