Skip to content

Commit b42543c

Browse files
authored
CDRIVER-4207 handshake on new stream in scanner (#915)
1 parent 296ff38 commit b42543c

File tree

3 files changed

+95
-7
lines changed

3 files changed

+95
-7
lines changed

src/libmongoc/src/mongoc/mongoc-topology-scanner-private.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ typedef struct mongoc_topology_scanner_node {
5454
mongoc_stream_t *stream;
5555

5656
int64_t last_used;
57+
/* last_failed is set upon a network error trying to check a server.
58+
* last_failed is used to enforce cooldownMS.
59+
* last_failed is not set upon a network error during an application operation on @stream. */
5760
int64_t last_failed;
5861
bool has_auth;
5962
bool hello_ok;

src/libmongoc/src/mongoc/mongoc-topology-scanner.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -374,12 +374,13 @@ _begin_hello_cmd (mongoc_topology_scanner_node_t *node,
374374
mongoc_stream_t *stream,
375375
bool is_setup_done,
376376
struct addrinfo *dns_result,
377-
int64_t initiate_delay_ms)
377+
int64_t initiate_delay_ms,
378+
bool use_handshake)
378379
{
379380
mongoc_topology_scanner_t *ts = node->ts;
380381
bson_t cmd;
381382

382-
if (node->last_used != -1 && node->last_failed == -1) {
383+
if (node->last_used != -1 && node->last_failed == -1 && !use_handshake) {
383384
/* The node's been used before and not failed recently */
384385
bson_copy_to (
385386
_mongoc_topology_scanner_get_monitoring_cmd (ts, node->hello_ok),
@@ -946,11 +947,21 @@ mongoc_topology_scanner_node_setup_tcp (mongoc_topology_scanner_node_t *node,
946947
}
947948

948949
if (node->successful_dns_result) {
949-
_begin_hello_cmd (node, NULL, false, node->successful_dns_result, 0);
950+
_begin_hello_cmd (node,
951+
NULL /* stream */,
952+
false /* is_setup_done */,
953+
node->successful_dns_result,
954+
0 /* initiate_delay_ms */,
955+
true /* use_handshake */);
950956
} else {
951957
LL_FOREACH2 (node->dns_results, iter, ai_next)
952958
{
953-
_begin_hello_cmd (node, NULL, false, iter, delay);
959+
_begin_hello_cmd (node,
960+
NULL /* stream */,
961+
false /* is_setup_done */,
962+
iter,
963+
delay,
964+
true /* use_handshake */);
954965
/* each subsequent DNS result will have an additional 250ms delay. */
955966
delay += HAPPY_EYEBALLS_DELAY_MS;
956967
}
@@ -1017,7 +1028,8 @@ mongoc_topology_scanner_node_connect_unix (mongoc_topology_scanner_node_t *node,
10171028
stream,
10181029
false /* is_setup_done */,
10191030
NULL /* dns result */,
1020-
0 /* delay */);
1031+
0 /* delay */,
1032+
true /* use_handshake */);
10211033
RETURN (true);
10221034
}
10231035
bson_set_error (error,
@@ -1055,7 +1067,12 @@ mongoc_topology_scanner_node_setup (mongoc_topology_scanner_node_t *node,
10551067

10561068
/* if there is already a working stream, push it back to be re-scanned. */
10571069
if (node->stream) {
1058-
_begin_hello_cmd (node, node->stream, true /* is_setup_done */, NULL, 0);
1070+
_begin_hello_cmd (node,
1071+
node->stream,
1072+
true /* is_setup_done */,
1073+
NULL /* dns_result */,
1074+
0 /* initiate_delay_ms */,
1075+
false /* use_handshake */);
10591076
node->stream = NULL;
10601077
return;
10611078
}
@@ -1067,7 +1084,12 @@ mongoc_topology_scanner_node_setup (mongoc_topology_scanner_node_t *node,
10671084
node->ts->uri, &node->host, node->ts->initiator_context, error);
10681085
if (stream) {
10691086
success = true;
1070-
_begin_hello_cmd (node, stream, false, NULL, 0);
1087+
_begin_hello_cmd (node,
1088+
stream,
1089+
false /* is_setup_done */,
1090+
NULL /* dns_result */,
1091+
0 /* initiate_delay_ms */,
1092+
true /* use_handshake */);
10711093
}
10721094
} else {
10731095
if (node->host.family == AF_UNIX) {

src/libmongoc/tests/test-mongoc-client.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4145,6 +4145,65 @@ test_mongoc_client_get_handshake_establishes_connection_pooled (void)
41454145
mongoc_client_pool_destroy (pool);
41464146
}
41474147

4148+
/* Regression test for CDRIVER-4207. */
4149+
void
4150+
test_mongoc_client_resends_handshake_on_network_error (void)
4151+
{
4152+
mongoc_client_t *client;
4153+
mock_server_t *server;
4154+
future_t *future;
4155+
request_t *request;
4156+
bson_error_t error;
4157+
bson_t *ping = tmp_bson ("{'ping': 1}");
4158+
4159+
server = mock_server_new ();
4160+
mock_server_run (server);
4161+
client = mongoc_client_new_from_uri (mock_server_get_uri (server));
4162+
mongoc_client_set_appname (client, "foo");
4163+
4164+
/* Send a "ping" command. */
4165+
future = future_client_command_simple (
4166+
client, "db", ping, NULL /* read_prefs */, NULL /* reply */, &error);
4167+
/* The first command on the new connection is handshake. It uses the legacy
4168+
* hello and includes the client.application.name. */
4169+
request = mock_server_receives_legacy_hello (
4170+
server,
4171+
"{'" HANDSHAKE_CMD_LEGACY_HELLO
4172+
"': 1, 'client': {'application': {'name': 'foo'}}}");
4173+
mock_server_replies_simple (request, "{'ok': 1, 'maxWireVersion': 14 }");
4174+
request_destroy (request);
4175+
request = mock_server_receives_msg (
4176+
server, MONGOC_QUERY_NONE, tmp_bson ("{'ping': 1}"));
4177+
mock_server_hangs_up (request);
4178+
future_wait (future);
4179+
future_destroy (future);
4180+
ASSERT_ERROR_CONTAINS (error,
4181+
MONGOC_ERROR_STREAM,
4182+
MONGOC_ERROR_STREAM_SOCKET,
4183+
"socket error or timeout");
4184+
request_destroy (request);
4185+
4186+
/* Send another "ping" command. */
4187+
future = future_client_command_simple (
4188+
client, "db", ping, NULL /* read_prefs */, NULL /* reply */, &error);
4189+
/* Expect the new connection to send the full handshake. */
4190+
request = mock_server_receives_legacy_hello (
4191+
server,
4192+
"{'" HANDSHAKE_CMD_LEGACY_HELLO
4193+
"': 1, 'client': {'application': {'name': 'foo'}}}");
4194+
mock_server_replies_simple (request, "{'ok': 1, 'maxWireVersion': 14 }");
4195+
request_destroy (request);
4196+
4197+
request = mock_server_receives_msg (
4198+
server, MONGOC_QUERY_NONE, tmp_bson ("{'ping': 1}"));
4199+
mock_server_replies_ok_and_destroys (request);
4200+
ASSERT (future_get_bool (future));
4201+
future_destroy (future);
4202+
4203+
mongoc_client_destroy (client);
4204+
mock_server_destroy (server);
4205+
}
4206+
41484207
void
41494208
test_client_install (TestSuite *suite)
41504209
{
@@ -4452,4 +4511,8 @@ test_client_install (TestSuite *suite)
44524511
suite,
44534512
"/Client/get_handshake_establishes_connection/pooled",
44544513
test_mongoc_client_get_handshake_establishes_connection_pooled);
4514+
TestSuite_AddMockServerTest (
4515+
suite,
4516+
"/Client/resends_handshake_on_network_error",
4517+
test_mongoc_client_resends_handshake_on_network_error);
44554518
}

0 commit comments

Comments
 (0)