void
mongoc_log_trace_bytes (const char *domain, const uint8_t *_b, size_t _l)
{
   bson_string_t *str, *astr;
   int32_t _i;
   uint8_t _v;

#ifdef MONGOC_TRACE
   if (!gLogTrace) {
      return;
   }
#endif

   str = bson_string_new(NULL);
   astr = bson_string_new(NULL);
   for (_i = 0; _i < _l; _i++) {
      _v = *(_b + _i);

      if ((_i % 16) == 0) {
         bson_string_append_printf(str, "%05x: ", _i);
      }

      bson_string_append_printf(str, " %02x", _v);
      if (isprint(_v)) {
         bson_string_append_printf(astr, " %c", _v);
      } else {
         bson_string_append(astr, " .");
      }

      if ((_i % 16) == 15) {
         mongoc_log(MONGOC_LOG_LEVEL_TRACE, domain,
                    "%s %s", str->str, astr->str);
         bson_string_truncate(str, 0);
         bson_string_truncate(astr, 0);
      } else if ((_i % 16) == 7) {
         bson_string_append(str, " ");
         bson_string_append(astr, " ");
      }
   }

   if (_i != 16) {
      mongoc_log(MONGOC_LOG_LEVEL_TRACE, domain,
                 "%-56s %s", str->str, astr->str);
   }

   bson_string_free(str, true);
   bson_string_free(astr, true);
}
Example #2
0
mongoc_client_t *
ha_sharded_cluster_get_client (ha_sharded_cluster_t *cluster)
{
   const ha_node_t *iter;
   mongoc_client_t *client;
   bson_string_t *str;

   BSON_ASSERT (cluster);
   BSON_ASSERT (cluster->routers);

   str = bson_string_new ("mongodb://");

   for (iter = cluster->routers; iter; iter = iter->next) {
      bson_string_append_printf (str, "127.0.0.1:%hu%s",
                                 iter->port,
                                 iter->next ? "," : "");
   }

   bson_string_append (str, "/");

   client = mongoc_client_new (str->str);

   bson_string_free (str, TRUE);

   return client;
}
Example #3
0
/*
 * If error is not set, set code from first document in array like
 * [{"code": 64, "errmsg": "duplicate"}, ...]. Format the error message
 * from all errors in array.
 */
static void
_set_error_from_response (bson_t *bson_array,
                          mongoc_error_domain_t domain,
                          const char *error_type,
                          bson_error_t *error /* OUT */)
{
   bson_iter_t array_iter;
   bson_iter_t doc_iter;
   bson_string_t *compound_err;
   const char *errmsg = NULL;
   int32_t code = 0;
   uint32_t n_keys, i;

   compound_err = bson_string_new (NULL);
   n_keys = bson_count_keys (bson_array);
   if (n_keys > 1) {
      bson_string_append_printf (
         compound_err, "Multiple %s errors: ", error_type);
   }

   if (!bson_empty0 (bson_array) && bson_iter_init (&array_iter, bson_array)) {
      /* get first code and all error messages */
      i = 0;

      while (bson_iter_next (&array_iter)) {
         if (BSON_ITER_HOLDS_DOCUMENT (&array_iter) &&
             bson_iter_recurse (&array_iter, &doc_iter)) {
            /* parse doc, which is like {"code": 64, "errmsg": "duplicate"} */
            while (bson_iter_next (&doc_iter)) {
               /* use the first error code we find */
               if (BSON_ITER_IS_KEY (&doc_iter, "code") && code == 0) {
                  code = bson_iter_int32 (&doc_iter);
               } else if (BSON_ITER_IS_KEY (&doc_iter, "errmsg")) {
                  errmsg = bson_iter_utf8 (&doc_iter, NULL);

                  /* build message like 'Multiple write errors: "foo", "bar"' */
                  if (n_keys > 1) {
                     bson_string_append_printf (compound_err, "\"%s\"", errmsg);
                     if (i < n_keys - 1) {
                        bson_string_append (compound_err, ", ");
                     }
                  } else {
                     /* single error message */
                     bson_string_append (compound_err, errmsg);
                  }
               }
            }

            i++;
         }
      }

      if (code && compound_err->len) {
         bson_set_error (
            error, domain, (uint32_t) code, "%s", compound_err->str);
      }
   }

   bson_string_free (compound_err, true);
}
Example #4
0
static bool
_mongoc_cyrus_is_failure (int status, bson_error_t *error)
{
   bool ret = (status < 0);

   TRACE ("Got status: %d ok is %d, continue=%d interact=%d\n",
          status,
          SASL_OK,
          SASL_CONTINUE,
          SASL_INTERACT);
   if (ret) {
      switch (status) {
      case SASL_NOMEM:
         bson_set_error (error,
                         MONGOC_ERROR_SASL,
                         status,
                         "SASL Failure: insufficient memory.");
         break;
      case SASL_NOMECH: {
         bson_string_t *str = bson_string_new ("available mechanisms: ");
         const char **mechs = sasl_global_listmech ();
         int i = 0;

         for (i = 0; mechs[i]; i++) {
            bson_string_append (str, mechs[i]);
            if (mechs[i + 1]) {
               bson_string_append (str, ",");
            }
         }
         bson_set_error (error,
                         MONGOC_ERROR_SASL,
                         status,
                         "SASL Failure: failure to negotiate mechanism (%s)",
                         str->str);
         bson_string_free (str, 0);
      } break;
      case SASL_BADPARAM:
         bson_set_error (error,
                         MONGOC_ERROR_SASL,
                         status,
                         "Bad parameter supplied. Please file a bug "
                         "with mongo-c-driver.");
         break;
      default:
         bson_set_error (error,
                         MONGOC_ERROR_SASL,
                         status,
                         "SASL Failure: (%d): %s",
                         status,
                         sasl_errstring (status, NULL, NULL));
         break;
      }
   }

   return ret;
}
Example #5
0
char *
mongoc_uri_unescape (const char *escaped_string)
{
   bson_unichar_t c;
   bson_string_t *str;
   unsigned int hex = 0;
   const char *ptr;
   const char *end;
   size_t len;

   BSON_ASSERT (escaped_string);

   len = strlen(escaped_string);

   /*
    * Double check that this is a UTF-8 valid string. Bail out if necessary.
    */
   if (!bson_utf8_validate(escaped_string, len, false)) {
      MONGOC_WARNING("%s(): escaped_string contains invalid UTF-8",
                     BSON_FUNC);
      return NULL;
   }

   ptr = escaped_string;
   end = ptr + len;
   str = bson_string_new(NULL);

   for (; *ptr; ptr = bson_utf8_next_char(ptr)) {
      c = bson_utf8_get_char(ptr);
      switch (c) {
      case '%':
         if (((end - ptr) < 2) ||
             !isxdigit(ptr[1]) ||
             !isxdigit(ptr[2]) ||
#ifdef _MSC_VER
             (1 != sscanf_s(&ptr[1], "%02x", &hex)) ||
#else
             (1 != sscanf(&ptr[1], "%02x", &hex)) ||
#endif
             !isprint(hex)) {
            bson_string_free(str, true);
            return NULL;
         }
         bson_string_append_c(str, hex);
         ptr += 2;
         break;
      default:
         bson_string_append_unichar(str, c);
         break;
      }
   }

   return bson_string_free(str, false);
}
Example #6
0
static void
ha_config_add_shard (ha_node_t        *node,
                     ha_replica_set_t *replica_set)
{
   mongoc_collection_t *collection;
   mongoc_client_t *client;
   bson_string_t *shardstr;
   bson_error_t error;
   bson_bool_t r;
   bson_t reply;
   bson_t cmd = BSON_INITIALIZER;
   char *uristr;

   uristr = bson_strdup_printf ("mongodb://127.0.0.1:%hu/", node->port);
   client = mongoc_client_new (uristr);
   collection = mongoc_client_get_collection (client, "admin", "fake");

   shardstr = bson_string_new (NULL);
   bson_string_append_printf (shardstr, "%s/127.0.0.1:%hu",
                              replica_set->name,
                              replica_set->nodes->port);

   bson_append_utf8 (&cmd, "addShard", -1, shardstr->str, shardstr->len);

   bson_string_free (shardstr, TRUE);

again:
   sleep (1);

   r = mongoc_collection_command_simple (collection, &cmd, NULL, &reply, &error);

   if (!r) {
      fprintf (stderr, "%s\n", error.message);
      goto again;
   }

#if 1
   {
      char *str;

      str = bson_as_json (&reply, NULL);
      printf ("%s\n", str);
      bson_free (str);
   }
#endif

   bson_destroy (&reply);
   bson_destroy (&cmd);
   mongoc_collection_destroy (collection);
   mongoc_client_destroy (client);
   bson_free (uristr);
}
Example #7
0
bool
_mongoc_cyrus_set_mechanism (mongoc_cyrus_t *sasl,
                             const char *mechanism,
                             bson_error_t *error)
{
   bson_string_t *str = bson_string_new ("");
   const char **mechs = sasl_global_listmech ();
   int i = 0;
   bool ok = false;

   BSON_ASSERT (sasl);

   for (i = 0; mechs[i]; i++) {
      if (!strcmp (mechs[i], mechanism)) {
         ok = true;
         break;
      }
      bson_string_append (str, mechs[i]);
      if (mechs[i + 1]) {
         bson_string_append (str, ",");
      }
   }

   if (ok) {
      bson_free (sasl->credentials.mechanism);
      sasl->credentials.mechanism = mechanism ? bson_strdup (mechanism) : NULL;
   } else {
      bson_set_error (error,
                      MONGOC_ERROR_SASL,
                      SASL_NOMECH,
                      "SASL Failure: Unsupported mechanism by client: %s. "
                      "Available mechanisms: %s",
                      mechanism,
                      str->str);
   }

   bson_string_free (str, true);
   return ok;
}
static void
_set_platform_string (mongoc_handshake_t *handshake)
{
   bson_string_t *str;
   char *config_str;

   str = bson_string_new ("");

   config_str = _mongoc_handshake_get_config_hex_string ();
   bson_string_append_printf (str, "cfg=%s", config_str);
   bson_free (config_str);

#ifdef _POSIX_VERSION
   bson_string_append_printf (str, " posix=%ld", _POSIX_VERSION);
#endif

#ifdef __STDC_VERSION__
   bson_string_append_printf (str, " stdc=%ld", __STDC_VERSION__);
#endif

   bson_string_append_printf (str, " CC=%s", MONGOC_COMPILER);

#ifdef MONGOC_COMPILER_VERSION
   bson_string_append_printf (str, " %s", MONGOC_COMPILER_VERSION);
#endif

   if (strlen (MONGOC_EVALUATE_STR (MONGOC_USER_SET_CFLAGS)) > 0) {
      bson_string_append_printf (
         str, " CFLAGS=%s", MONGOC_EVALUATE_STR (MONGOC_USER_SET_CFLAGS));
   }

   if (strlen (MONGOC_EVALUATE_STR (MONGOC_USER_SET_LDFLAGS)) > 0) {
      bson_string_append_printf (
         str, " LDFLAGS=%s", MONGOC_EVALUATE_STR (MONGOC_USER_SET_LDFLAGS));
   }

   handshake->platform = bson_string_free (str, false);
}
Example #9
0
mongoc_client_t *
ha_replica_set_create_client (ha_replica_set_t *replica_set)
{
   mongoc_client_t *client;
   bson_string_t *str;
   ha_node_t *iter;
   char *portstr;

   str = bson_string_new("mongodb://");

   for (iter = replica_set->nodes; iter; iter = iter->next) {
      bson_string_append(str, "127.0.0.1:");

      portstr = bson_strdup_printf("%hu", iter->port);
      bson_string_append(str, portstr);
      bson_free(portstr);

      if (iter->next) {
         bson_string_append(str, ",");
      }
   }

   bson_string_append(str, "/?replicaSet=");
   bson_string_append(str, replica_set->name);

   client = mongoc_client_new(str->str);

#ifdef MONGOC_ENABLE_SSL
   if (replica_set->ssl_opt) {
      mongoc_client_set_ssl_opts(client, replica_set->ssl_opt);
   }
#endif

   bson_string_free(str, TRUE);

   return client;
}
/* a uri with one bogus host */
mongoc_uri_t *
uri_from_ismaster_plus_one (bson_t *ismaster_response)
{
   /* start with one bad host and a comma */
   bson_string_t *uri_str = bson_string_new ("mongodb://" BAD_HOST ",");
   char *name;
   bson_iter_t iter;
   bson_iter_t hosts_iter;

   if ((name = set_name (ismaster_response))) {
      bson_iter_init_find (&iter, ismaster_response, "hosts");
      bson_iter_recurse (&iter, &hosts_iter);
      while (bson_iter_next (&hosts_iter)) {
         assert (BSON_ITER_HOLDS_UTF8 (&hosts_iter));
         bson_string_append (uri_str, bson_iter_utf8 (&hosts_iter, NULL));
         while (bson_iter_next (&hosts_iter)) {
            bson_string_append (uri_str, ",");
            bson_string_append (uri_str, bson_iter_utf8 (&hosts_iter, NULL));
         }

         bson_string_append_printf (
            uri_str, "/?replicaSet=%s&connecttimeoutms=1000", name);
      }

      bson_free (name);
   } else {
      char *host = test_framework_get_host ();

      bson_string_append (uri_str, host);
      bson_string_append (uri_str, "/?connecttimeoutms=1000");

      bson_free (host);
   }

   return mongoc_uri_new (bson_string_free (uri_str, false));
}
Example #11
0
void
mock_server_reply_multi (request_t           *request,
                         mongoc_reply_flags_t flags,
                         const bson_t        *docs,
                         int                  n_docs,
                         int64_t              cursor_id)
{
   const mongoc_rpc_t *request_rpc;
   mock_server_t *server;
   mongoc_stream_t *client;
   char *doc_json;
   bson_string_t *docs_json;
   mongoc_iovec_t *iov;
   mongoc_array_t ar;
   mongoc_rpc_t r = {{ 0 }};
   size_t expected = 0;
   ssize_t n_written;
   int iovcnt;
   int i;
   uint8_t *buf;
   uint8_t *ptr;
   size_t len;

   BSON_ASSERT (request);
   BSON_ASSERT (docs);

   request_rpc = &request->request_rpc;
   server = request->server;
   client = request->client;

   docs_json = bson_string_new ("");
   for (i = 0; i < n_docs; i++) {
      doc_json = bson_as_json (&docs[i], NULL);
      bson_string_append (docs_json, doc_json);
      bson_free (doc_json);
      if (i < n_docs - 1) {
         bson_string_append (docs_json, ", ");
      }
   }

   if (mock_server_get_verbose (request->server)) {
      printf ("%5.2f  %hu <- %hu \t%s\n",
              mock_server_get_uptime_sec (request->server),
              request->client_port,
              mock_server_get_port (request->server),
              docs_json->str);
      fflush (stdout);
   }

   len = 0;

   for (i = 0; i < n_docs; i++) {
      len += docs[i].len;
   }

   ptr = buf = bson_malloc (len);

   for (i = 0; i < n_docs; i++) {
      memcpy (ptr, bson_get_data (&docs[i]), docs[i].len);
      ptr += docs[i].len;
   }

   _mongoc_array_init (&ar, sizeof (mongoc_iovec_t));

   if (!(request->opcode == MONGOC_OPCODE_QUERY &&
         request_rpc->query.flags & MONGOC_QUERY_EXHAUST)) {
      server->last_response_id++;
   }

   mongoc_mutex_lock (&server->mutex);
   r.reply.request_id = server->last_response_id;
   mongoc_mutex_unlock (&server->mutex);
   r.reply.msg_len = 0;
   r.reply.response_to = request_rpc->header.request_id;
   r.reply.opcode = MONGOC_OPCODE_REPLY;
   r.reply.flags = flags;
   r.reply.cursor_id = cursor_id;
   r.reply.start_from = 0;
   r.reply.n_returned = 1;
   r.reply.documents = buf;
   r.reply.documents_len = (uint32_t)len;

   _mongoc_rpc_gather (&r, &ar);
   _mongoc_rpc_swab_to_le (&r);

   iov = (mongoc_iovec_t *)ar.data;
   iovcnt = (int) ar.len;

   for (i = 0; i < iovcnt; i++) {
      expected += iov[i].iov_len;
   }

   n_written = mongoc_stream_writev (client, iov, (size_t) iovcnt, -1);

   assert (n_written == expected);

   bson_string_free (docs_json, true);
   _mongoc_array_destroy (&ar);
   bson_free (buf);
}
/* Uses old way of querying system.namespaces. */
mongoc_cursor_t *
_mongoc_database_find_collections_legacy (mongoc_database_t *database,
                                          const bson_t      *filter,
                                          bson_error_t      *error)
{
   mongoc_collection_t *col;
   mongoc_cursor_t *cursor = NULL;
   mongoc_read_prefs_t *read_prefs;
   uint32_t dbname_len;
   bson_t legacy_filter;
   bson_iter_t iter;
   const char *col_filter;
   bson_t q = BSON_INITIALIZER;
   mongoc_database_find_collections_legacy_ctx_t *ctx;

   BSON_ASSERT (database);

   col = mongoc_client_get_collection (database->client,
                                       database->name,
                                       "system.namespaces");

   BSON_ASSERT (col);

   dbname_len = (uint32_t)strlen (database->name);

   ctx = bson_malloc (sizeof (*ctx));

   ctx->dbname = database->name;
   ctx->dbname_len = dbname_len;

   /* Filtering on name needs to be handled differently for old servers. */
   if (filter && bson_iter_init_find (&iter, filter, "name")) {
      bson_string_t *buf;
      /* on legacy servers, this must be a string (i.e. not a regex) */
      if (!BSON_ITER_HOLDS_UTF8 (&iter)) {
         bson_set_error (error,
                         MONGOC_ERROR_NAMESPACE,
                         MONGOC_ERROR_NAMESPACE_INVALID_FILTER_TYPE,
                         "On legacy servers, a filter on name can only be a string.");
         goto cleanup_filter;
      }
      BSON_ASSERT (BSON_ITER_HOLDS_UTF8 (&iter));
      col_filter = bson_iter_utf8 (&iter, NULL);
      bson_init (&legacy_filter);
      bson_copy_to_excluding_noinit (filter, &legacy_filter, "name", NULL);
      /* We must db-qualify filters on name. */
      buf = bson_string_new (database->name);
      bson_string_append_c (buf, '.');
      bson_string_append (buf, col_filter);
      BSON_APPEND_UTF8 (&legacy_filter, "name", buf->str);
      bson_string_free (buf, true);
      filter = &legacy_filter;
   }

   read_prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY);

   cursor = mongoc_collection_find (col, MONGOC_QUERY_NONE, 0, 0, 0,
                                    filter ? filter : &q, NULL, read_prefs);

   _mongoc_cursor_transform_init (
      cursor,
      _mongoc_database_find_collections_legacy_filter,
      _mongoc_database_find_collections_legacy_mutate,
      &bson_free,
      ctx);

   mongoc_read_prefs_destroy (read_prefs);

 cleanup_filter:
   mongoc_collection_destroy (col);

   return cursor;
}
char *
_mongoc_secure_transport_RFC2253_from_cert (SecCertificateRef cert)
{
   CFTypeRef value;
   bson_string_t *retval;
   CFTypeRef subject_name;
   CFDictionaryRef cert_dict;

   cert_dict = SecCertificateCopyValues (cert, NULL, NULL);
   if (!cert_dict) {
      return NULL;
   }

   subject_name = CFDictionaryGetValue (cert_dict, kSecOIDX509V1SubjectName);
   if (!subject_name) {
      CFRelease (cert_dict);
      return NULL;
   }

   subject_name = CFDictionaryGetValue (subject_name, kSecPropertyKeyValue);
   if (!subject_name) {
      CFRelease (cert_dict);
      return NULL;
   }

   retval = bson_string_new ("");;

   value = _mongoc_secure_transport_dict_get (subject_name, kSecOIDCommonName);
   _bson_append_cftyperef (retval, "CN=", value);

   value = _mongoc_secure_transport_dict_get (subject_name, kSecOIDOrganizationalUnitName);
   if (value) {
      /* Can be either one unit name, or array of unit names */
      if (CFGetTypeID(value) == CFStringGetTypeID()) {
         _bson_append_cftyperef (retval, ",OU=", value);
      } else if (CFGetTypeID(value) == CFArrayGetTypeID()) {
         CFIndex len = CFArrayGetCount(value);

         if (len > 0) {
            _bson_append_cftyperef (retval, ",OU=", CFArrayGetValueAtIndex(value, 0));
         }
         if (len > 1) {
            _bson_append_cftyperef (retval, ",", CFArrayGetValueAtIndex(value, 1));
         }
         if (len > 2) {
            _bson_append_cftyperef (retval, ",", CFArrayGetValueAtIndex(value, 2));
         }
      }
   }

   value = _mongoc_secure_transport_dict_get (subject_name, kSecOIDOrganizationName);
   _bson_append_cftyperef (retval, ",O=", value);

   value = _mongoc_secure_transport_dict_get (subject_name, kSecOIDLocalityName);
   _bson_append_cftyperef (retval, ",L=", value);

   value = _mongoc_secure_transport_dict_get (subject_name, kSecOIDStateProvinceName);
   _bson_append_cftyperef (retval, ",ST=", value);

   value = _mongoc_secure_transport_dict_get (subject_name, kSecOIDCountryName);
   _bson_append_cftyperef (retval, ",C=", value);

   /* This seems rarely used */
   value = _mongoc_secure_transport_dict_get (subject_name, kSecOIDStreetAddress);
   _bson_append_cftyperef (retval, ",STREET", value);

   CFRelease (cert_dict);
   return bson_string_free (retval, false);
}
Example #14
0
void
mongoc_log_trace_iovec (const char *domain, const mongoc_iovec_t *_iov, size_t _iovcnt)
{
   bson_string_t *str, *astr;
   const char *_b;
   unsigned _i = 0;
   unsigned _j = 0;
   unsigned _k = 0;
   size_t _l = 0;
   uint8_t _v;

#ifdef MONGOC_TRACE
   if (!gLogTrace) {
      return;
   }
#endif

   for (_i = 0; _i < _iovcnt; _i++) {
      _l += _iov[_i].iov_len;
   }

   _i = 0;
   str = bson_string_new(NULL);
   astr = bson_string_new(NULL);

   for (_j = 0; _j < _iovcnt; _j++) {
      _b = (char *)_iov[_j].iov_base;
      _l = _iov[_j].iov_len;

      for (_k = 0; _k < _l; _k++, _i++) {
         _v = *(_b + _k);
         if ((_i % 16) == 0) {
            bson_string_append_printf(str, "%05x: ", _i);
         }

         bson_string_append_printf(str, " %02x", _v);
         if (isprint(_v)) {
            bson_string_append_printf(astr, " %c", _v);
         } else {
            bson_string_append(astr, " .");
         }

         if ((_i % 16) == 15) {
            mongoc_log(MONGOC_LOG_LEVEL_TRACE, domain,
                       "%s %s", str->str, astr->str);
            bson_string_truncate(str, 0);
            bson_string_truncate(astr, 0);
         } else if ((_i % 16) == 7) {
            bson_string_append(str, " ");
            bson_string_append(astr, " ");
         }
      }
   }

   if (_i != 16) {
      mongoc_log(MONGOC_LOG_LEVEL_TRACE, domain,
                 "%-56s %s", str->str, astr->str);
   }

   bson_string_free(str, true);
   bson_string_free(astr, true);
}
Example #15
0
void
ha_sharded_cluster_start (ha_sharded_cluster_t *cluster)
{
   bson_string_t *configopt;
   struct stat st;
   ha_node_t *iter;
   char *cmd;
   int i;

   bson_return_if_fail(cluster);

   if (!stat(cluster->name, &st)) {
      if (S_ISDIR(st.st_mode)) {
         /* Ayyyeeeeeee */
         cmd = bson_strdup_printf("rm -rf \"%s\"", cluster->name);
         fprintf(stderr, "%s\n", cmd);
         system(cmd);
         bson_free(cmd);
      }
   }

   if (!!mkdir(cluster->name, 0750)) {
      fprintf(stderr, "Failed to create directory \"%s\"\n",
              cluster->name);
      abort();
   }

   for (i = 0; i < 12; i++) {
      if (cluster->replicas[i]) {
         ha_replica_set_start(cluster->replicas[i]);
      }
   }

   configopt = bson_string_new (NULL);

   for (iter = cluster->configs; iter; iter = iter->next) {
      ha_node_setup(iter);
      ha_node_restart(iter);
      bson_string_append_printf (configopt, "127.0.0.1:%hu%s",
                                 iter->port,
                                 iter->next ? "," : "");
   }

   sleep (5);

   for (iter = cluster->routers; iter; iter = iter->next) {
      bson_free (iter->configopt);
      iter->configopt = bson_strdup (configopt->str);
      ha_node_setup (iter);
      ha_node_restart (iter);
   }

   ha_sharded_cluster_wait_for_healthy (cluster);

   for (i = 0; i < 12; i++) {
      if (cluster->replicas[i]) {
         ha_config_add_shard (cluster->routers, cluster->replicas[i]);
      }
   }

   bson_string_free (configopt, TRUE);
}
/* Uses old way of querying system.namespaces. */
bson_t *
_mongoc_database_get_collection_info_legacy (mongoc_database_t *database,
                                             const bson_t      *filter,
                                             bson_error_t      *error)
{
   mongoc_collection_t *col;
   mongoc_cursor_t *cursor;
   mongoc_read_prefs_t *read_prefs;
   uint32_t dbname_len;
   const bson_t *doc;
   bson_t legacy_filter;
   bson_iter_t iter;
   const char *name;
   const char *col_filter;
   bson_t q = BSON_INITIALIZER;
   bson_t *ret = NULL;
   bson_t col_array = BSON_INITIALIZER;
   const char *key;
   char keystr[16];
   uint32_t n_cols = 0;

   BSON_ASSERT (database);

   col = mongoc_client_get_collection (database->client,
                                       database->name,
                                       "system.namespaces");

   BSON_ASSERT (col);

   dbname_len = (uint32_t)strlen (database->name);

   /* Filtering on name needs to be handled differently for old servers. */
   if (filter && bson_iter_init_find (&iter, filter, "name")) {
      /* on legacy servers, this must be a string (i.e. not a regex) */
      if (!BSON_ITER_HOLDS_UTF8 (&iter)) {
         bson_set_error (error,
                         MONGOC_ERROR_NAMESPACE,
                         MONGOC_ERROR_NAMESPACE_INVALID_FILTER_TYPE,
                         "On legacy servers, a filter on name can only be a string.");
         goto cleanup_filter;
      }
      BSON_ASSERT (BSON_ITER_HOLDS_UTF8 (&iter));
      col_filter = bson_iter_utf8 (&iter, NULL);
      bson_init (&legacy_filter);
      bson_copy_to_excluding_noinit (filter, &legacy_filter, "name", NULL);
      /* We must db-qualify filters on name. */
      bson_string_t *buf = bson_string_new (database->name);
      bson_string_append_c (buf, '.');
      bson_string_append (buf, col_filter);
      BSON_APPEND_UTF8 (&legacy_filter, "name", buf->str);
      bson_string_free (buf, true);
      filter = &legacy_filter;
   }

   read_prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY);

   cursor = mongoc_collection_find (col, MONGOC_QUERY_NONE, 0, 0, 0,
                                    filter ? filter : &q, NULL, read_prefs);

   ret = bson_new();

   BSON_APPEND_ARRAY_BEGIN (ret, "collections", &col_array);

   while (mongoc_cursor_more (cursor) &&
          !mongoc_cursor_error (cursor, error)) {
      if (mongoc_cursor_next (cursor, &doc)) {
         /* 2 gotchas here.
          * 1. need to ignore any system collections (prefixed with $)
          * 2. need to remove the database name from the collection so that clients
          *    don't need to specialize their logic for old versions of the server.
          */
         if (bson_iter_init_find (&iter, doc, "name") &&
             BSON_ITER_HOLDS_UTF8 (&iter) &&
             (name = bson_iter_utf8 (&iter, NULL)) &&
             !strchr (name, '$') &&
             (0 == strncmp (name, database->name, dbname_len))) {
            bson_t nprefix_col = BSON_INITIALIZER;
            bson_copy_to_excluding_noinit (doc, &nprefix_col, "name", NULL);
            BSON_APPEND_UTF8 (&nprefix_col, "name", name + (dbname_len + 1));  /* +1 for the '.' */
            /* need to construct a key for this array element. */
            bson_uint32_to_string(n_cols, &key, keystr, sizeof (keystr));
            BSON_APPEND_DOCUMENT (&col_array, key, &nprefix_col);
            ++n_cols;
         }
      }
   }

   bson_append_array_end (ret, &col_array);

   mongoc_cursor_destroy (cursor);
   mongoc_read_prefs_destroy (read_prefs);
 cleanup_filter:
   mongoc_collection_destroy (col);
   return ret;
}
/* returns a hex string for all config flag bits, which must be freed. */
char *
_mongoc_handshake_get_config_hex_string (void)
{
   uint32_t byte_count;
   uint8_t *bf;
   bson_string_t *str;
   int i;

   byte_count = (LAST_MONGOC_MD_FLAG + 7) / 8; /* ceil (num_bits / 8) */
   /* allocate enough bytes to fit all config bits. */
   bf = (uint8_t *) bson_malloc0 (byte_count);

#ifdef MONGOC_ENABLE_SSL_SECURE_CHANNEL
   _set_bit (bf, byte_count, MONGOC_ENABLE_SSL_SECURE_CHANNEL);
#endif

#ifdef MONGOC_ENABLE_CRYPTO_CNG
   _set_bit (bf, byte_count, MONGOC_ENABLE_CRYPTO_CNG);
#endif

#ifdef MONGOC_ENABLE_SSL_SECURE_TRANSPORT
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SSL_SECURE_TRANSPORT);
#endif

#ifdef MONGOC_ENABLE_CRYPTO_COMMON_CRYPTO
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_CRYPTO_COMMON_CRYPTO);
#endif

#ifdef MONGOC_ENABLE_SSL_OPENSSL
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SSL_OPENSSL);
#endif

#ifdef MONGOC_ENABLE_CRYPTO_LIBCRYPTO
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_CRYPTO_LIBCRYPTO);
#endif

#ifdef MONGOC_ENABLE_SSL
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SSL);
#endif

#ifdef MONGOC_ENABLE_CRYPTO
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_CRYPTO);
#endif

#ifdef MONGOC_ENABLE_CRYPTO_SYSTEM_PROFILE
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_CRYPTO_SYSTEM_PROFILE);
#endif

#ifdef MONGOC_ENABLE_SASL
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SASL);
#endif

#ifdef MONGOC_HAVE_SASL_CLIENT_DONE
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_HAVE_SASL_CLIENT_DONE);
#endif

#ifdef MONGOC_NO_AUTOMATIC_GLOBALS
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_NO_AUTOMATIC_GLOBALS);
#endif

#ifdef MONGOC_EXPERIMENTAL_FEATURES
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_EXPERIMENTAL_FEATURES);
#endif

#ifdef MONGOC_ENABLE_SSL_LIBRESSL
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SSL_LIBRESSL);
#endif

#ifdef MONGOC_ENABLE_SASL_CYRUS
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SASL_CYRUS);
#endif

#ifdef MONGOC_ENABLE_SASL_SSPI
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SASL_SSPI);
#endif

#ifdef MONGOC_HAVE_SOCKLEN
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_HAVE_SOCKLEN);
#endif

#ifdef MONGOC_ENABLE_COMPRESSION
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_COMPRESSION);
#endif

#ifdef MONGOC_ENABLE_COMPRESSION_SNAPPY
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_COMPRESSION_SNAPPY);
#endif

#ifdef MONGOC_ENABLE_COMPRESSION_ZLIB
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_COMPRESSION_ZLIB);
#endif

#ifdef MONGOC_MD_FLAG_ENABLE_SASL_GSSAPI
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SASL_GSSAPI);
#endif

#ifdef MONGOC_HAVE_RES_NSEARCH
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_RES_NSEARCH);
#endif

#ifdef MONGOC_HAVE_RES_NDESTROY
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_RES_NDESTROY);
#endif

#ifdef MONGOC_HAVE_RES_NCLOSE
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_RES_NCLOSE);
#endif

#ifdef MONGOC_HAVE_RES_SEARCH
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_RES_SEARCH);
#endif

#ifdef MONGOC_HAVE_DNSAPI
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_DNSAPI);
#endif

#ifdef MONGOC_HAVE_RDTSCP
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_RDTSCP);
#endif

#ifdef MONGOC_HAVE_SCHED_GETCPU
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_HAVE_SCHED_GETCPU);
#endif

#ifdef MONGOC_ENABLE_SHM_COUNTERS
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_SHM_COUNTERS);
#endif

#ifdef MONGOC_TRACE
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_TRACE);
#endif

#ifdef MONGOC_ENABLE_ICU
   _set_bit (bf, byte_count, MONGOC_MD_FLAG_ENABLE_ICU);
#endif

   str = bson_string_new ("0x");
   for (i = 0; i < byte_count; i++) {
      bson_string_append_printf (str, "%02x", bf[i]);
   }
   bson_free (bf);
   /* free the bson_string_t, but keep the underlying char* alive. */
   return bson_string_free (str, false);
}