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)
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