void NetworkInterfaceASIO::_beginCommunication(AsyncOp* op) {
    // The way that we connect connections for the connection pool is by
    // starting the callback chain with connect(), but getting off at the first
    // _beginCommunication. I.e. all AsyncOp's start off with _inSetup == true
    // and arrive here as they're connected and authed. Once they hit here, we
    // return to the connection pool's get() callback with _inSetup == false,
    // so we can proceed with user operations after they return to this
    // codepath.
    if (op->_inSetup) {
        log() << "Successfully connected to " << op->request().target.toString();
        op->_inSetup = false;
        op->finish(RemoteCommandResponse());
        return;
    }

    LOG(3) << "Initiating asynchronous command: " << redact(op->request().toString());

    auto beginStatus = op->beginCommand(op->request());
    if (!beginStatus.isOK()) {
        return _completeOperation(op, beginStatus);
    }

    _asyncRunCommand(op, [this, op](std::error_code ec, size_t bytes) {
        _validateAndRun(op, ec, [this, op]() { _completedOpCallback(op); });
    });
}
void NetworkInterfaceASIO::_beginCommunication(AsyncOp* op) {
    auto& cmd = op->beginCommand(op->request(), op->operationProtocol());

    _asyncRunCommand(&cmd,
                     [this, op](std::error_code ec, size_t bytes) {
                         _validateAndRun(op, ec, [this, op]() { _completedOpCallback(op); });
                     });
}
void NetworkInterfaceASIO::_beginCommunication(AsyncOp* op) {
    auto negotiatedProtocol =
        rpc::negotiate(op->connection().serverProtocols(), op->connection().clientProtocols());

    if (!negotiatedProtocol.isOK()) {
        return _completeOperation(op, negotiatedProtocol.getStatus());
    }

    op->setOperationProtocol(negotiatedProtocol.getValue());

    auto& cmd = op->beginCommand(
        std::move(*_messageFromRequest(op->request(), negotiatedProtocol.getValue())));

    _asyncRunCommand(&cmd,
                     [this, op](std::error_code ec, size_t bytes) {
                         _validateAndRun(op, ec, [this, op]() { _completedOpCallback(op); });
                     });
}