Newer
Older
34001
34002
34003
34004
34005
34006
34007
34008
34009
34010
34011
34012
34013
34014
34015
34016
34017
34018
34019
34020
34021
34022
34023
34024
34025
34026
34027
34028
34029
34030
34031
34032
34033
34034
34035
34036
34037
34038
34039
34040
34041
34042
34043
34044
34045
34046
34047
34048
int res;
#define CHECK_RESULTS(in, expected_res, expected_start, expected_len) do { \
input = (in); \
res = get_in_brackets_const(input, &start, &len); \
if ((expected_res) != res) { \
ast_test_status_update(test, "Unexpected result: %d != %d\n", expected_res, res); \
return AST_TEST_FAIL; \
} \
if ((expected_start) != start) { \
const char *e = expected_start ? expected_start : "(null)"; \
const char *a = start ? start : "(null)"; \
ast_test_status_update(test, "Unexpected start: %s != %s\n", e, a); \
return AST_TEST_FAIL; \
} \
if ((expected_len) != len) { \
ast_test_status_update(test, "Unexpected len: %d != %d\n", expected_len, len); \
return AST_TEST_FAIL; \
} \
} while(0)
switch (cmd) {
case TEST_INIT:
info->name = __func__;
info->category = "/channels/chan_sip/";
info->summary = "get_in_brackets_const test";
info->description =
"Tests the get_in_brackets_const function";
return AST_TEST_NOT_RUN;
case TEST_EXECUTE:
break;
}
CHECK_RESULTS("", 1, NULL, -1);
CHECK_RESULTS("normal <test>", 0, input + 8, 4);
CHECK_RESULTS("\"normal\" <test>", 0, input + 10, 4);
CHECK_RESULTS("not normal <test", -1, NULL, -1);
CHECK_RESULTS("\"yes < really\" <test>", 0, input + 16, 4);
CHECK_RESULTS("\"even > this\" <test>", 0, input + 15, 4);
CHECK_RESULTS("<sip:id1@10.10.10.10;lr>", 0, input + 1, 22);
CHECK_RESULTS("<sip:id1@10.10.10.10;lr>, <sip:id1@10.10.10.20;lr>", 0, input + 1, 22);
CHECK_RESULTS("<sip:id1,id2@10.10.10.10;lr>", 0, input + 1, 26);
CHECK_RESULTS("<sip:id1@10., <sip:id2@10.10.10.10;lr>", 0, input + 1, 36);
CHECK_RESULTS("\"quoted text\" <sip:dlg1@10.10.10.10;lr>", 0, input + 15, 23);
return AST_TEST_PASS;
}
34049
34050
34051
34052
34053
34054
34055
34056
34057
34058
34059
34060
34061
34062
34063
34064
34065
34066
34067
34068
34069
34070
34071
34072
34073
34074
34075
34076
34077
34078
#endif
#define DATA_EXPORT_SIP_PEER(MEMBER) \
MEMBER(sip_peer, name, AST_DATA_STRING) \
MEMBER(sip_peer, secret, AST_DATA_PASSWORD) \
MEMBER(sip_peer, md5secret, AST_DATA_PASSWORD) \
MEMBER(sip_peer, remotesecret, AST_DATA_PASSWORD) \
MEMBER(sip_peer, context, AST_DATA_STRING) \
MEMBER(sip_peer, subscribecontext, AST_DATA_STRING) \
MEMBER(sip_peer, username, AST_DATA_STRING) \
MEMBER(sip_peer, accountcode, AST_DATA_STRING) \
MEMBER(sip_peer, tohost, AST_DATA_STRING) \
MEMBER(sip_peer, regexten, AST_DATA_STRING) \
MEMBER(sip_peer, fromuser, AST_DATA_STRING) \
MEMBER(sip_peer, fromdomain, AST_DATA_STRING) \
MEMBER(sip_peer, fullcontact, AST_DATA_STRING) \
MEMBER(sip_peer, cid_num, AST_DATA_STRING) \
MEMBER(sip_peer, cid_name, AST_DATA_STRING) \
MEMBER(sip_peer, vmexten, AST_DATA_STRING) \
MEMBER(sip_peer, language, AST_DATA_STRING) \
MEMBER(sip_peer, mohinterpret, AST_DATA_STRING) \
MEMBER(sip_peer, mohsuggest, AST_DATA_STRING) \
MEMBER(sip_peer, parkinglot, AST_DATA_STRING) \
MEMBER(sip_peer, useragent, AST_DATA_STRING) \
MEMBER(sip_peer, mwi_from, AST_DATA_STRING) \
MEMBER(sip_peer, engine, AST_DATA_STRING) \
MEMBER(sip_peer, unsolicited_mailbox, AST_DATA_STRING) \
MEMBER(sip_peer, is_realtime, AST_DATA_BOOLEAN) \
MEMBER(sip_peer, host_dynamic, AST_DATA_BOOLEAN) \
MEMBER(sip_peer, autoframing, AST_DATA_BOOLEAN) \
MEMBER(sip_peer, inuse, AST_DATA_INTEGER) \
MEMBER(sip_peer, ringing, AST_DATA_INTEGER) \
MEMBER(sip_peer, onhold, AST_DATA_INTEGER) \
MEMBER(sip_peer, call_limit, AST_DATA_INTEGER) \
MEMBER(sip_peer, t38_maxdatagram, AST_DATA_INTEGER) \
MEMBER(sip_peer, maxcallbitrate, AST_DATA_INTEGER) \
MEMBER(sip_peer, rtptimeout, AST_DATA_SECONDS) \
MEMBER(sip_peer, rtpholdtimeout, AST_DATA_SECONDS) \
MEMBER(sip_peer, rtpkeepalive, AST_DATA_SECONDS) \
MEMBER(sip_peer, lastms, AST_DATA_MILLISECONDS) \
MEMBER(sip_peer, maxms, AST_DATA_MILLISECONDS) \
MEMBER(sip_peer, qualifyfreq, AST_DATA_MILLISECONDS) \
MEMBER(sip_peer, timer_t1, AST_DATA_MILLISECONDS) \
MEMBER(sip_peer, timer_b, AST_DATA_MILLISECONDS) \
MEMBER(sip_peer, description, AST_DATA_STRING)
34094
34095
34096
34097
34098
34099
34100
34101
34102
34103
34104
34105
34106
34107
34108
34109
34110
34111
34112
34113
34114
34115
34116
34117
34118
34119
34120
34121
34122
AST_DATA_STRUCTURE(sip_peer, DATA_EXPORT_SIP_PEER);
static int peers_data_provider_get(const struct ast_data_search *search,
struct ast_data *data_root)
{
struct sip_peer *peer;
struct ao2_iterator i;
struct ast_data *data_peer, *data_peer_mailboxes = NULL, *data_peer_mailbox, *enum_node;
struct ast_data *data_sip_options;
int total_mailboxes, x;
struct sip_mailbox *mailbox;
i = ao2_iterator_init(peers, 0);
while ((peer = ao2_iterator_next(&i))) {
ao2_lock(peer);
data_peer = ast_data_add_node(data_root, "peer");
if (!data_peer) {
ao2_unlock(peer);
ao2_ref(peer, -1);
continue;
}
ast_data_add_structure(sip_peer, data_peer, peer);
/* transfer mode */
enum_node = ast_data_add_node(data_peer, "allowtransfer");
if (!enum_node) {
ao2_unlock(peer);
ao2_ref(peer, -1);
34125
34126
34127
34128
34129
34130
34131
34132
34133
34134
34135
34136
34137
34138
34139
34140
34141
34142
34143
34144
34145
34146
34147
34148
34149
34150
34151
34152
34153
34154
34155
34156
continue;
}
ast_data_add_str(enum_node, "text", transfermode2str(peer->allowtransfer));
ast_data_add_int(enum_node, "value", peer->allowtransfer);
/* transports */
ast_data_add_str(data_peer, "transports", get_transport_list(peer->transports));
/* peer type */
if ((peer->type & SIP_TYPE_USER) && (peer->type & SIP_TYPE_PEER)) {
ast_data_add_str(data_peer, "type", "friend");
} else if (peer->type & SIP_TYPE_PEER) {
ast_data_add_str(data_peer, "type", "peer");
} else if (peer->type & SIP_TYPE_USER) {
ast_data_add_str(data_peer, "type", "user");
}
/* mailboxes */
total_mailboxes = 0;
AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) {
if (!total_mailboxes) {
data_peer_mailboxes = ast_data_add_node(data_peer, "mailboxes");
if (!data_peer_mailboxes) {
break;
}
total_mailboxes++;
}
data_peer_mailbox = ast_data_add_node(data_peer_mailboxes, "mailbox");
if (!data_peer_mailbox) {
continue;
}
Richard Mudgett
committed
ast_data_add_str(data_peer_mailbox, "id", mailbox->id);
}
/* amaflags */
enum_node = ast_data_add_node(data_peer, "amaflags");
if (!enum_node) {
ao2_unlock(peer);
ao2_ref(peer, -1);
continue;
}
ast_data_add_int(enum_node, "value", peer->amaflags);
ast_data_add_str(enum_node, "text", ast_channel_amaflags2string(peer->amaflags));
/* sip options */
data_sip_options = ast_data_add_node(data_peer, "sipoptions");
if (!data_sip_options) {
ao2_unlock(peer);
ao2_ref(peer, -1);
continue;
}
for (x = 0 ; x < ARRAY_LEN(sip_options); x++) {
ast_data_add_bool(data_sip_options, sip_options[x].text, peer->sipoptions & sip_options[x].id);
}
/* callingpres */
enum_node = ast_data_add_node(data_peer, "callingpres");
if (!enum_node) {
ao2_unlock(peer);
ao2_ref(peer, -1);
continue;
}
ast_data_add_int(enum_node, "value", peer->callingpres);
ast_data_add_str(enum_node, "text", ast_describe_caller_presentation(peer->callingpres));
/* codecs */
ast_data_add_codecs(data_peer, "codecs", peer->caps);
34193
34194
34195
34196
34197
34198
34199
34200
34201
34202
34203
34204
34205
34206
34207
34208
34209
34210
34211
34212
34213
34214
if (!ast_data_search_match(search, data_peer)) {
ast_data_remove_node(data_root, data_peer);
}
ao2_unlock(peer);
ao2_ref(peer, -1);
}
ao2_iterator_destroy(&i);
return 0;
}
static const struct ast_data_handler peers_data_provider = {
.version = AST_DATA_HANDLER_VERSION,
.get = peers_data_provider_get
};
static const struct ast_data_entry sip_data_providers[] = {
AST_DATA_ENTRY("asterisk/channel/sip/peers", &peers_data_provider),
};
static const struct ast_sip_api_tech chan_sip_api_provider = {
.version = AST_SIP_API_VERSION,
.name = "chan_sip",
.sipinfo_send = sipinfo_send,
};
static int unload_module(void);
/*!
* \brief Load the module
*
* Module loading including tests for configuration or dependencies.
* This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
* or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
Matthew Jordan
committed
* tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
* configuration file or other non-critical problem return
* AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
*/
static int load_module(void)
Olle Johansson
committed
ast_verbose("SIP channel loading...\n");
if (STASIS_MESSAGE_TYPE_INIT(session_timeout_type)) {
unload_module();
return AST_MODULE_LOAD_FAILURE;
}
if (!(sip_tech.capabilities = ast_format_cap_alloc(0))) {
unload_module();
return AST_MODULE_LOAD_FAILURE;
}
if (ast_sip_api_provider_register(&chan_sip_api_provider)) {
unload_module();
return AST_MODULE_LOAD_FAILURE;
}
/* the fact that ao2_containers can't resize automatically is a major worry! */
/* if the number of objects gets above MAX_XXX_BUCKETS, things will slow down */
peers = ao2_t_container_alloc(HASH_PEER_SIZE, peer_hash_cb, peer_cmp_cb, "allocate peers");
peers_by_ip = ao2_t_container_alloc(HASH_PEER_SIZE, peer_iphash_cb, peer_ipcmp_cb, "allocate peers_by_ip");
dialogs = ao2_t_container_alloc(HASH_DIALOG_SIZE, dialog_hash_cb, dialog_cmp_cb, "allocate dialogs");
dialogs_needdestroy = ao2_t_container_alloc(1, NULL, NULL, "allocate dialogs_needdestroy");
Stefan Schmidt
committed
dialogs_rtpcheck = ao2_t_container_alloc(HASH_DIALOG_SIZE, dialog_hash_cb, dialog_cmp_cb, "allocate dialogs for rtpchecks");
threadt = ao2_t_container_alloc(HASH_DIALOG_SIZE, threadt_hash_cb, threadt_cmp_cb, "allocate threadt table");
if (!peers || !peers_by_ip || !dialogs || !dialogs_needdestroy || !dialogs_rtpcheck
|| !threadt) {
ast_log(LOG_ERROR, "Unable to create primary SIP container(s)\n");
unload_module();
return AST_MODULE_LOAD_FAILURE;
}
if (!(sip_cfg.caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
unload_module();
return AST_MODULE_LOAD_FAILURE;
}
ast_format_cap_append_by_type(sip_tech.capabilities, AST_MEDIA_TYPE_AUDIO);
registry_list = ao2_t_container_alloc(HASH_REGISTRY_SIZE, registry_hash_cb, registry_cmp_cb, "allocate registry_list");
subscription_mwi_list = ao2_t_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX,
AO2_CONTAINER_ALLOC_OPT_INSERT_BEGIN, NULL, NULL, "allocate subscription_mwi_list");
if (!(sched = ast_sched_context_create())) {
ast_log(LOG_ERROR, "Unable to create scheduler context\n");
unload_module();
return AST_MODULE_LOAD_FAILURE;
if (!(io = io_context_create())) {
ast_log(LOG_ERROR, "Unable to create I/O context\n");
unload_module();
return AST_MODULE_LOAD_FAILURE;
sip_reloadreason = CHANNEL_MODULE_LOAD;
can_parse_xml = sip_is_xml_parsable();
if (reload_config(sip_reloadreason)) { /* Load the configuration from sip.conf */
unload_module();
return AST_MODULE_LOAD_DECLINE;
/* Initialize bogus peer. Can be done first after reload_config() */
if (!(bogus_peer = temp_peer("(bogus_peer)"))) {
ast_log(LOG_ERROR, "Unable to create bogus_peer for authentication\n");
unload_module();
return AST_MODULE_LOAD_FAILURE;
}
/* Make sure the auth will always fail. */
ast_string_field_set(bogus_peer, md5secret, BOGUS_PEER_MD5SECRET);
ast_clear_flag(&bogus_peer->flags[0], SIP_INSECURE);
/* Prepare the version that does not require DTMF BEGIN frames.
Kevin P. Fleming
committed
* We need to use tricks such as memcpy and casts because the variable
* has const fields.
*/
memcpy(&sip_tech_info, &sip_tech, sizeof(sip_tech));
Kevin P. Fleming
committed
memset((void *) &sip_tech_info.send_digit_begin, 0, sizeof(sip_tech_info.send_digit_begin));
if (ast_msg_tech_register(&sip_msg_tech)) {
unload_module();
return AST_MODULE_LOAD_FAILURE;
}
/* Make sure we can register our sip channel type */
if (ast_channel_register(&sip_tech)) {
ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n");
unload_module();
return AST_MODULE_LOAD_FAILURE;
#ifdef TEST_FRAMEWORK
AST_TEST_REGISTER(test_sip_peers_get);
AST_TEST_REGISTER(test_sip_mwi_subscribe_parse);
AST_TEST_REGISTER(test_tcp_message_fragmentation);
AST_TEST_REGISTER(get_in_brackets_const_test);
#endif
/* Register AstData providers */
ast_data_register_multiple(sip_data_providers, ARRAY_LEN(sip_data_providers));
/* Register all CLI functions for SIP */
ast_cli_register_multiple(cli_sip, ARRAY_LEN(cli_sip));
Kevin P. Fleming
committed
/* Tell the RTP engine about our RTP glue */
ast_rtp_glue_register(&sip_rtp_glue);
/* Register dialplan applications */
ast_register_application_xml(app_dtmfmode, sip_dtmfmode);
ast_register_application_xml(app_sipaddheader, sip_addheader);
ast_register_application_xml(app_sipremoveheader, sip_removeheader);
#ifdef TEST_FRAMEWORK
ast_register_application_xml(app_sipsendcustominfo, sip_sendcustominfo);
#endif
/* Register dialplan functions */
ast_custom_function_register(&sip_header_function);
ast_custom_function_register(&sippeer_function);
ast_custom_function_register(&checksipdomain_function);
/* Register manager commands */
ast_manager_register_xml("SIPpeers", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_show_peers);
ast_manager_register_xml("SIPshowpeer", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_show_peer);
ast_manager_register_xml("SIPqualifypeer", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_qualify_peer);
ast_manager_register_xml("SIPshowregistry", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_show_registry);
ast_manager_register_xml("SIPnotify", EVENT_FLAG_SYSTEM, manager_sipnotify);
ast_manager_register_xml("SIPpeerstatus", EVENT_FLAG_SYSTEM, manager_sip_peer_status);
sip_poke_all_peers();
sip_keepalive_all_peers();
sip_send_all_registers();
sip_send_all_mwi_subscriptions();
if (sip_epa_register(&cc_epa_static_data)) {
unload_module();
return AST_MODULE_LOAD_DECLINE;
}
if (sip_reqresp_parser_init() == -1) {
ast_log(LOG_ERROR, "Unable to initialize the SIP request and response parser\n");
unload_module();
return AST_MODULE_LOAD_DECLINE;
}
if (can_parse_xml) {
/* SIP CC agents require the ability to parse XML PIDF bodies
* in incoming PUBLISH requests
*/
if (ast_cc_agent_register(&sip_cc_agent_callbacks)) {
unload_module();
return AST_MODULE_LOAD_DECLINE;
}
}
if (ast_cc_monitor_register(&sip_cc_monitor_callbacks)) {
unload_module();
return AST_MODULE_LOAD_DECLINE;
}
if (!(sip_monitor_instances = ao2_container_alloc(37, sip_monitor_instance_hash_fn, sip_monitor_instance_cmp_fn))) {
unload_module();
return AST_MODULE_LOAD_DECLINE;
}
/* And start the monitor for the first time */
restart_monitor();
Tilghman Lesher
committed
ast_realtime_require_field(ast_check_realtime("sipregs") ? "sipregs" : "sippeers",
"name", RQ_CHAR, 10,
"ipaddr", RQ_CHAR, INET6_ADDRSTRLEN - 1,
"port", RQ_UINTEGER2, 5,
"regseconds", RQ_INTEGER4, 11,
Tilghman Lesher
committed
"defaultuser", RQ_CHAR, 10,
"fullcontact", RQ_CHAR, 35,
Tilghman Lesher
committed
"regserver", RQ_CHAR, 20,
"useragent", RQ_CHAR, 20,
SENTINEL);
Tilghman Lesher
committed
sip_register_tests();
network_change_stasis_subscribe();
ast_websocket_add_protocol("sip", sip_websocket_callback);
return AST_MODULE_LOAD_SUCCESS;
static int unload_module(void)
struct sip_pvt *p;
struct ast_context *con;
struct ao2_iterator i;
ast_sip_api_provider_unregister();
ast_websocket_remove_protocol("sip", sip_websocket_callback);
network_change_stasis_unsubscribe();
acl_change_event_stasis_unsubscribe();
ast_sched_dump(sched);
Matthew Jordan
committed
/* First, take us out of the channel type list */
ast_channel_unregister(&sip_tech);
ast_msg_tech_unregister(&sip_msg_tech);
ast_custom_function_unregister(&sippeer_function);
Kevin P. Fleming
committed
ast_custom_function_unregister(&sip_header_function);
ast_custom_function_unregister(&checksipdomain_function);
Kevin P. Fleming
committed
/* Unregister dial plan applications */
Olle Johansson
committed
ast_unregister_application(app_sipaddheader);
ast_unregister_application(app_sipremoveheader);
#ifdef TEST_FRAMEWORK
ast_unregister_application(app_sipsendcustominfo);
AST_TEST_UNREGISTER(test_sip_peers_get);
AST_TEST_UNREGISTER(test_sip_mwi_subscribe_parse);
AST_TEST_UNREGISTER(test_tcp_message_fragmentation);
AST_TEST_UNREGISTER(get_in_brackets_const_test);
#endif
/* Unregister all the AstData providers */
ast_data_unregister(NULL);
ast_cli_unregister_multiple(cli_sip, ARRAY_LEN(cli_sip));
/* Disconnect from RTP engine */
ast_rtp_glue_unregister(&sip_rtp_glue);
ast_manager_unregister("SIPpeers");
ast_manager_unregister("SIPshowpeer");
ast_manager_unregister("SIPqualifypeer");
ast_manager_unregister("SIPshowregistry");
ast_manager_unregister("SIPnotify");
ast_manager_unregister("SIPpeerstatus");
Matthew Jordan
committed
/* Kill TCP/TLS server threads */
ast_tcptls_server_stop(&sip_tcp_desc);
ast_tcptls_server_stop(&sip_tls_desc);
ast_ssl_teardown(sip_tls_desc.tls_cfg);
/* Kill all existing TCP/TLS threads */
i = ao2_iterator_init(threadt, 0);
while ((th = ao2_t_iterator_next(&i, "iterate through tcp threads for 'sip show tcp'"))) {
pthread_t thread = th->threadid;
th->stop = 1;
pthread_kill(thread, SIGURG);
ao2_t_ref(th, -1, "decrement ref from iterator");
ao2_iterator_destroy(&i);
Olle Johansson
committed
/* Hangup all dialogs if they have an owner */
i = ao2_iterator_init(dialogs, 0);
while ((p = ao2_t_iterator_next(&i, "iterate thru dialogs"))) {
if (p->owner)
ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
ao2_t_ref(p, -1, "toss dialog ptr from iterator_next");
ao2_iterator_destroy(&i);
unlink_all_peers_from_tables();
ast_mutex_lock(&monlock);
if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
pthread_t th = monitor_thread;
monitor_thread = AST_PTHREADT_STOP;
pthread_cancel(th);
pthread_kill(th, SIGURG);
ast_mutex_unlock(&monlock);
pthread_join(th, NULL);
} else {
monitor_thread = AST_PTHREADT_STOP;
ast_mutex_unlock(&monlock);
Olle Johansson
committed
/* Destroy all the dialogs and free their memory */
i = ao2_iterator_init(dialogs, 0);
while ((p = ao2_t_iterator_next(&i, "iterate thru dialogs"))) {
dialog_unlink_all(p);
ao2_t_ref(p, -1, "throw away iterator result");
}
ao2_iterator_destroy(&i);
Mark Spencer
committed
/* Free memory for local network address mask */
ast_mutex_lock(&authl_lock);
if (authl) {
ao2_t_cleanup(authl, "Removing global authentication");
authl = NULL;
}
ast_mutex_unlock(&authl_lock);
sip_epa_unregister_all();
ast_free(default_tls_cfg.certfile);
ast_free(default_tls_cfg.pvtfile);
ast_free(default_tls_cfg.cipher);
ast_free(default_tls_cfg.cafile);
ast_free(default_tls_cfg.capath);
{
struct ao2_iterator iter;
struct sip_subscription_mwi *iterator;
iter = ao2_iterator_init(subscription_mwi_list, 0);
while ((iterator = ao2_t_iterator_next(&iter, "unload_module iter"))) {
ao2_lock(iterator);
if (iterator->dnsmgr) {
ast_dnsmgr_release(iterator->dnsmgr);
iterator->dnsmgr = NULL;
ao2_t_ref(iterator, -1, "dnsmgr release");
}
ao2_unlock(iterator);
ao2_t_ref(iterator, -1, "unload_module iter");
ao2_iterator_destroy(&iter);
}
ao2_cleanup(subscription_mwi_list);
/*
* Wait awhile for the TCP/TLS thread container to become empty.
*
* XXX This is a hack, but the worker threads cannot be created
* joinable. They can die on their own and remove themselves
* from the container thus resulting in a huge memory leak.
*/
wait_count = 1000;
while (ao2_container_count(threadt) && --wait_count) {
sched_yield();
}
if (!wait_count) {
ast_debug(2, "TCP/TLS thread container did not become empty :(\n");
}
ao2_t_cleanup(bogus_peer, "unref the bogus_peer");
ao2_t_cleanup(peers, "unref the peers table");
ao2_t_cleanup(peers_by_ip, "unref the peers_by_ip table");
ao2_t_cleanup(dialogs, "unref the dialogs table");
ao2_t_cleanup(dialogs_needdestroy, "unref dialogs_needdestroy");
ao2_t_cleanup(dialogs_rtpcheck, "unref dialogs_rtpcheck");
ao2_t_cleanup(threadt, "unref the thread table");
ao2_t_cleanup(sip_monitor_instances, "unref the sip_monitor_instances table");
clear_sip_domains();
sip_cfg.contact_acl = ast_free_acl_list(sip_cfg.contact_acl);
if (sipsock_read_id) {
ast_io_remove(io, sipsock_read_id);
sipsock_read_id = NULL;
}
close(sipsock);
ast_sched_context_destroy(sched);
con = ast_context_find(used_context);
ast_context_destroy(con, "SIP");
Tilghman Lesher
committed
ast_unload_realtime("sipregs");
ast_unload_realtime("sippeers");
ast_cc_monitor_unregister(&sip_cc_monitor_callbacks);
ast_cc_agent_unregister(&sip_cc_agent_callbacks);
sip_unregister_tests();
if (notify_types) {
ast_config_destroy(notify_types);
notify_types = NULL;
}
ao2_cleanup(sip_tech.capabilities);
sip_tech.capabilities = NULL;
ao2_cleanup(sip_cfg.caps);
sip_cfg.caps = NULL;
STASIS_MESSAGE_TYPE_CLEANUP(session_timeout_type);
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Session Initiation Protocol (SIP)",
Mark Michelson
committed
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
.reload = reload,
Tilghman Lesher
committed
.load_pri = AST_MODPRI_CHANNEL_DRIVER,
Richard Mudgett
committed
.nonoptreq = "res_crypto,res_http_websocket",