'Send a message to MongoDB and return a Response object.
Can raise ConnectionFailure.
:Parameters:
- `operation`: A _Query or _GetMore object.
- `set_slave_okay`: Pass to operation.get_message.
- `all_credentials`: dict, maps auth source to MongoCredential.
- `listeners`: Instance of _EventListeners or None.
- `exhaust` (optional): If True, the socket used stays checked out.
It is returned along with its Pool in the Response.'

def send_message_with_response(self, operation, set_slave_okay, all_credentials, listeners, exhaust=False):

    with self.get_socket(all_credentials, exhaust) as sock_info:
        duration = None
        publish = listeners.enabled_for_commands
        if publish:
            start = datetime.now()
        use_find_cmd = False
        if (sock_info.max_wire_version >= 4):
            if (not exhaust):
                use_find_cmd = True
        elif (isinstance(operation, _Query) and (not operation.read_concern.ok_for_legacy)):
            raise ConfigurationError(('read    concern    level    of    %s    is    not    valid    with    a    max    wire    version    of    %d.' % (operation.read_concern.level, sock_info.max_wire_version)))
        if (isinstance(operation, _Query) and (sock_info.max_wire_version < 5) and (operation.collation is not None)):
            raise ConfigurationError(('Specifying    a    collation    is    unsupported    with    a    max    wire    version    of    %d.' % (sock_info.max_wire_version,)))
        message = operation.get_message(set_slave_okay, sock_info.is_mongos, use_find_cmd)
        (request_id, data, max_doc_size) = self._split_message(message)
        if publish:
            encoding_duration = (datetime.now() - start)
            (cmd, dbn) = operation.as_command()
            listeners.publish_command_start(cmd, dbn, request_id, sock_info.address)
            start = datetime.now()
        try:
            sock_info.send_message(data, max_doc_size)
            response_data = sock_info.receive_message(1, request_id)
        except Exception as exc:
            if publish:
                duration = ((datetime.now() - start) + encoding_duration)
                failure = _convert_exception(exc)
                listeners.publish_command_failure(duration, failure, next(iter(cmd)), request_id, sock_info.address)
            raise
        if publish:
            duration = ((datetime.now() - start) + encoding_duration)
        if exhaust:
            return ExhaustResponse(data=response_data, address=self._description.address, socket_info=sock_info, pool=self._pool, duration=duration, request_id=request_id, from_command=use_find_cmd)
        else:
            return Response(data=response_data, address=self._description.address, duration=duration, request_id=request_id, from_command=use_find_cmd)
