diff options
Diffstat (limited to 'src')
4 files changed, 52 insertions, 1 deletions
diff --git a/src/mongo/executor/network_interface_asio.h b/src/mongo/executor/network_interface_asio.h index fd8c61d15d7..d291619bd55 100644 --- a/src/mongo/executor/network_interface_asio.h +++ b/src/mongo/executor/network_interface_asio.h @@ -94,6 +94,7 @@ private: rpc::ProtocolSet serverProtocols() const; rpc::ProtocolSet clientProtocols() const; + void setServerProtocols(rpc::ProtocolSet protocols); // Explicit move construction and assignment to support MSVC #if defined(_MSC_VER) && _MSC_VER < 1900 @@ -254,6 +255,7 @@ private: void _connectASIO(AsyncOp* op); void _connectWithDBClientConnection(AsyncOp* op); void _setupSocket(AsyncOp* op, const asio::ip::tcp::resolver::iterator& endpoints); + void _runIsMaster(AsyncOp* op); void _authenticate(AsyncOp* op); void _sslHandshake(AsyncOp* op); diff --git a/src/mongo/executor/network_interface_asio_auth.cpp b/src/mongo/executor/network_interface_asio_auth.cpp index 7bbc87b0e0a..176d435fa6b 100644 --- a/src/mongo/executor/network_interface_asio_auth.cpp +++ b/src/mongo/executor/network_interface_asio_auth.cpp @@ -32,9 +32,52 @@ #include "mongo/executor/network_interface_asio.h" +#include "mongo/rpc/factory.h" +#include "mongo/rpc/legacy_request_builder.h" + namespace mongo { namespace executor { +void NetworkInterfaceASIO::_runIsMaster(AsyncOp* op) { + // We use a legacy builder to create our ismaster request because we may + // have to communicate with servers that do not support OP_COMMAND + rpc::LegacyRequestBuilder requestBuilder{}; + requestBuilder.setDatabase("admin"); + requestBuilder.setCommandName("ismaster"); + requestBuilder.setMetadata(rpc::makeEmptyMetadata()); + requestBuilder.setCommandArgs(BSON("ismaster" << 1)); + + // Set current command to ismaster request and run + auto& cmd = op->beginCommand(std::move(*(requestBuilder.done()))); + cmd.toSend().header().setResponseTo(0); + + // Callback to parse protocol information out of received ismaster response + auto parseIsMaster = [this, op]() { + try { + auto commandReply = rpc::makeReply(&(op->command().toRecv())); + BSONObj isMasterReply = commandReply->getCommandReply(); + + auto protocolSet = rpc::parseProtocolSetFromIsMasterReply(isMasterReply); + if (!protocolSet.isOK()) + return _completeOperation(op, protocolSet.getStatus()); + + op->connection()->setServerProtocols(protocolSet.getValue()); + + // Advance the state machine + _authenticate(op); + + } catch (...) { + // makeReply will throw if the rely was invalid. + _completeOperation(op, exceptionToStatus()); + } + }; + + _asyncRunCommand(&cmd, + [this, op, parseIsMaster](std::error_code ec, size_t bytes) { + _validateAndRun(op, ec, std::move(parseIsMaster)); + }); +} + void NetworkInterfaceASIO::_authenticate(AsyncOp* op) { // TODO: Implement asynchronous authentication, SERVER-19155 asio::post(_io_service, [this, op]() { _beginCommunication(op); }); diff --git a/src/mongo/executor/network_interface_asio_connect.cpp b/src/mongo/executor/network_interface_asio_connect.cpp index 9819497e24f..f50840bf3da 100644 --- a/src/mongo/executor/network_interface_asio_connect.cpp +++ b/src/mongo/executor/network_interface_asio_connect.cpp @@ -81,6 +81,10 @@ rpc::ProtocolSet NetworkInterfaceASIO::AsyncConnection::clientProtocols() const return _clientProtocols; } +void NetworkInterfaceASIO::AsyncConnection::setServerProtocols(rpc::ProtocolSet protocols) { + _serverProtocols = protocols; +} + void NetworkInterfaceASIO::_connectASIO(AsyncOp* op) { tcp::resolver::query query(op->request().target.host(), std::to_string(op->request().target.port())); diff --git a/src/mongo/executor/network_interface_asio_ssl.cpp b/src/mongo/executor/network_interface_asio_ssl.cpp index c44f772dacb..d61cb6ce156 100644 --- a/src/mongo/executor/network_interface_asio_ssl.cpp +++ b/src/mongo/executor/network_interface_asio_ssl.cpp @@ -37,7 +37,9 @@ namespace executor { void NetworkInterfaceASIO::_sslHandshake(AsyncOp* op) { // TODO: Implement asynchronous SSL, SERVER-19221 - _authenticate(op); + + // Advance the state machine + _runIsMaster(op); } } // namespace executor |