Skip to content

Commit 6c6935c

Browse files
authored
CDRIVER-3929 Include apiVersion in handshake commands (#753)
* Fix tab indentation * CDRIVER-3929 Include apiVersion in handshake commands * Protect pooled clients against later API changes * Fix wrong indentation * Fix wrong re-initialisation of BSON objects * Unconditionally destroy ts->api * Improve handling of server API on pooled clients * Code review fixes
1 parent da0e8a7 commit 6c6935c

10 files changed

+272
-45
lines changed

src/libmongoc/src/mongoc/mongoc-client-pool.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ struct _mongoc_client_pool_t {
5151
int32_t error_api_version;
5252
bool error_api_set;
5353
mongoc_server_api_t *api;
54+
bool client_initialized;
5455
};
5556

5657

@@ -240,6 +241,8 @@ _initialize_new_client (mongoc_client_pool_t *pool, mongoc_client_t *client)
240241
pool->topology->scanner->initiator,
241242
pool->topology->scanner->initiator_context);
242243

244+
pool->client_initialized = true;
245+
client->is_pooled = true;
243246
client->error_api_version = pool->error_api_version;
244247
_mongoc_client_set_apm_callbacks_private (
245248
client, &pool->apm_callbacks, pool->apm_context);
@@ -528,6 +531,15 @@ mongoc_client_pool_set_server_api (mongoc_client_pool_t *pool,
528531
return false;
529532
}
530533

534+
if (pool->client_initialized) {
535+
bson_set_error (error,
536+
MONGOC_ERROR_POOL,
537+
MONGOC_ERROR_POOL_API_TOO_LATE,
538+
"Cannot set server api after a client has been created");
539+
return false;
540+
}
541+
531542
pool->api = mongoc_server_api_copy (api);
543+
_mongoc_topology_scanner_set_server_api (pool->topology->scanner, api);
532544
return true;
533545
}

src/libmongoc/src/mongoc/mongoc-client-private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ struct _mongoc_client_t {
9999
mongoc_uri_t *uri;
100100
mongoc_cluster_t cluster;
101101
bool in_exhaust;
102+
bool is_pooled;
102103

103104
mongoc_stream_initiator_t initiator;
104105
void *initiator_data;

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3105,6 +3105,14 @@ mongoc_client_set_server_api (mongoc_client_t *client,
31053105
BSON_ASSERT_PARAM (client);
31063106
BSON_ASSERT_PARAM (api);
31073107

3108+
if (client->is_pooled) {
3109+
bson_set_error (error,
3110+
MONGOC_ERROR_CLIENT,
3111+
MONGOC_ERROR_CLIENT_API_FROM_POOL,
3112+
"Cannot set server api on a client checked out from a pool");
3113+
return false;
3114+
}
3115+
31083116
if (client->api) {
31093117
bson_set_error (error,
31103118
MONGOC_ERROR_CLIENT,
@@ -3114,5 +3122,6 @@ mongoc_client_set_server_api (mongoc_client_t *client,
31143122
}
31153123

31163124
client->api = mongoc_server_api_copy (api);
3125+
_mongoc_topology_scanner_set_server_api (client->topology->scanner, api);
31173126
return true;
31183127
}

src/libmongoc/src/mongoc/mongoc-cmd-private.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ _is_retryable_read (const mongoc_cmd_parts_t *parts,
146146
void
147147
_mongoc_cmd_append_payload_as_array (const mongoc_cmd_t *cmd, bson_t *out);
148148

149+
void
150+
_mongoc_cmd_append_server_api (bson_t *command_body,
151+
const mongoc_server_api_t *api);
152+
149153
BSON_END_DECLS
150154

151155

src/libmongoc/src/mongoc/mongoc-cmd.c

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -796,8 +796,8 @@ _txn_in_progress (mongoc_cmd_parts_t *parts)
796796
}
797797

798798
return (_mongoc_client_session_txn_in_progress (cs)
799-
/* commitTransaction and abortTransaction count as in progress, too. */
800-
|| parts->assembled.is_txn_finish);
799+
/* commitTransaction and abortTransaction count as in progress, too. */
800+
|| parts->assembled.is_txn_finish);
801801
}
802802

803803

@@ -827,14 +827,12 @@ mongoc_cmd_parts_assemble (mongoc_cmd_parts_t *parts,
827827
bson_error_t *error)
828828
{
829829
mongoc_server_description_type_t server_type;
830-
mongoc_server_api_t *api;
831830
mongoc_client_session_t *cs;
832831
const bson_t *cluster_time = NULL;
833832
mongoc_read_prefs_t *prefs = NULL;
834833
const char *cmd_name;
835834
bool is_get_more;
836835
const mongoc_read_prefs_t *prefs_ptr;
837-
const char *string_version;
838836
bool ret = false;
839837

840838
ENTRY;
@@ -994,23 +992,8 @@ mongoc_cmd_parts_assemble (mongoc_cmd_parts_t *parts,
994992
sending a getmore, or if we are in a transaction. */
995993
if (parts->client->api) {
996994
if (!is_get_more && !_txn_in_progress (parts)) {
997-
api = parts->client->api;
998-
string_version = mongoc_server_api_version_to_string (api->version);
999-
1000-
bson_append_utf8 (
1001-
&parts->assembled_body, "apiVersion", -1, string_version, -1);
1002-
1003-
if (api->strict.is_set) {
1004-
bson_append_bool (
1005-
&parts->assembled_body, "apiStrict", -1, api->strict.value);
1006-
}
1007-
1008-
if (api->deprecation_errors.is_set) {
1009-
bson_append_bool (&parts->assembled_body,
1010-
"apiDeprecationErrors",
1011-
-1,
1012-
api->deprecation_errors.value);
1013-
}
995+
_mongoc_cmd_append_server_api (&parts->assembled_body,
996+
parts->client->api);
1014997
}
1015998
}
1016999

@@ -1155,3 +1138,43 @@ _mongoc_cmd_append_payload_as_array (const mongoc_cmd_t *cmd, bson_t *out)
11551138

11561139
bson_append_array_end (out, &bson);
11571140
}
1141+
1142+
/*--------------------------------------------------------------------------
1143+
*
1144+
* _mongoc_cmd_append_server_api --
1145+
* Append versioned API fields to a mongoc_cmd_t
1146+
*
1147+
* Arguments:
1148+
* cmd The mongoc_cmd_t, which will have versioned API fields added
1149+
* api A mongoc_server_api_t holding server API information
1150+
*
1151+
* Pre-conditions:
1152+
* - @api is initialized.
1153+
* - @command_body is initialised
1154+
*
1155+
*--------------------------------------------------------------------------
1156+
*/
1157+
void
1158+
_mongoc_cmd_append_server_api (bson_t *command_body,
1159+
const mongoc_server_api_t *api)
1160+
{
1161+
const char *string_version;
1162+
1163+
BSON_ASSERT (command_body);
1164+
BSON_ASSERT (api);
1165+
1166+
string_version = mongoc_server_api_version_to_string (api->version);
1167+
1168+
bson_append_utf8 (command_body, "apiVersion", -1, string_version, -1);
1169+
1170+
if (api->strict.is_set) {
1171+
bson_append_bool (command_body, "apiStrict", -1, api->strict.value);
1172+
}
1173+
1174+
if (api->deprecation_errors.is_set) {
1175+
bson_append_bool (command_body,
1176+
"apiDeprecationErrors",
1177+
-1,
1178+
api->deprecation_errors.value);
1179+
}
1180+
}

src/libmongoc/src/mongoc/mongoc-error.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,9 @@ typedef enum {
130130

131131
/* An error related to server version api */
132132
MONGOC_ERROR_CLIENT_API_ALREADY_SET,
133-
MONGOC_ERROR_POOL_API_ALREADY_SET
133+
MONGOC_ERROR_CLIENT_API_FROM_POOL,
134+
MONGOC_ERROR_POOL_API_ALREADY_SET,
135+
MONGOC_ERROR_POOL_API_TOO_LATE
134136
} mongoc_error_code_t;
135137

136138
MONGOC_EXPORT (bool)

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ typedef struct mongoc_topology_scanner {
109109
bool negotiate_sasl_supported_mechs;
110110
bool bypass_cooldown;
111111
bool speculative_authentication;
112+
113+
mongoc_server_api_t *api;
112114
} mongoc_topology_scanner_t;
113115

114116
mongoc_topology_scanner_t *
@@ -223,6 +225,10 @@ bool
223225
mongoc_topology_scanner_node_in_cooldown (mongoc_topology_scanner_node_t *node,
224226
int64_t when);
225227

228+
void
229+
_mongoc_topology_scanner_set_server_api (mongoc_topology_scanner_t *ts,
230+
const mongoc_server_api_t *api);
231+
226232
/* for testing. */
227233
mongoc_stream_t *
228234
_mongoc_topology_scanner_tcp_initiate (mongoc_async_cmd_t *acmd);

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

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,32 @@ _jumpstart_other_acmds (mongoc_topology_scanner_node_t *node,
104104
mongoc_async_cmd_t *acmd);
105105

106106
static void
107-
_add_ismaster (bson_t *cmd)
107+
_add_ismaster (bson_t *cmd, const mongoc_server_api_t *api)
108108
{
109109
BSON_APPEND_INT32 (cmd, "isMaster", 1);
110+
111+
if (api) {
112+
_mongoc_cmd_append_server_api (cmd, api);
113+
}
114+
}
115+
116+
static void
117+
_init_ismaster (mongoc_topology_scanner_t *ts)
118+
{
119+
bson_init (&ts->ismaster_cmd);
120+
bson_init (&ts->ismaster_cmd_with_handshake);
121+
bson_init (&ts->cluster_time);
122+
123+
_add_ismaster (&ts->ismaster_cmd, ts->api);
124+
}
125+
126+
static void
127+
_reset_ismaster (mongoc_topology_scanner_t *ts)
128+
{
129+
bson_reinit (&ts->ismaster_cmd);
130+
bson_reinit (&ts->ismaster_cmd_with_handshake);
131+
132+
_add_ismaster (&ts->ismaster_cmd, ts->api);
110133
}
111134

112135
const char *
@@ -226,7 +249,7 @@ _build_ismaster_with_handshake (mongoc_topology_scanner_t *ts)
226249
int count = 0;
227250
char buf[16];
228251

229-
_add_ismaster (doc);
252+
_add_ismaster (doc, ts->api);
230253

231254
BSON_APPEND_DOCUMENT_BEGIN (doc, HANDSHAKE_FIELD, &subdoc);
232255
res = _mongoc_handshake_build_doc_with_application (&subdoc, ts->appname);
@@ -346,21 +369,19 @@ mongoc_topology_scanner_new (
346369

347370
ts->async = mongoc_async_new ();
348371

349-
bson_init (&ts->ismaster_cmd);
350-
_add_ismaster (&ts->ismaster_cmd);
351-
bson_init (&ts->ismaster_cmd_with_handshake);
352-
bson_init (&ts->cluster_time);
353-
354372
ts->setup_err_cb = setup_err_cb;
355373
ts->cb = cb;
356374
ts->cb_data = data;
357375
ts->uri = uri;
358376
ts->appname = NULL;
377+
ts->api = NULL;
359378
ts->handshake_ok_to_send = false;
360379
ts->connect_timeout_msec = connect_timeout_msec;
361380
/* may be overridden for testing. */
362381
ts->dns_cache_timeout_ms = DNS_CACHE_TIMEOUT_MS;
363382

383+
_init_ismaster (ts);
384+
364385
return ts;
365386
}
366387

@@ -398,6 +419,7 @@ mongoc_topology_scanner_destroy (mongoc_topology_scanner_t *ts)
398419
bson_destroy (&ts->ismaster_cmd);
399420
bson_destroy (&ts->ismaster_cmd_with_handshake);
400421
bson_destroy (&ts->cluster_time);
422+
mongoc_server_api_destroy (ts->api);
401423

402424
/* This field can be set by a mongoc_client */
403425
bson_free ((char *) ts->appname);
@@ -1324,3 +1346,15 @@ _jumpstart_other_acmds (mongoc_topology_scanner_node_t *node,
13241346
}
13251347
}
13261348
}
1349+
1350+
void
1351+
_mongoc_topology_scanner_set_server_api (mongoc_topology_scanner_t *ts,
1352+
const mongoc_server_api_t *api)
1353+
{
1354+
BSON_ASSERT (ts);
1355+
BSON_ASSERT (api);
1356+
1357+
mongoc_server_api_destroy (ts->api);
1358+
ts->api = mongoc_server_api_copy (api);
1359+
_reset_ismaster (ts);
1360+
}

0 commit comments

Comments
 (0)