res_pjsip_session: Add ability to accept multiple sdp answers
[asterisk/asterisk.git] / res / res_pjsip / config_system.c
index 8c4c548..65e4e2c 100644 (file)
@@ -26,6 +26,7 @@
 #include "include/res_pjsip_private.h"
 #include "asterisk/threadpool.h"
 #include "asterisk/dns.h"
+#include "asterisk/res_pjsip_cli.h"
 
 #define TIMER_T1_MIN 100
 #define DEFAULT_TIMER_T1 500
@@ -49,6 +50,15 @@ struct system_config {
                /*! Maxumum number of threads in the threadpool */
                int max_size;
        } threadpool;
+       /*! Nonzero to disable switching from UDP to TCP transport */
+       unsigned int disable_tcp_switch;
+       /*!
+        * Although early media is enabled in pjproject by default, it's only
+        * enabled when the To tags are different. These options allow turning
+        * on or off the feature for different tags and same tags.
+        */
+       unsigned int follow_early_media_fork;
+       unsigned int accept_multiple_sdp_answers;
 };
 
 static struct ast_threadpool_options sip_threadpool_options = {
@@ -93,8 +103,19 @@ static int system_apply(const struct ast_sorcery *system_sorcery, void *obj)
        pjsip_cfg()->tsx.t1 = system->timert1;
        pjsip_cfg()->tsx.td = system->timerb;
 
+       pjsip_cfg()->endpt.follow_early_media_fork = system->follow_early_media_fork;
+#ifdef HAVE_PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS
+       pjsip_cfg()->endpt.accept_multiple_sdp_answers = system->accept_multiple_sdp_answers;
+#else
+       if (system->accept_multiple_sdp_answers) {
+               ast_log(LOG_WARNING,
+                       "The accept_multiple_sdp_answers flag is not supported in this version of pjproject. Ignoring\n");
+       }
+#endif
+
        if (system->compactheaders) {
                extern pj_bool_t pjsip_use_compact_form;
+
                pjsip_use_compact_form = PJ_TRUE;
        }
 
@@ -103,6 +124,43 @@ static int system_apply(const struct ast_sorcery *system_sorcery, void *obj)
        sip_threadpool_options.idle_timeout = system->threadpool.idle_timeout;
        sip_threadpool_options.max_size = system->threadpool.max_size;
 
+       pjsip_cfg()->endpt.disable_tcp_switch =
+               system->disable_tcp_switch ? PJ_TRUE : PJ_FALSE;
+
+       return 0;
+}
+
+static struct system_config *get_system_cfg(void)
+{
+       struct system_config *cfg;
+       struct ao2_container *systems;
+       systems = ast_sorcery_retrieve_by_fields(system_sorcery, "system",
+               AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
+
+       if (!systems) {
+               return NULL;
+       }
+
+       cfg = ao2_find(systems, NULL, 0);
+       ao2_ref(systems, -1);
+       return cfg;
+}
+
+int sip_cli_print_system(struct ast_sip_cli_context *context)
+{
+       struct system_config *cfg = get_system_cfg();
+
+       if (!cfg) {
+               cfg = ast_sorcery_alloc(system_sorcery, "system", NULL);
+               if (!cfg) {
+                       return -1;
+               }
+       }
+
+       ast_str_append(&context->output_buffer, 0, "\nSystem Settings:\n\n");
+       ast_sip_cli_print_sorcery_objectset(cfg, context, 0);
+
+       ao2_ref(cfg, -1);
        return 0;
 }
 
@@ -117,8 +175,6 @@ int ast_sip_initialize_system(void)
                return -1;
        }
 
-       ast_sorcery_apply_config(system_sorcery, "res_pjsip");
-
        ast_sorcery_apply_default(system_sorcery, "system", "config", "pjsip.conf,criteria=type=system");
 
        if (ast_sorcery_object_register_no_reload(system_sorcery, "system", system_alloc, NULL, system_apply)) {
@@ -141,8 +197,14 @@ int ast_sip_initialize_system(void)
                        OPT_UINT_T, 0, FLDSET(struct system_config, threadpool.auto_increment));
        ast_sorcery_object_field_register(system_sorcery, "system", "threadpool_idle_timeout", "60",
                        OPT_UINT_T, 0, FLDSET(struct system_config, threadpool.idle_timeout));
-       ast_sorcery_object_field_register(system_sorcery, "system", "threadpool_max_size", "0",
+       ast_sorcery_object_field_register(system_sorcery, "system", "threadpool_max_size", "50",
                        OPT_UINT_T, 0, FLDSET(struct system_config, threadpool.max_size));
+       ast_sorcery_object_field_register(system_sorcery, "system", "disable_tcp_switch", "yes",
+                       OPT_BOOL_T, 1, FLDSET(struct system_config, disable_tcp_switch));
+       ast_sorcery_object_field_register(system_sorcery, "system", "follow_early_media_fork", "yes",
+                       OPT_BOOL_T, 1, FLDSET(struct system_config, follow_early_media_fork));
+       ast_sorcery_object_field_register(system_sorcery, "system", "accept_multiple_sdp_answers", "no",
+                       OPT_BOOL_T, 1, FLDSET(struct system_config, accept_multiple_sdp_answers));
 
        ast_sorcery_load(system_sorcery);
 
@@ -201,6 +263,7 @@ static int system_create_resolver_and_set_nameservers(void *data)
                status = pjsip_endpt_create_resolver(ast_sip_get_pjsip_endpoint(), &resolver);
                if (status != PJ_SUCCESS) {
                        ast_log(LOG_ERROR, "Could not create DNS resolver(%d), resorting to system resolution\n", status);
+                       ao2_ref(discovered_nameservers, -1);
                        return 0;
                }
        }
@@ -240,5 +303,5 @@ static int system_create_resolver_and_set_nameservers(void *data)
 
 void ast_sip_initialize_dns(void)
 {
-       ast_sip_push_task_synchronous(NULL, system_create_resolver_and_set_nameservers, NULL);
-}
\ No newline at end of file
+       ast_sip_push_task_wait_servant(NULL, system_create_resolver_and_set_nameservers, NULL);
+}