'Called by a server to deserialize a request, compute and serialize
a response or error. Compare to \'handle()\' in Thrift.'

def respond(self, call_request):

    buffer_reader = StringIO(call_request)
    buffer_decoder = io.BinaryDecoder(buffer_reader)
    buffer_writer = StringIO()
    buffer_encoder = io.BinaryEncoder(buffer_writer)
    error = None
    response_metadata = {}
    try:
        remote_protocol = self.process_handshake(buffer_decoder, buffer_encoder)
        if (remote_protocol is None):
            return buffer_writer.getvalue()
        request_metadata = META_READER.read(buffer_decoder)
        remote_message_name = buffer_decoder.read_utf8()
        remote_message = remote_protocol.messages.get(remote_message_name)
        if (remote_message is None):
            fail_msg = ('Unknown    remote    message:    %s' % remote_message_name)
            raise schema.AvroException(fail_msg)
        local_message = self.local_protocol.messages.get(remote_message_name)
        if (local_message is None):
            fail_msg = ('Unknown    local    message:    %s' % remote_message_name)
            raise schema.AvroException(fail_msg)
        writers_schema = remote_message.request
        readers_schema = local_message.request
        request = self.read_request(writers_schema, readers_schema, buffer_decoder)
        try:
            response = self.invoke(local_message, request)
        except AvroRemoteException as e:
            error = e
        except Exception as e:
            error = AvroRemoteException(str(e))
        META_WRITER.write(response_metadata, buffer_encoder)
        buffer_encoder.write_boolean((error is not None))
        if (error is None):
            writers_schema = local_message.response
            self.write_response(writers_schema, response, buffer_encoder)
        else:
            writers_schema = local_message.errors
            self.write_error(writers_schema, error, buffer_encoder)
    except schema.AvroException as e:
        error = AvroRemoteException(str(e))
        buffer_encoder = io.BinaryEncoder(StringIO())
        META_WRITER.write(response_metadata, buffer_encoder)
        buffer_encoder.write_boolean(True)
        self.write_error(SYSTEM_ERROR_SCHEMA, error, buffer_encoder)
    return buffer_writer.getvalue()
