Skip to content
Snippets Groups Projects
res_pjsip.c 80.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • 
    void *ast_sip_dict_set(pj_pool_t* pool, void *ht,
    		       const char *key, void *val)
    {
    	if (!ht) {
    		ht = pj_hash_create(pool, 11);
    	}
    
    	pj_hash_set(pool, ht, key, PJ_HASH_KEY_STRING, 0, val);
    
    	return ht;
    }
    
    
    static void remove_request_headers(pjsip_endpoint *endpt)
    {
    	const pjsip_hdr *request_headers = pjsip_endpt_get_request_headers(endpt);
    	pjsip_hdr *iter = request_headers->next;
    
    	while (iter != request_headers) {
    		pjsip_hdr *to_erase = iter;
    		iter = iter->next;
    		pj_list_erase(to_erase);
    	}
    }
    
    
    static int load_module(void)
    {
    
    	/* The third parameter is just copied from
    	 * example code from PJLIB. This can be adjusted
    	 * if necessary.
    
    	 */
    	pj_status_t status;
    
    	struct ast_threadpool_options options;
    
    
    	if (pj_init() != PJ_SUCCESS) {
    		return AST_MODULE_LOAD_DECLINE;
    	}
    
    	if (pjlib_util_init() != PJ_SUCCESS) {
    		pj_shutdown();
    		return AST_MODULE_LOAD_DECLINE;
    	}
    
    	pj_caching_pool_init(&caching_pool, NULL, 1024 * 1024);
    	if (pjsip_endpt_create(&caching_pool.factory, "SIP", &ast_pjsip_endpoint) != PJ_SUCCESS) {
    		ast_log(LOG_ERROR, "Failed to create PJSIP endpoint structure. Aborting load\n");
    
    		pj_caching_pool_destroy(&caching_pool);
    		return AST_MODULE_LOAD_DECLINE;
    
    
    	/* PJSIP will automatically try to add a Max-Forwards header. Since we want to control that,
    	 * we need to stop PJSIP from doing it automatically
    	 */
    	remove_request_headers(ast_pjsip_endpoint);
    
    
    	memory_pool = pj_pool_create(&caching_pool.factory, "SIP", 1024, 1024, NULL);
    	if (!memory_pool) {
    		ast_log(LOG_ERROR, "Failed to create memory pool for SIP. Aborting load\n");
    
    		pjsip_endpt_destroy(ast_pjsip_endpoint);
    		ast_pjsip_endpoint = NULL;
    		pj_caching_pool_destroy(&caching_pool);
    		return AST_MODULE_LOAD_DECLINE;
    
    	if (ast_sip_initialize_system()) {
    
    		ast_log(LOG_ERROR, "Failed to initialize SIP 'system' configuration section. Aborting load\n");
    
    		pj_pool_release(memory_pool);
    		memory_pool = NULL;
    		pjsip_endpt_destroy(ast_pjsip_endpoint);
    		ast_pjsip_endpoint = NULL;
    		pj_caching_pool_destroy(&caching_pool);
    		return AST_MODULE_LOAD_DECLINE;
    
    	sip_get_threadpool_options(&options);
    	options.thread_start = sip_thread_start;
    	sip_threadpool = ast_threadpool_create("SIP", NULL, &options);
    	if (!sip_threadpool) {
    		ast_log(LOG_ERROR, "Failed to create SIP threadpool. Aborting load\n");
    
    		pj_pool_release(memory_pool);
    		memory_pool = NULL;
    		pjsip_endpt_destroy(ast_pjsip_endpoint);
    		ast_pjsip_endpoint = NULL;
    		pj_caching_pool_destroy(&caching_pool);
    		return AST_MODULE_LOAD_DECLINE;
    
    	pjsip_tsx_layer_init_module(ast_pjsip_endpoint);
    	pjsip_ua_init_module(ast_pjsip_endpoint, NULL);
    
    	monitor_continue = 1;
    	status = pj_thread_create(memory_pool, "SIP", (pj_thread_proc *) &monitor_thread_exec,
    			NULL, PJ_THREAD_DEFAULT_STACK_SIZE * 2, 0, &monitor_thread);
    	if (status != PJ_SUCCESS) {
    		ast_log(LOG_ERROR, "Failed to start SIP monitor thread. Aborting load\n");
    
    		pj_pool_release(memory_pool);
    		memory_pool = NULL;
    		pjsip_endpt_destroy(ast_pjsip_endpoint);
    		ast_pjsip_endpoint = NULL;
    		pj_caching_pool_destroy(&caching_pool);
    		return AST_MODULE_LOAD_DECLINE;
    
    	ast_sip_initialize_global_headers();
    
    
    	if (ast_res_pjsip_initialize_configuration(ast_module_info)) {
    
    		ast_log(LOG_ERROR, "Failed to initialize SIP configuration. Aborting load\n");
    
    		ast_sip_destroy_global_headers();
    		stop_monitor_thread();
    		pj_pool_release(memory_pool);
    		memory_pool = NULL;
    		pjsip_endpt_destroy(ast_pjsip_endpoint);
    		ast_pjsip_endpoint = NULL;
    		pj_caching_pool_destroy(&caching_pool);
    		return AST_MODULE_LOAD_DECLINE;
    
    	}
    
    	if (ast_sip_initialize_distributor()) {
    		ast_log(LOG_ERROR, "Failed to register distributor module. Aborting load\n");
    
    		ast_res_pjsip_destroy_configuration();
    		ast_sip_destroy_global_headers();
    		stop_monitor_thread();
    		pj_pool_release(memory_pool);
    		memory_pool = NULL;
    		pjsip_endpt_destroy(ast_pjsip_endpoint);
    		ast_pjsip_endpoint = NULL;
    		pj_caching_pool_destroy(&caching_pool);
    		return AST_MODULE_LOAD_DECLINE;
    
    	}
    
    	if (ast_sip_initialize_outbound_authentication()) {
    		ast_log(LOG_ERROR, "Failed to initialize outbound authentication. Aborting load\n");
    
    		ast_sip_destroy_distributor();
    		ast_res_pjsip_destroy_configuration();
    		ast_sip_destroy_global_headers();
    		stop_monitor_thread();
    		pj_pool_release(memory_pool);
    		memory_pool = NULL;
    		pjsip_endpt_destroy(ast_pjsip_endpoint);
    		ast_pjsip_endpoint = NULL;
    		pj_caching_pool_destroy(&caching_pool);
    		return AST_MODULE_LOAD_DECLINE;
    
    	ast_res_pjsip_init_options_handling(0);
    
    	ast_module_ref(ast_module_info->self);
    
    }
    
    static int reload_module(void)
    {
    
    	if (ast_res_pjsip_reload_configuration()) {
    
    		return AST_MODULE_LOAD_DECLINE;
    	}
    
    	ast_res_pjsip_init_options_handling(1);
    
    	return 0;
    }
    
    static int unload_module(void)
    {
    
    	/* This will never get called as this module can't be unloaded */
    
    	return 0;
    }
    
    AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Basic SIP resource",
    		.load = load_module,
    		.unload = unload_module,
    		.reload = reload_module,
    
    		.load_pri = AST_MODPRI_CHANNEL_DEPEND - 5,