From 22acf2fc5a93930e9ed7d47753aceb88ad5b6b39 Mon Sep 17 00:00:00 2001 From: Richard Whitehouse Date: Tue, 2 May 2017 10:41:59 +0000 Subject: [PATCH 1/5] Separate out defaulting and validating options --- src/main.cpp | 284 +++++++++++++++++++++++++++------------------------ 1 file changed, 152 insertions(+), 132 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index dd6c46b7d..c0a24fe60 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -532,6 +532,153 @@ bool parse_port(const std::string& port_str, int& port) return -1; \ } +// Set the options to their defaults +static void default_options(struct options& opt) +{ + opt.pcscf_enabled = false; + opt.pcscf_trusted_port = 0; + opt.pcscf_untrusted_port = 0; + opt.upstream_proxy_port = 0; + opt.webrtc_port = 0; + opt.ibcf = PJ_FALSE; + opt.external_icscf_uri = ""; + opt.auth_enabled = PJ_FALSE; + opt.enum_suffix = ".e164.arpa"; + opt.default_tel_uri_translation = false; + + // If changing this default for reg_max_expires, note that + // debian/homestead.init.d in the homestead repository also defaults + // reg_max_expires, and so the default value set in that file must be changed + // also. + opt.reg_max_expires = 300; + + opt.sub_max_expires = 0; + opt.sas_server = "0.0.0.0"; + opt.record_routing_model = 1; + opt.default_session_expires = 10 * 60; + opt.max_session_expires = 10 * 60; + opt.worker_threads = 1; + opt.analytics_enabled = PJ_FALSE; + opt.http_address = "127.0.0.1"; + opt.http_port = 9888; + opt.http_threads = 1; + opt.dns_servers.push_back("127.0.0.1"); + opt.billing_cdf = ""; + opt.emerg_reg_accepted = PJ_FALSE; + opt.max_call_list_length = 0; + opt.memento_threads = 25; + opt.call_list_ttl = 604800; + opt.target_latency_us = 100000; + opt.cass_target_latency_us = 1000000; + opt.max_tokens = 1000; + opt.init_token_rate = 100.0; + opt.min_token_rate = 10.0; + opt.log_to_file = PJ_FALSE; + opt.log_level = 0; + opt.daemon = PJ_FALSE; + opt.interactive = PJ_FALSE; + opt.memcached_write_format = MemcachedWriteFormat::JSON; + opt.override_npdi = PJ_FALSE; + opt.exception_max_ttl = 600; + opt.sip_blacklist_duration = SIPResolver::DEFAULT_BLACKLIST_DURATION; + opt.http_blacklist_duration = HttpResolver::DEFAULT_BLACKLIST_DURATION; + opt.astaire_blacklist_duration = AstaireResolver::DEFAULT_BLACKLIST_DURATION; + opt.sip_tcp_connect_timeout = 2000; + opt.sip_tcp_send_timeout = 2000; + opt.session_continued_timeout_ms = SCSCFSproutlet::DEFAULT_SESSION_CONTINUED_TIMEOUT; + opt.session_terminated_timeout_ms = SCSCFSproutlet::DEFAULT_SESSION_TERMINATED_TIMEOUT; + opt.stateless_proxies.clear(); + opt.ralf_threads = 25; + opt.non_register_auth_mode = NonRegisterAuthentication::NEVER; + opt.force_third_party_register_body = false; + opt.listen_port = 0; + SPROUTLET_MACRO(SPROUTLET_CFG_OPTIONS_DEFAULT_VALUES) + opt.impi_store_mode = ImpiStore::Mode::READ_IMPI_WRITE_IMPI; + opt.nonce_count_supported = false; + opt.scscf_node_uri = ""; + opt.sas_signaling_if = false; + opt.disable_tcp_switch = false; + +} + +static int validate_options(struct options& opt) +{ + if (opt.sas_server == "0.0.0.0") + { + TRC_WARNING("SAS server option was invalid or not configured - SAS is disabled"); + CL_SPROUT_INVALID_SAS_OPTION.log(); + } + + if ((!opt.pcscf_enabled) && (!opt.enabled_scscf) && (!opt.enabled_icscf)) + { + CL_SPROUT_NO_SI_CSCF.log(); + TRC_WARNING("Most Sprout nodes have at least one of P-CSCF, S-CSCF or I-CSCF enabled"); + } + + if ((opt.pcscf_enabled) && ((opt.enabled_scscf) || (opt.enabled_icscf))) + { + TRC_ERROR("Cannot enable both P-CSCF and S/I-CSCF"); + return 1; + } + + if ((opt.pcscf_enabled) && + (opt.upstream_proxy == "")) + { + TRC_ERROR("Cannot enable P-CSCF without specifying --routing-proxy"); + return 1; + } + + if ((opt.ibcf) && (!opt.pcscf_enabled)) + { + TRC_ERROR("Cannot enable IBCF without also enabling P-CSCF"); + return 1; + } + + if ((opt.webrtc_port != 0 ) && (!opt.pcscf_enabled)) + { + TRC_ERROR("Cannot enable WebRTC without also enabling P-CSCF"); + return 1; + } + + if (((opt.enabled_scscf) || (opt.enabled_icscf)) && + (opt.hss_server == "")) + { + CL_SPROUT_SI_CSCF_NO_HOMESTEAD.log(); + TRC_ERROR("S/I-CSCF enabled with no Homestead server"); + return 1; + } + + if ((opt.pcscf_enabled) && (opt.hss_server != "")) + { + TRC_WARNING("Homestead server configured on P-CSCF, ignoring"); + } + + if ((opt.pcscf_enabled) && (opt.xdm_server != "")) + { + TRC_WARNING("XDM server configured on P-CSCF, ignoring"); + } + + if (((!opt.registration_stores.empty()) || (opt.impi_store != "")) && + (opt.auth_enabled) && + (opt.worker_threads == 1)) + { + TRC_WARNING("Use multiple threads for good performance when using memstore and/or authentication"); + } + + if ((opt.pcscf_enabled) && (opt.reg_max_expires != 0)) + { + TRC_WARNING("A registration expiry period should not be specified for P-CSCF"); + } + + if ((!opt.enum_servers.empty()) && + (!opt.enum_file.empty())) + { + TRC_WARNING("Both ENUM server and ENUM file lookup enabled - ignoring ENUM file"); + } + + return 0; +} + static pj_status_t init_logging_options(int argc, char* argv[], struct options* options) { int c; @@ -1442,69 +1589,7 @@ int main(int argc, char* argv[]) sem_init(&term_sem, 0, 0); signal(SIGTERM, terminate_handler); - opt.pcscf_enabled = false; - opt.pcscf_trusted_port = 0; - opt.pcscf_untrusted_port = 0; - opt.upstream_proxy_port = 0; - opt.webrtc_port = 0; - opt.ibcf = PJ_FALSE; - opt.external_icscf_uri = ""; - opt.auth_enabled = PJ_FALSE; - opt.enum_suffix = ".e164.arpa"; - opt.default_tel_uri_translation = false; - - // If changing this default for reg_max_expires, note that - // debian/homestead.init.d in the homestead repository also defaults - // reg_max_expires, and so the default value set in that file must be changed - // also. - opt.reg_max_expires = 300; - - opt.sub_max_expires = 0; - opt.sas_server = "0.0.0.0"; - opt.record_routing_model = 1; - opt.default_session_expires = 10 * 60; - opt.max_session_expires = 10 * 60; - opt.worker_threads = 1; - opt.analytics_enabled = PJ_FALSE; - opt.http_address = "127.0.0.1"; - opt.http_port = 9888; - opt.http_threads = 1; - opt.dns_servers.push_back("127.0.0.1"); - opt.billing_cdf = ""; - opt.emerg_reg_accepted = PJ_FALSE; - opt.max_call_list_length = 0; - opt.memento_threads = 25; - opt.call_list_ttl = 604800; - opt.target_latency_us = 100000; - opt.cass_target_latency_us = 1000000; - opt.max_tokens = 1000; - opt.init_token_rate = 100.0; - opt.min_token_rate = 10.0; - opt.log_to_file = PJ_FALSE; - opt.log_level = 0; - opt.daemon = PJ_FALSE; - opt.interactive = PJ_FALSE; - opt.memcached_write_format = MemcachedWriteFormat::JSON; - opt.override_npdi = PJ_FALSE; - opt.exception_max_ttl = 600; - opt.sip_blacklist_duration = SIPResolver::DEFAULT_BLACKLIST_DURATION; - opt.http_blacklist_duration = HttpResolver::DEFAULT_BLACKLIST_DURATION; - opt.astaire_blacklist_duration = AstaireResolver::DEFAULT_BLACKLIST_DURATION; - opt.sip_tcp_connect_timeout = 2000; - opt.sip_tcp_send_timeout = 2000; - opt.session_continued_timeout_ms = SCSCFSproutlet::DEFAULT_SESSION_CONTINUED_TIMEOUT; - opt.session_terminated_timeout_ms = SCSCFSproutlet::DEFAULT_SESSION_TERMINATED_TIMEOUT; - opt.stateless_proxies.clear(); - opt.ralf_threads = 25; - opt.non_register_auth_mode = NonRegisterAuthentication::NEVER; - opt.force_third_party_register_body = false; - opt.listen_port = 0; - SPROUTLET_MACRO(SPROUTLET_CFG_OPTIONS_DEFAULT_VALUES) - opt.impi_store_mode = ImpiStore::Mode::READ_IMPI_WRITE_IMPI; - opt.nonce_count_supported = false; - opt.scscf_node_uri = ""; - opt.sas_signaling_if = false; - opt.disable_tcp_switch = false; + default_options(opt); status = init_logging_options(argc, argv, &opt); @@ -1584,79 +1669,14 @@ int main(int argc, char* argv[]) } std::vector sproutlet_uris; - SPROUTLET_MACRO(SPROUTLET_VERIFY_OPTIONS) - if (opt.sas_server == "0.0.0.0") - { - TRC_WARNING("SAS server option was invalid or not configured - SAS is disabled"); - CL_SPROUT_INVALID_SAS_OPTION.log(); - } - - if ((!opt.pcscf_enabled) && (!opt.enabled_scscf) && (!opt.enabled_icscf)) - { - CL_SPROUT_NO_SI_CSCF.log(); - TRC_WARNING("Most Sprout nodes have at least one of P-CSCF, S-CSCF or I-CSCF enabled"); - } - - if ((opt.pcscf_enabled) && ((opt.enabled_scscf) || (opt.enabled_icscf))) - { - TRC_ERROR("Cannot enable both P-CSCF and S/I-CSCF"); - return 1; - } - - if ((opt.pcscf_enabled) && - (opt.upstream_proxy == "")) - { - TRC_ERROR("Cannot enable P-CSCF without specifying --routing-proxy"); - return 1; - } - - if ((opt.ibcf) && (!opt.pcscf_enabled)) - { - TRC_ERROR("Cannot enable IBCF without also enabling P-CSCF"); - return 1; - } - - if ((opt.webrtc_port != 0 ) && (!opt.pcscf_enabled)) - { - TRC_ERROR("Cannot enable WebRTC without also enabling P-CSCF"); - return 1; - } - - if (((opt.enabled_scscf) || (opt.enabled_icscf)) && - (opt.hss_server == "")) - { - CL_SPROUT_SI_CSCF_NO_HOMESTEAD.log(); - TRC_ERROR("S/I-CSCF enabled with no Homestead server"); - return 1; - } - - if ((opt.pcscf_enabled) && (opt.hss_server != "")) - { - TRC_WARNING("Homestead server configured on P-CSCF, ignoring"); - } - - if ((opt.pcscf_enabled) && (opt.xdm_server != "")) - { - TRC_WARNING("XDM server configured on P-CSCF, ignoring"); - } + SPROUTLET_MACRO(SPROUTLET_VERIFY_OPTIONS) - if (((!opt.registration_stores.empty()) || (opt.impi_store != "")) && - (opt.auth_enabled) && - (opt.worker_threads == 1)) - { - TRC_WARNING("Use multiple threads for good performance when using memstore and/or authentication"); - } + status = validate_options(opt); - if ((opt.pcscf_enabled) && (opt.reg_max_expires != 0)) - { - TRC_WARNING("A registration expiry period should not be specified for P-CSCF"); - } - - if ((!opt.enum_servers.empty()) && - (!opt.enum_file.empty())) + if (status != PJ_SUCCESS) { - TRC_WARNING("Both ENUM server and ENUM file lookup enabled - ignoring ENUM file"); + return status; } // Parse the registration-stores argument. From bdb22712c640dc1c99e8fa6784a45b4a3cb572ab Mon Sep 17 00:00:00 2001 From: Richard Whitehouse Date: Tue, 2 May 2017 10:56:30 +0000 Subject: [PATCH 2/5] Determine address family in main --- include/stack.h | 1 + src/main.cpp | 21 +++++++++++++++++++-- src/stack.cpp | 16 ++++------------ 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/include/stack.h b/include/stack.h index 61370d608..b460c2d9d 100644 --- a/include/stack.h +++ b/include/stack.h @@ -166,6 +166,7 @@ extern pj_status_t init_stack(const std::string& sas_system_name, int scscf_port, bool sas_signaling_if, std::set sproutlet_ports, + int address_family, const std::string& local_host, const std::string& public_host, const std::string& home_domain, diff --git a/src/main.cpp b/src/main.cpp index c0a24fe60..263d9a448 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1679,6 +1679,13 @@ int main(int argc, char* argv[]) return status; } + // If local host was not specified, use the host name returned by + // pj_gethostname. + if (opt.local_host == "") + { + opt.local_host = PJUtils::pj_str_to_string(pj_gethostname()); + } + // Parse the registration-stores argument. std::string registration_store_location; std::vector remote_registration_stores_locations; @@ -1892,6 +1899,15 @@ int main(int argc, char* argv[]) quiescing_mgr = new QuiescingManager(); quiescing_mgr->register_completion_handler(new QuiesceCompleteHandler()); + // Set up the default address family. This is IPv4 unless our local host is an IPv6 address. + int addr_family = AF_INET; + struct in6_addr dummy_addr; + if (inet_pton(AF_INET6, opt.local_host.c_str(), &dummy_addr) == 1) + { + TRC_DEBUG("Local host is an IPv6 address - enabling IPv6 mode"); + addr_family = AF_INET6; + } + // Initialize the PJSIP stack and associated subsystems. status = init_stack(opt.sas_system_name, opt.sas_server, @@ -1900,6 +1916,7 @@ int main(int argc, char* argv[]) opt.port_scscf, opt.sas_signaling_if, opt.sproutlet_ports, + addr_family, opt.local_host, opt.public_host, opt.home_domain, @@ -1938,7 +1955,7 @@ int main(int argc, char* argv[]) // Now that we know the address family, create an HttpResolver too. http_resolver = new HttpResolver(dns_resolver, - stack_data.addr_family, + addr_family, opt.http_blacklist_duration); if (opt.ralf_server != "") @@ -2102,7 +2119,7 @@ int main(int argc, char* argv[]) TRC_STATUS("Using memcached compatible store with binary protocol"); astaire_resolver = new AstaireResolver(dns_resolver, - stack_data.addr_family, + addr_family, opt.astaire_blacklist_duration); local_data_store = (Store*)new TopologyNeutralMemcachedStore(registration_store_location, diff --git a/src/stack.cpp b/src/stack.cpp index 44469560b..fb5b6343b 100644 --- a/src/stack.cpp +++ b/src/stack.cpp @@ -582,6 +582,7 @@ pj_status_t init_stack(const std::string& system_name, int scscf_port, bool sas_signaling_if, std::set sproutlet_ports, + int address_family, const std::string& local_host, const std::string& public_host, const std::string& home_domain, @@ -605,8 +606,7 @@ pj_status_t init_stack(const std::string& system_name, unsigned addr_cnt = PJ_ARRAY_SIZE(addr_list); unsigned i; - // Get ports and host names specified on options. If local host was not - // specified, use the host name returned by pj_gethostname. + // Get ports and host names specified on options. char* local_host_cstr = strdup(local_host.c_str()); char* public_host_cstr = strdup(public_host.c_str()); char* home_domain_cstr = strdup(home_domain.c_str()); @@ -620,6 +620,7 @@ pj_status_t init_stack(const std::string& system_name, stack_data.pcscf_untrusted_port = pcscf_untrusted_port; stack_data.scscf_port = scscf_port; + stack_data.addr_family = address_family; stack_data.sipresolver = sipresolver; // Copy other functional options to stack data. @@ -629,7 +630,7 @@ pj_status_t init_stack(const std::string& system_name, stack_data.sip_tcp_send_timeout = sip_tcp_send_timeout; // Work out local and public hostnames and cluster domain names. - stack_data.local_host = (local_host != "") ? pj_str(local_host_cstr) : *pj_gethostname(); + stack_data.local_host = pj_str(local_host_cstr); stack_data.public_host = (public_host != "") ? pj_str(public_host_cstr) : stack_data.local_host; stack_data.default_home_domain = (home_domain != "") ? pj_str(home_domain_cstr) : stack_data.local_host; stack_data.scscf_uri_str = pj_str(scscf_uri_cstr); @@ -657,15 +658,6 @@ pj_status_t init_stack(const std::string& system_name, } } - // Set up the default address family. This is IPv4 unless our local host is an IPv6 address. - stack_data.addr_family = AF_INET; - struct in6_addr dummy_addr; - if (inet_pton(AF_INET6, local_host_cstr, &dummy_addr) == 1) - { - TRC_DEBUG("Local host is an IPv6 address - enabling IPv6 mode"); - stack_data.addr_family = AF_INET6; - } - stack_data.record_route_on_every_hop = false; stack_data.record_route_on_initiation_of_originating = false; stack_data.record_route_on_initiation_of_terminating = false; From aad19aa0d54f1aa53c32a984ea2bf1e935953f27 Mon Sep 17 00:00:00 2001 From: Richard Whitehouse Date: Tue, 2 May 2017 11:36:37 +0000 Subject: [PATCH 3/5] Initialize PJSIP after sproutlets have been loaded --- src/main.cpp | 200 +++++++++++++++++++++++++-------------------------- 1 file changed, 100 insertions(+), 100 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 263d9a448..e59a40c06 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1908,51 +1908,6 @@ int main(int argc, char* argv[]) addr_family = AF_INET6; } - // Initialize the PJSIP stack and associated subsystems. - status = init_stack(opt.sas_system_name, - opt.sas_server, - opt.pcscf_trusted_port, - opt.pcscf_untrusted_port, - opt.port_scscf, - opt.sas_signaling_if, - opt.sproutlet_ports, - addr_family, - opt.local_host, - opt.public_host, - opt.home_domain, - opt.additional_home_domains, - opt.uri_scscf, - opt.sprout_hostname, - opt.alias_hosts, - sip_resolver, - opt.record_routing_model, - opt.default_session_expires, - opt.max_session_expires, - opt.sip_tcp_connect_timeout, - opt.sip_tcp_send_timeout, - quiescing_mgr, - opt.billing_cdf, - sproutlet_uris); - - if (status != PJ_SUCCESS) - { - CL_SPROUT_SIP_INIT_INTERFACE_FAIL.log(PJUtils::pj_status_to_string(status).c_str()); - TRC_ERROR("Error initializing stack %s", PJUtils::pj_status_to_string(status).c_str()); - return 1; - } - - //If the flag is set, disable UDP-to-TCP uplift. - if (opt.disable_tcp_switch) - { - TRC_STATUS("Disabling UDP-to-TCP uplift"); - pjsip_cfg_t* pjsip_config = pjsip_cfg(); - pjsip_config->endpt.disable_tcp_switch = true; - } - - // Set up our signal handler for (un)quiesce signals. - signal(QUIESCE_SIGNAL, quiesce_unquiesce_handler); - signal(UNQUIESCE_SIGNAL, quiesce_unquiesce_handler); - // Now that we know the address family, create an HttpResolver too. http_resolver = new HttpResolver(dns_resolver, addr_family, @@ -1977,9 +1932,6 @@ int main(int argc, char* argv[]) CL_SPROUT_NO_RALF_CONFIGURED.log(); } - // Initialise the OPTIONS handling module. - status = init_options(); - if (opt.hss_server != "") { // Create a connection to the HSS. @@ -2017,58 +1969,6 @@ int main(int argc, char* argv[]) enum_service = new DummyEnumService(opt.home_domain); } - if (opt.pcscf_enabled) - { - // Create an ACR factory for the P-CSCF. - pcscf_acr_factory = (ralf_processor != NULL) ? - (ACRFactory*)new RalfACRFactory(ralf_processor, ACR::PCSCF) : - new ACRFactory(); - - // Launch stateful proxy as P-CSCF. - status = init_stateful_proxy(NULL, - NULL, - NULL, - true, - opt.upstream_proxy, - opt.upstream_proxy_port, - opt.upstream_proxy_connections, - opt.upstream_proxy_recycle, - opt.ibcf, - opt.trusted_hosts, - opt.pbxes, - opt.pbx_service_route, - analytics_logger, - NULL, - NULL, - NULL, - pcscf_acr_factory, - NULL, - NULL, - "", - quiescing_mgr, - opt.enabled_icscf, - opt.enabled_scscf, - opt.emerg_reg_accepted); - if (status != PJ_SUCCESS) - { - TRC_ERROR("Failed to enable P-CSCF edge proxy"); - return 1; - } - - pj_bool_t websockets_enabled = (opt.webrtc_port != 0); - if (websockets_enabled) - { - status = init_websockets((unsigned short)opt.webrtc_port); - if (status != PJ_SUCCESS) - { - TRC_ERROR("Error initializing websockets, %s", - PJUtils::pj_status_to_string(status).c_str()); - - return 1; - } - } - } - // Create a connection to Chronos. std::string port_str = std::to_string(opt.http_port); @@ -2252,6 +2152,106 @@ int main(int argc, char* argv[]) return 1; } + // Initialize the PJSIP stack and associated subsystems. + status = init_stack(opt.sas_system_name, + opt.sas_server, + opt.pcscf_trusted_port, + opt.pcscf_untrusted_port, + opt.port_scscf, + opt.sas_signaling_if, + opt.sproutlet_ports, + addr_family, + opt.local_host, + opt.public_host, + opt.home_domain, + opt.additional_home_domains, + opt.uri_scscf, + opt.sprout_hostname, + opt.alias_hosts, + sip_resolver, + opt.record_routing_model, + opt.default_session_expires, + opt.max_session_expires, + opt.sip_tcp_connect_timeout, + opt.sip_tcp_send_timeout, + quiescing_mgr, + opt.billing_cdf, + sproutlet_uris); + + if (status != PJ_SUCCESS) + { + CL_SPROUT_SIP_INIT_INTERFACE_FAIL.log(PJUtils::pj_status_to_string(status).c_str()); + TRC_ERROR("Error initializing stack %s", PJUtils::pj_status_to_string(status).c_str()); + return 1; + } + + // If the flag is set, disable UDP-to-TCP uplift. + if (opt.disable_tcp_switch) + { + TRC_STATUS("Disabling UDP-to-TCP uplift"); + pjsip_cfg_t* pjsip_config = pjsip_cfg(); + pjsip_config->endpt.disable_tcp_switch = true; + } + + // Set up our signal handler for (un)quiesce signals. + signal(QUIESCE_SIGNAL, quiesce_unquiesce_handler); + signal(UNQUIESCE_SIGNAL, quiesce_unquiesce_handler); + + // Initialise the OPTIONS handling module. + status = init_options(); + + if (opt.pcscf_enabled) + { + // Create an ACR factory for the P-CSCF. + pcscf_acr_factory = (ralf_processor != NULL) ? + (ACRFactory*)new RalfACRFactory(ralf_processor, ACR::PCSCF) : + new ACRFactory(); + + // Launch stateful proxy as P-CSCF. + status = init_stateful_proxy(NULL, + NULL, + NULL, + true, + opt.upstream_proxy, + opt.upstream_proxy_port, + opt.upstream_proxy_connections, + opt.upstream_proxy_recycle, + opt.ibcf, + opt.trusted_hosts, + opt.pbxes, + opt.pbx_service_route, + analytics_logger, + NULL, + NULL, + NULL, + pcscf_acr_factory, + NULL, + NULL, + "", + quiescing_mgr, + opt.enabled_icscf, + opt.enabled_scscf, + opt.emerg_reg_accepted); + if (status != PJ_SUCCESS) + { + TRC_ERROR("Failed to enable P-CSCF edge proxy"); + return 1; + } + + pj_bool_t websockets_enabled = (opt.webrtc_port != 0); + if (websockets_enabled) + { + status = init_websockets((unsigned short)opt.webrtc_port); + if (status != PJ_SUCCESS) + { + TRC_ERROR("Error initializing websockets, %s", + PJUtils::pj_status_to_string(status).c_str()); + + return 1; + } + } + } + // Must happen after all SNMP tables have been registered. if (opt.pcscf_enabled) { From 00786a3c265dde2832ca843e0d39b3535987e171 Mon Sep 17 00:00:00 2001 From: Richard Whitehouse Date: Tue, 2 May 2017 13:08:46 +0000 Subject: [PATCH 4/5] Split creating and starting the stack --- include/stack.h | 16 ++++++------ src/main.cpp | 65 +++++++++++++++++++++++++++++-------------------- src/stack.cpp | 30 ++++++++++++++--------- 3 files changed, 66 insertions(+), 45 deletions(-) diff --git a/include/stack.h b/include/stack.h index b460c2d9d..6a584fe33 100644 --- a/include/stack.h +++ b/include/stack.h @@ -165,24 +165,26 @@ extern pj_status_t init_stack(const std::string& sas_system_name, int pcscf_untrusted_port, int scscf_port, bool sas_signaling_if, - std::set sproutlet_ports, int address_family, const std::string& local_host, const std::string& public_host, const std::string& home_domain, const std::string& additional_home_domains, - const std::string& sproutlet_uri, - const std::string& sprout_hostname, - const std::string& alias_hosts, + const std::string& scscf_uri, SIPResolver* sipresolver, int record_routing_model, const int default_session_expires, const int max_session_expires, const int sip_tcp_connect_timeout, const int sip_tcp_send_timeout, - QuiescingManager *quiescing_mgr, - const std::string& cdf_domain, - std::vector sproutlet_uris); + const std::string& cdf_domain); + +pj_status_t start_stack(std::set sproutlet_ports, + const std::string& sprout_hostname, + const std::string& alias_hosts, + QuiescingManager *quiescing_mgr_arg, + std::vector sproutlet_uris); + extern pj_status_t start_pjsip_thread(); extern pj_status_t stop_pjsip_thread(); extern void stop_stack(); diff --git a/src/main.cpp b/src/main.cpp index e59a40c06..fbda2e452 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1908,6 +1908,36 @@ int main(int argc, char* argv[]) addr_family = AF_INET6; } + // Initialize the PJSIP stack and associated subsystems. + // We need to do this early so that components which use PJSIP + // can create data on stack_data.pool. + status = init_stack(opt.sas_system_name, + opt.sas_server, + opt.pcscf_trusted_port, + opt.pcscf_untrusted_port, + opt.port_scscf, + opt.sas_signaling_if, + addr_family, + opt.local_host, + opt.public_host, + opt.home_domain, + opt.additional_home_domains, + opt.uri_scscf, + sip_resolver, + opt.record_routing_model, + opt.default_session_expires, + opt.max_session_expires, + opt.sip_tcp_connect_timeout, + opt.sip_tcp_send_timeout, + opt.billing_cdf); + + if (status != PJ_SUCCESS) + { + CL_SPROUT_SIP_INIT_INTERFACE_FAIL.log(PJUtils::pj_status_to_string(status).c_str()); + TRC_ERROR("Error initializing stack %s", PJUtils::pj_status_to_string(status).c_str()); + return 1; + } + // Now that we know the address family, create an HttpResolver too. http_resolver = new HttpResolver(dns_resolver, addr_family, @@ -2152,36 +2182,19 @@ int main(int argc, char* argv[]) return 1; } - // Initialize the PJSIP stack and associated subsystems. - status = init_stack(opt.sas_system_name, - opt.sas_server, - opt.pcscf_trusted_port, - opt.pcscf_untrusted_port, - opt.port_scscf, - opt.sas_signaling_if, - opt.sproutlet_ports, - addr_family, - opt.local_host, - opt.public_host, - opt.home_domain, - opt.additional_home_domains, - opt.uri_scscf, - opt.sprout_hostname, - opt.alias_hosts, - sip_resolver, - opt.record_routing_model, - opt.default_session_expires, - opt.max_session_expires, - opt.sip_tcp_connect_timeout, - opt.sip_tcp_send_timeout, - quiescing_mgr, - opt.billing_cdf, - sproutlet_uris); + // Start the PJSIP stack and it's transports. These needs to + // happen after we have loaded the sproutlets so they can adjust the + // listening ports. + status = start_stack(opt.sproutlet_ports, + opt.sprout_hostname, + opt.alias_hosts, + quiescing_mgr, + sproutlet_uris); if (status != PJ_SUCCESS) { CL_SPROUT_SIP_INIT_INTERFACE_FAIL.log(PJUtils::pj_status_to_string(status).c_str()); - TRC_ERROR("Error initializing stack %s", PJUtils::pj_status_to_string(status).c_str()); + TRC_ERROR("Error starting stack %s", PJUtils::pj_status_to_string(status).c_str()); return 1; } diff --git a/src/stack.cpp b/src/stack.cpp index fb5b6343b..d94bdb54e 100644 --- a/src/stack.cpp +++ b/src/stack.cpp @@ -581,30 +581,21 @@ pj_status_t init_stack(const std::string& system_name, int pcscf_untrusted_port, int scscf_port, bool sas_signaling_if, - std::set sproutlet_ports, int address_family, const std::string& local_host, const std::string& public_host, const std::string& home_domain, const std::string& additional_home_domains, const std::string& scscf_uri, - const std::string& sprout_hostname, - const std::string& alias_hosts, SIPResolver* sipresolver, int record_routing_model, const int default_session_expires, const int max_session_expires, const int sip_tcp_connect_timeout, const int sip_tcp_send_timeout, - QuiescingManager *quiescing_mgr_arg, - const std::string& cdf_domain, - std::vector sproutlet_uris) + const std::string& cdf_domain) { pj_status_t status; - pj_sockaddr pri_addr; - pj_sockaddr addr_list[16]; - unsigned addr_cnt = PJ_ARRAY_SIZE(addr_list); - unsigned i; // Get ports and host names specified on options. char* local_host_cstr = strdup(local_host.c_str()); @@ -718,6 +709,21 @@ pj_status_t init_stack(const std::string& system_name, stack_data.scscf_uri = (pjsip_sip_uri*)PJUtils::uri_from_string(scscf_uri, stack_data.pool); + return status; +} + +pj_status_t start_stack(std::set sproutlet_ports, + const std::string& sprout_hostname, + const std::string& alias_hosts, + QuiescingManager *quiescing_mgr_arg, + std::vector sproutlet_uris) +{ + pj_status_t status; + pj_sockaddr pri_addr; + pj_sockaddr addr_list[16]; + unsigned addr_cnt = PJ_ARRAY_SIZE(addr_list); + unsigned i; + // Create listening transports for the ports whichtrusted and untrusted ports. stack_data.pcscf_trusted_tcp_factory = NULL; if (stack_data.pcscf_trusted_port != 0) @@ -769,13 +775,13 @@ pj_status_t init_stack(const std::string& system_name, // to be added in Record-Route. stack_data.name.push_back(stack_data.local_host); - if (strcmp(local_host_cstr, public_host_cstr)) + if (pj_strcmp(&stack_data.local_host, &stack_data.public_host)) { stack_data.name.push_back(stack_data.public_host); } // S-CSCF enabled with a specified URI, so add host name from the URI to hostnames. - if ((scscf_port != 0) && (stack_data.scscf_uri != NULL)) + if ((stack_data.scscf_port != 0) && (stack_data.scscf_uri != NULL)) { stack_data.name.push_back(stack_data.scscf_uri->host); } From 85a8a57263cf06b163ccef351852d9da49648796 Mon Sep 17 00:00:00 2001 From: Richard Whitehouse Date: Tue, 2 May 2017 13:52:55 +0000 Subject: [PATCH 5/5] Allow all sproutlets to register ports and URIs Previously only built in sproutlets could add URIs and ports to those that the stack used. --- include/sproutlet_options.h | 6 ------ src/main.cpp | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/include/sproutlet_options.h b/include/sproutlet_options.h index 2bd8150ba..188898217 100644 --- a/include/sproutlet_options.h +++ b/include/sproutlet_options.h @@ -142,14 +142,12 @@ { \ TRC_INFO(""#NAME_LOWER" enabled on %d", opt.port_##NAME_LOWER); \ opt.enabled_##NAME_LOWER = true; \ - opt.sproutlet_ports.insert(opt.port_##NAME_LOWER); \ } \ } \ else if (opt.port_##NAME_LOWER != 0) \ { \ TRC_INFO(""#NAME_LOWER" enabled on %d", opt.port_##NAME_LOWER); \ opt.enabled_##NAME_LOWER = true; \ - opt.sproutlet_ports.insert(opt.port_##NAME_LOWER); \ } \ \ if (!opt.set_prefix_##NAME_LOWER) \ @@ -178,10 +176,6 @@ TRC_ERROR(""#NAME_LOWER" enabled, but no "#NAME_LOWER" URI specified"); \ return 1; \ } \ - else \ - { \ - sproutlet_uris.push_back(opt.uri_##NAME_LOWER); \ - } \ } #endif diff --git a/src/main.cpp b/src/main.cpp index fbda2e452..d6e4f3555 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2182,6 +2182,23 @@ int main(int argc, char* argv[]) return 1; } + // Add all of the sproutlets to the list of sproutlet ports and URIs + for (Sproutlet* sproutlet : sproutlets) + { + int port = sproutlet->port(); + std::string uri = sproutlet->uri_as_str(); + + if (port != 0) + { + opt.sproutlet_ports.insert(port); + } + + if (uri != "") + { + sproutlet_uris.push_back(uri); + } + } + // Start the PJSIP stack and it's transports. These needs to // happen after we have loaded the sproutlets so they can adjust the // listening ports.