Option& Option::operator=(const string& v) { assert(!type.empty()); if ( (type != "button" && v.empty()) || (type == "check" && v != "true" && v != "false") || (type == "spin" && (stof(v) < min || stof(v) > max))) return *this; if (type == "combo") { OptionsMap comboMap; // To have case insensitive compare string token; std::istringstream ss(defaultValue); while (ss >> token) comboMap[token] << Option(); for (auto &value : comboValues) comboMap[value] << Option(); if (!comboMap.count(v) || v == "var") return *this; }
static void verify_broker_option(OptionsMap& options) { if (!options.count("servername")) { return; } struct addrinfo hints, *res; std::string broker = options["servername"]; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; if (getaddrinfo(broker.c_str(), NULL, &hints, &res) == 0) { freeaddrinfo(res); } else { OptionsMap::iterator iter = options.find("servername"); options.erase(iter); mh_err("Broker '%s' is not resolvable - ignoring", broker.c_str()); } }
OptionsMap mh_parse_options(const char *proc_name, int argc, char **argv, OptionsMap &options) { std::stringstream url; OptionsMap amqp_options; int lpc = 0; options["protocol"] = "tcp"; options["serverport"] = "49000"; amqp_options["reconnect"] = true; /* Force local-only handling */ mh_add_option('b', required_argument, "broker", "specify broker host name", &options, map_option); mh_add_option('D', no_argument, "dns-srv", "interpret the value of --broker as a domain name for DNS SRV lookups", &options, map_option); mh_add_option('p', required_argument, "port", "specify broker port", &options, map_option); mh_add_option('v', no_argument, "verbose", "Increase the log level", NULL, map_option); mh_add_option('u', required_argument, "username", "username to use for authentication to the broker", &amqp_options, connection_option); mh_add_option('P', required_argument, "password", "password to use for authentication to the broker", &amqp_options, connection_option); mh_add_option('s', required_argument, "service", "service name to use for authentication to the broker", &amqp_options, connection_option); mh_add_option('r', required_argument, "reconnect", "attempt to reconnect if the broker connection is lost", &amqp_options, connection_option); #ifdef MH_SSL mh_add_option('n', required_argument, "ssl-cert-name", "name of the certificate to use", &amqp_options, connection_option); mh_add_option('t', no_argument, "use-tls", "Use TLS/SSL encryption", &options, connection_option); #endif #ifdef WIN32 for (lpc = 0; lpc < DIMOF(matahari_options); lpc++) { if (matahari_options[lpc].callback) { char *value = NULL; wchar_t *name_ws = char2wide(matahari_options[lpc].long_name); if (RegistryRead (HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\services\\Matahari", name_ws, &value) == 0) { matahari_options[lpc].callback( matahari_options[lpc].code, matahari_options[lpc].long_name, value, matahari_options[lpc].userdata); free(value); value = NULL; } free(name_ws); } } #else int idx = 0; int num_options = 0; int opt_string_len = 0; char opt_string[2 * DIMOF(matahari_options)]; struct option *long_opts = (struct option *)calloc(1, sizeof(struct option)); int arg; /* Force more local-only processing specific to linux */ mh_add_option('h', no_argument, "help", NULL, NULL, NULL); opt_string[0] = 0; for(lpc = 0; lpc < DIMOF(matahari_options); lpc++) { if(matahari_options[lpc].code) { long_opts = (struct option *)realloc(long_opts, (2 + num_options) * sizeof(struct option)); long_opts[num_options].name = matahari_options[lpc].long_name; long_opts[num_options].has_arg = matahari_options[lpc].has_arg; long_opts[num_options].flag = NULL; long_opts[num_options].val = matahari_options[lpc].code; num_options++; long_opts[num_options].name = 0; long_opts[num_options].has_arg = 0; long_opts[num_options].flag = 0; long_opts[num_options].val = 0; opt_string[opt_string_len++] = matahari_options[lpc].code; if(matahari_options[lpc].has_arg == required_argument) { opt_string[opt_string_len++] = ':'; } opt_string[opt_string_len] = 0; } } read_environment(options); while ((arg = getopt_long(argc, argv, opt_string, long_opts, &idx)) != -1) { if(arg == 'h') { print_help('h', NULL, NULL, (void*)proc_name); exit(0); } else if(arg > 0 && arg < DIMOF(matahari_options) && matahari_options[arg].callback) { matahari_options[arg].callback( matahari_options[arg].code, matahari_options[arg].long_name, optarg, matahari_options[arg].userdata); } else { print_help(arg, NULL, NULL, (void*)proc_name); exit(1); } } free(long_opts); if (!options.count("dns-srv")) { verify_broker_option(options); } #endif #ifdef MH_SSL if (options.count("use-tls")) { options["protocol"] = "ssl"; if (!options.count("ssl-cert-db")) { mh_warn("To enable SSL, you must supply a certificate database"); } if (!options.count("ssl-cert-password-file")) { mh_warn("To enable SSL, you must supply a certificate password file"); } if (!(amqp_options.count("ssl-cert-name") || options.count("ssl-cert-name"))) { mh_warn("No SSL certificate name specified"); } } #endif return amqp_options; }
qpid::messaging::Connection mh_connect(OptionsMap mh_options, OptionsMap amqp_options, int retry) { int retries = 0; int backoff = 0; GList *srv_records = NULL, *cur_srv_record = NULL; struct mh_dnssrv_record *record; GError *error = NULL; int status; /* Attempt to initiate k5start for credential renewal's without * prompting for a password each time an agent is run */ if (strcmp(amqp_options["sasl-mechanism"].asString().c_str(),"GSSAPI") == 0) { std::string krb5_keytab(mh_options["krb5_keytab"].asString()); std::string krb5_interval(mh_options["krb5_interval"].asString()); const gchar *k5start_bin[] = { "/usr/bin/k5start", "-U", "-f", krb5_keytab.c_str(), "-K", krb5_interval.c_str(), NULL, }; mh_trace("kerberos: %s %s %s %s %s %s", k5start_bin[0], k5start_bin[1], k5start_bin[2], k5start_bin[3], k5start_bin[4], k5start_bin[5]); if (g_file_test(k5start_bin[0], G_FILE_TEST_IS_EXECUTABLE)) { mh_trace("Running k5start"); if (!g_spawn_sync( NULL, (gchar **) k5start_bin, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL, &status, &error)) { mh_warn("k5start failure: %s", error->message); g_error_free(error); } } } if (!mh_options.count("servername") || mh_options.count("dns-srv")) { /* * Do an SRV lookup either because no broker was specified at all, * or because a broker domain was given and the --srv option was * used specifically requesting an SRV lookup. */ std::stringstream query; query << "_matahari."; query << ((mh_options["protocol"]) == "ssl" ? "_tls" : "_tcp") << "."; if (mh_options.count("servername")) { query << mh_options["servername"]; } else { query << mh_dnsdomainname(); } if ((cur_srv_record = srv_records = mh_dnssrv_lookup(query.str().c_str()))) { mh_info("SRV query successful: %s", query.str().c_str()); } else { mh_info("SRV query not successful: %s", query.str().c_str()); } } while (true) { std::stringstream url; if (srv_records) { /* Use the result of a DNS SRV lookup. */ record = (struct mh_dnssrv_record *) cur_srv_record->data; url << "amqp:" << mh_options["protocol"]; url << ":" << mh_dnssrv_record_get_host(record); url << ":" << mh_dnssrv_record_get_port(record); cur_srv_record = cur_srv_record->next; if (!cur_srv_record) { cur_srv_record = srv_records; } } else if (mh_options.count("servername")) { /* Use the explicitly specified broker hostname or IP address. */ url << "amqp:" << mh_options["protocol"] << ":" << mh_options["servername"] << ":" << mh_options["serverport"] ; } else { /* If nothing else, try localhost */ url << "amqp:" << mh_options["protocol"] << ":localhost:" << mh_options["serverport"] ; } retries++; qpid::messaging::Connection amqp = qpid::messaging::Connection(url.str(), amqp_options); if(retries < 5) { mh_info("Trying: %s", url.str().c_str()); } else if(retries == 5) { mh_warn("Cannot find a QMF broker - will keep retrying silently"); } else { backoff = retries % 300; } try { amqp.open(); g_list_free_full(srv_records, mh_dnssrv_record_free); return amqp; } catch (const std::exception& err) { if(!retry) { goto bail; } else if(backoff) { g_usleep(backoff * G_USEC_PER_SEC); } } } bail: g_list_free_full(srv_records, mh_dnssrv_record_free); return NULL; }