diff --git a/conf/freeswitch.xml b/conf/freeswitch.xml index cb52a04975..bcfcd6b66c 100644 --- a/conf/freeswitch.xml +++ b/conf/freeswitch.xml @@ -3,491 +3,507 @@
- - + + - - - + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - + + - + - - - + + + - - - + + + - - - - - - - + + + + + + + - + - - + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - + + + + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - + + + + + + + + + - + - - + + - + - - - - + + + + - + - - - - - + + + + + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - + + + + you need to really set them up --> - - - - - - - - - - - + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ "dialplan, caller_id_name, ani, ani2, caller_id_number, + network_addr, rdnis, destination_number, uuid, source, + context, chan_name" --> - - - + + + + + + + --> - - - + + + - - - + + + - - - + + + + you do not need any regex in the condition + + + --> +The first match will play a beep and the second one plays +the desired file. This is for demo purposes both actions +could have been under the same tag as well. + --> - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + +
@@ -495,16 +511,16 @@
- + - +
- + diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 0af98f0223..7ebe3f5dc2 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -39,13 +39,23 @@ #define HAVE_APR #include +struct outbound_reg; +typedef struct outbound_reg outbound_reg_t; + struct sofia_profile; typedef struct sofia_profile sofia_profile_t; #define NUA_MAGIC_T sofia_profile_t +struct sofia_private { + switch_core_session_t *session; + outbound_reg_t *oreg; +}; + +typedef struct sofia_private sofia_private_t; + struct private_object; typedef struct private_object private_object_t; -#define NUA_HMAGIC_T switch_core_session_t +#define NUA_HMAGIC_T sofia_private_t #define MY_EVENT_REGISTER "sofia::register" #define MY_EVENT_EXPIRE "sofia::expire" @@ -77,10 +87,6 @@ static char auth_sql[] = " expires INTEGER(8)" ");\n"; - - - - static const char modname[] = "mod_sofia"; #define STRLEN 15 @@ -133,6 +139,41 @@ static struct { switch_mutex_t *mutex; } globals; +typedef enum { + REG_FLAG_AUTHED = (1 << 0), +} reg_flags_t; + +typedef enum { + REG_STATE_UNREGED, + REG_STATE_TRYING, + REG_STATE_REGISTER, + REG_STATE_REGED, + REG_STATE_FAILED, + REG_STATE_EXPIRED +} reg_state_t; + +struct outbound_reg { + sofia_private_t sofia_private; + nua_handle_t *nh; + sofia_profile_t *profile; + char *name; + char *register_scheme; + char *register_realm; + char *register_username; + char *register_password; + char *register_from; + char *register_to; + char *register_proxy; + char *expires_str; + uint32_t freq; + time_t expires; + time_t retry; + uint32_t flags; + reg_state_t state; + switch_memory_pool_t *pool; + struct outbound_reg *next; +}; + struct sofia_profile { int debug; char *name; @@ -163,12 +204,14 @@ struct sofia_profile { sip_alias_node_t *aliases; switch_payload_t te; uint32_t codec_flags; - switch_mutex_t *reg_mutex; + switch_mutex_t *ireg_mutex; + switch_mutex_t *oreg_mutex; + outbound_reg_t *registrations; }; - struct private_object { + sofia_private_t sofia_private; uint32_t flags; switch_core_session_t *session; switch_frame_t read_frame; @@ -263,21 +306,21 @@ static void sip_i_state(int status, nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, - switch_core_session_t *session, + sofia_private_t *sofia_private, sip_t const *sip, tagi_t tags[]); static void sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, - switch_core_session_t *session, + sofia_private_t *sofia_private, sip_t const *sip, tagi_t tags[]); static void sip_i_register(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, - switch_core_session_t *session, + sofia_private_t *sofia_private, sip_t const *sip, tagi_t tags[]); @@ -287,7 +330,7 @@ static void event_callback(nua_event_t event, nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, - switch_core_session_t *session, + sofia_private_t *sofia_private, sip_t const *sip, tagi_t tags[]); @@ -356,7 +399,7 @@ static auth_res_t parse_auth(sofia_profile_t *profile, sip_authorization_t const } if (switch_strlen_zero(np)) { - if (!get_auth_data(profile->dbname, nonce, np, nplen, profile->reg_mutex)) { + if (!get_auth_data(profile->dbname, nonce, np, nplen, profile->ireg_mutex)) { ret = AUTH_STALE; goto end; } @@ -468,7 +511,7 @@ static void check_expire(sofia_profile_t *profile, time_t now) return; } - switch_mutex_lock(profile->reg_mutex); + switch_mutex_lock(profile->ireg_mutex); snprintf(sql, sizeof(sql), "select '%s',* from sip_registrations where expires > 0 and expires < %ld", profile->name, (long) now); switch_core_db_exec(db, sql, del_callback, NULL, &errmsg); @@ -482,7 +525,7 @@ static void check_expire(sofia_profile_t *profile, time_t now) switch_core_db_persistant_execute(db, sql, 25); snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and expires < %ld", (long) now); switch_core_db_persistant_execute(db, sql, 25); - switch_mutex_unlock(profile->reg_mutex); + switch_mutex_unlock(profile->ireg_mutex); switch_core_db_close(db); } @@ -500,7 +543,7 @@ static char *find_reg_url(sofia_profile_t *profile, char *user, char *host, char cbt.val = val; cbt.len = len; - switch_mutex_lock(profile->reg_mutex); + switch_mutex_lock(profile->ireg_mutex); if (host) { snprintf(val, len, "select contact from sip_registrations where user='%s' and host='%s'", user, host); } else { @@ -515,7 +558,7 @@ static char *find_reg_url(sofia_profile_t *profile, char *user, char *host, char errmsg = NULL; } - switch_mutex_unlock(profile->reg_mutex); + switch_mutex_unlock(profile->ireg_mutex); switch_core_db_close(db); return cbt.matches ? val : NULL; @@ -723,7 +766,8 @@ static void do_invite(switch_core_session_t *session) switch_set_flag_locked(tech_pvt, TFLAG_READY); tech_pvt->nh = nua_handle(tech_pvt->profile->nua, NULL, SIPTAG_TO_STR(tech_pvt->dest), TAG_END()); - nua_handle_bind(tech_pvt->nh, session); + tech_pvt->sofia_private.session = session; + nua_handle_bind(tech_pvt->nh, &tech_pvt->sofia_private); nua_invite(tech_pvt->nh, SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str), SOATAG_RTP_SORT(SOA_RTP_SORT_REMOTE), @@ -1593,7 +1637,7 @@ static void sip_i_state(int status, nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, - switch_core_session_t *session, + sofia_private_t *sofia_private, sip_t const *sip, tagi_t tags[]) @@ -1604,7 +1648,8 @@ static void sip_i_state(int status, int ss_state = nua_callstate_init; switch_channel_t *channel = NULL; private_object_t *tech_pvt = NULL; - + switch_core_session_t *session = sofia_private ? sofia_private->session : NULL; + tl_gets(tags, NUTAG_CALLSTATE_REF(ss_state), NUTAG_OFFER_RECV_REF(offer_recv), @@ -1842,7 +1887,6 @@ typedef enum { static uint8_t handle_register(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, - switch_core_session_t *session, sip_t const *sip, sofia_regtype_t regtype, char *key, @@ -1852,7 +1896,6 @@ static uint8_t handle_register(nua_t *nua, sip_expires_t const *expires = sip->sip_expires; sip_authorization_t const *authorization = sip->sip_authorization; sip_contact_t const *contact = sip->sip_contact; - switch_xml_t domain, xml, user, param; char params[1024] = ""; char *sql; @@ -1865,9 +1908,9 @@ static uint8_t handle_register(nua_t *nua, char *passwd = NULL; uint8_t stale = 0, ret = 0, forbidden = 0; auth_res_t auth_res; - long exptime = 60; + if (expires) { exptime = expires->ex_delta; } else if (contact->m_expires) { @@ -1979,7 +2022,7 @@ static uint8_t handle_register(nua_t *nua, } - execute_sql(profile->dbname, sql, profile->reg_mutex); + execute_sql(profile->dbname, sql, profile->ireg_mutex); switch_core_db_free(sql); switch_core_db_free(auth_str); ret = 1; @@ -2025,7 +2068,7 @@ static uint8_t handle_register(nua_t *nua, } if (sql) { - execute_sql(profile->dbname, sql, profile->reg_mutex); + execute_sql(profile->dbname, sql, profile->ireg_mutex); switch_core_db_free(sql); sql = NULL; } @@ -2051,17 +2094,17 @@ static uint8_t handle_register(nua_t *nua, static void sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, - switch_core_session_t *session, + sofia_private_t *sofia_private, sip_t const *sip, tagi_t tags[]) { - + switch_core_session_t *session = sofia_private ? sofia_private->session : NULL; char key[128] = ""; if (!session) { if ((profile->pflags & PFLAG_AUTH_CALLS)) { - if (handle_register(nua, profile, nh, session, sip, REG_INVITE, key, sizeof(key))) { + if (handle_register(nua, profile, nh, sip, REG_INVITE, key, sizeof(key))) { return; } } @@ -2119,7 +2162,8 @@ static void sip_i_invite(nua_t *nua, switch_channel_set_caller_profile(channel, tech_pvt->caller_profile); } switch_set_flag_locked(tech_pvt, TFLAG_INBOUND); - nua_handle_bind(nh, session); + tech_pvt->sofia_private.session = session; + nua_handle_bind(nh, &tech_pvt->sofia_private); } } } @@ -2127,25 +2171,94 @@ static void sip_i_invite(nua_t *nua, static void sip_i_register(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, - switch_core_session_t *session, + sofia_private_t *sofia_private, sip_t const *sip, tagi_t tags[]) { - handle_register(nua, profile, nh, session, sip, REG_REGISTER, NULL, 0); + //switch_core_session_t *session = sofia_private ? sofia_private->session : NULL; + handle_register(nua, profile, nh, sip, REG_REGISTER, NULL, 0); } -static void event_callback(nua_event_t event, - int status, - char const *phrase, - nua_t *nua, - sofia_profile_t *profile, + + +static void sip_r_register(int status, + char const *phrase, + nua_t *nua, + sofia_profile_t *profile, nua_handle_t *nh, - switch_core_session_t *session, - sip_t const *sip, - tagi_t tags[]) + sofia_private_t *sofia_private, + sip_t const *sip, + tagi_t tags[]) +{ + outbound_reg_t *oreg = NULL; + sip_www_authenticate_t const *authenticate = NULL; + + if (sofia_private) { + if (sofia_private->oreg) { + oreg = sofia_private->oreg; + } else if (profile) { + /* NOTE + this is a linked list, when nua_identity comes + we need to actually pick the right one... + */ + oreg = profile->registrations; + } + } + + if (!oreg) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No authentication available!\n"); + return; + } + + if (sip->sip_www_authenticate) { + authenticate = sip->sip_www_authenticate; + } else if (sip->sip_proxy_authenticate) { + authenticate = sip->sip_proxy_authenticate; + } + + if (authenticate) { + char const *realm = (char const *) *authenticate->au_params; + char const *scheme = (char const *) authenticate->au_scheme; + char authentication[256] = ""; + int ss_state; + + snprintf(authentication, sizeof(authentication), "%s:%s:%s:%s", scheme, strstr(realm, "=") + 1, + oreg->register_username, + oreg->register_password); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Authenticating '%s' with '%s'.\n", + profile->username, authentication); + + + ss_state = nua_callstate_authenticating; + + tl_gets(tags, + NUTAG_CALLSTATE_REF(ss_state), + SIPTAG_WWW_AUTHENTICATE_REF(authenticate), + TAG_END()); + + nua_authenticate(nh, NUTAG_AUTH(authentication), TAG_END()); + + } else if (status == 200) { + if (!sofia_private->session) { + oreg->state = REG_STATE_REGISTER; + } + } +} + +static void event_callback(nua_event_t event, + int status, + char const *phrase, + nua_t *nua, + sofia_profile_t *profile, + nua_handle_t *nh, + sofia_private_t *sofia_private, + sip_t const *sip, + tagi_t tags[]) { struct private_object *tech_pvt = NULL; auth_res_t auth_res = AUTH_FORBIDDEN; + switch_core_session_t *session = sofia_private ? sofia_private->session : NULL; if (session) { if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) { @@ -2184,107 +2297,104 @@ static void event_callback(nua_event_t event, switch (event) { case nua_r_shutdown: - //sip_r_shutdown(status, phrase, nua, profile, nh, session, sip, tags); + //sip_r_shutdown(status, phrase, nua, profile, nh, sofia_private, sip, tags); break; case nua_r_get_params: - //sip_r_get_params(status, phrase, nua, profile, nh, session, sip, tags); - break; - - case nua_r_register: - //sip_r_register(status, phrase, nua, profile, nh, session, sip, tags); - break; - - case nua_r_unregister: - //sip_r_unregister(status, phrase, nua, profile, nh, session, sip, tags); - break; - - case nua_r_options: - //sip_r_options(status, phrase, nua, profile, nh, session, sip, tags); + //sip_r_get_params(status, phrase, nua, profile, nh, sofia_private, sip, tags); break; case nua_r_invite: - //sip_r_invite(status, phrase, nua, profile, nh, session, sip, tags); + case nua_r_register: + sip_r_register(status, phrase, nua, profile, nh, sofia_private, sip, tags); + break; + + case nua_r_unregister: + //sip_r_unregister(status, phrase, nua, profile, nh, sofia_private, sip, tags); + break; + + case nua_r_options: + //sip_r_options(status, phrase, nua, profile, nh, sofia_private, sip, tags); break; case nua_i_fork: - //sip_i_fork(status, phrase, nua, profile, nh, session, sip, tags); + //sip_i_fork(status, phrase, nua, profile, nh, sofia_private, sip, tags); break; case nua_i_invite: - sip_i_invite(nua, profile, nh, session, sip, tags); + sip_i_invite(nua, profile, nh, sofia_private, sip, tags); break; case nua_i_register: - sip_i_register (nua, profile, nh, session, sip, tags); + sip_i_register (nua, profile, nh, sofia_private, sip, tags); break; case nua_i_prack: - //sip_i_prack(nua, profile, nh, session, sip, tags); + //sip_i_prack(nua, profile, nh, sofia_private, sip, tags); break; case nua_i_state: - sip_i_state(status, phrase, nua, profile, nh, session, sip, tags); + sip_i_state(status, phrase, nua, profile, nh, sofia_private, sip, tags); break; case nua_r_bye: - //sip_r_bye(status, phrase, nua, profile, nh, session, sip, tags); + //sip_r_bye(status, phrase, nua, profile, nh, sofia_private, sip, tags); break; case nua_i_bye: - //sip_i_bye(nua, profile, nh, session, sip, tags); + //sip_i_bye(nua, profile, nh, sofia_private, sip, tags); break; case nua_r_message: - //sip_r_message(status, phrase, nua, profile, nh, session, sip, tags); + //sip_r_message(status, phrase, nua, profile, nh, sofia_private, sip, tags); break; case nua_i_message: - //sip_i_message(nua, profile, nh, session, sip, tags); + //sip_i_message(nua, profile, nh, sofia_private, sip, tags); break; case nua_r_info: - //sip_r_info(status, phrase, nua, profile, nh, session, sip, tags); + //sip_r_info(status, phrase, nua, profile, nh, sofia_private, sip, tags); break; case nua_i_info: - //sip_i_info(nua, profile, nh, session, sip, tags); + //sip_i_info(nua, profile, nh, sofia_private, sip, tags); break; case nua_r_refer: - //sip_r_refer(status, phrase, nua, profile, nh, session, sip, tags); + //sip_r_refer(status, phrase, nua, profile, nh, sofia_private, sip, tags); break; case nua_i_refer: - //sip_i_refer(nua, profile, nh, session, sip, tags); + //sip_i_refer(nua, profile, nh, sofia_private, sip, tags); break; case nua_r_subscribe: - //sip_r_subscribe(status, phrase, nua, profile, nh, session, sip, tags); + //sip_r_subscribe(status, phrase, nua, profile, nh, sofia_private, sip, tags); break; case nua_r_unsubscribe: - //sip_r_unsubscribe(status, phrase, nua, profile, nh, session, sip, tags); + //sip_r_unsubscribe(status, phrase, nua, profile, nh, sofia_private, sip, tags); break; case nua_r_publish: - //sip_r_publish(status, phrase, nua, profile, nh, session, sip, tags); + //sip_r_publish(status, phrase, nua, profile, nh, sofia_private, sip, tags); break; case nua_r_notify: - //sip_r_notify(status, phrase, nua, profile, nh, session, sip, tags); + //sip_r_notify(status, phrase, nua, profile, nh, sofia_private, sip, tags); break; case nua_i_notify: - //sip_i_notify(nua, profile, nh, session, sip, tags); + //sip_i_notify(nua, profile, nh, sofia_private, sip, tags); break; case nua_i_cancel: - //sip_i_cancel(nua, profile, nh, session, sip, tags); + //sip_i_cancel(nua, profile, nh, sofia_private, sip, tags); break; case nua_i_error: - //sip_i_error(nua, profile, nh, session, status, phrase, tags); + //sip_i_error(nua, profile, nh, sofia_private, status, phrase, tags); break; case nua_i_active: @@ -2309,15 +2419,67 @@ static void event_callback(nua_event_t event, } } -#define REG_SECONDS 30 +static void check_oreg(sofia_profile_t *profile, time_t now) +{ + outbound_reg_t *oregp; + for (oregp = profile->registrations; oregp; oregp = oregp->next) { + int ss_state = nua_callstate_authenticating; + reg_state_t ostate = oregp->state; + + switch(ostate) { + case REG_STATE_REGISTER: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "registered %s\n", oregp->name); + oregp->expires = now + oregp->freq; + oregp->state = REG_STATE_REGED; + oregp->retry = 0; + break; + case REG_STATE_UNREGED: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "registering %s\n", oregp->name); + if ((oregp->nh = nua_handle(oregp->profile->nua, NULL, + NUTAG_URL(oregp->register_proxy), + SIPTAG_TO_STR(oregp->register_to), + NUTAG_CALLSTATE_REF(ss_state), + SIPTAG_FROM_STR(oregp->register_from), TAG_END()))) { + + oregp->sofia_private.oreg = oregp; + nua_handle_bind(oregp->nh, &oregp->sofia_private); + nua_register(oregp->nh, + SIPTAG_FROM_STR(oregp->register_from), + SIPTAG_CONTACT_STR(oregp->register_from), + SIPTAG_EXPIRES_STR(oregp->expires_str), + NUTAG_REGISTRAR(oregp->register_proxy), + TAG_NULL()); + oregp->state = REG_STATE_TRYING; + oregp->retry = now + 10; + } + break; + default: + if (oregp->retry && now >= oregp->retry) { + oregp->state = REG_STATE_UNREGED; + oregp->retry = 0; + } + if (oregp->expires && now >= oregp->expires) { + oregp->state = REG_STATE_UNREGED; + oregp->expires = 0; + } + break; + } + } + +} + +#define IREG_SECONDS 30 +#define OREG_SECONDS 1 static void *SWITCH_THREAD_FUNC profile_thread_run(switch_thread_t *thread, void *obj) { sofia_profile_t *profile = (sofia_profile_t *) obj; switch_memory_pool_t *pool; sip_alias_node_t *node; - uint32_t loops = 0; + uint32_t ireg_loops = 0; + uint32_t oreg_loops = 0; switch_core_db_t *db; + profile->s_root = su_root_create(NULL); profile->nua = nua_create(profile->s_root, /* Event loop */ event_callback, /* Callback for processing events */ @@ -2363,18 +2525,25 @@ static void *SWITCH_THREAD_FUNC profile_thread_run(switch_thread_t *thread, void } switch_core_db_close(db); - switch_mutex_init(&profile->reg_mutex, SWITCH_MUTEX_NESTED, profile->pool); + switch_mutex_init(&profile->ireg_mutex, SWITCH_MUTEX_NESTED, profile->pool); + switch_mutex_init(&profile->oreg_mutex, SWITCH_MUTEX_NESTED, profile->pool); switch_mutex_lock(globals.mutex); globals.running = 1; switch_mutex_unlock(globals.mutex); - loops = REG_SECONDS; + ireg_loops = IREG_SECONDS; + oreg_loops = OREG_SECONDS; while(globals.running == 1) { - if (++loops >= REG_SECONDS) { + if (++ireg_loops >= IREG_SECONDS) { check_expire(profile, time(NULL)); - loops = 0; + ireg_loops = 0; + } + + if (++oreg_loops >= OREG_SECONDS) { + check_oreg(profile, time(NULL)); + oreg_loops = 0; } su_root_step(profile->s_root, 1000); @@ -2411,8 +2580,10 @@ static void launch_profile_thread(sofia_profile_t *profile) static switch_status_t config_sofia(int reload) { char *cf = "sofia.conf"; - switch_xml_t cfg, xml = NULL, xprofile, param; + switch_xml_t cfg, xml = NULL, xprofile, param, settings, profiles, registration, registrations; switch_status_t status = SWITCH_STATUS_SUCCESS; + sofia_profile_t *profile = NULL; + char url[512] = ""; if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf); @@ -2420,150 +2591,233 @@ static switch_status_t config_sofia(int reload) goto done; } - for (xprofile = switch_xml_child(cfg, "profile"); xprofile; xprofile = xprofile->next) { - char *xprofilename = (char *) switch_xml_attr_soft(xprofile, "name"); - sofia_profile_t *profile; - switch_memory_pool_t *pool = NULL; - char url[512] = ""; + if ((profiles = switch_xml_child(cfg, "profiles"))) { + for (xprofile = switch_xml_child(profiles, "profile"); xprofile; xprofile = xprofile->next) { + if (!(settings = switch_xml_child(xprofile, "settings"))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Settings, check the new config!\n", cf); + } else { + char *xprofilename = (char *) switch_xml_attr_soft(xprofile, "name"); + switch_memory_pool_t *pool = NULL; - /* Setup the pool */ - if ((status = switch_core_new_memory_pool(&pool)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); - goto done; - } + + /* Setup the pool */ + if ((status = switch_core_new_memory_pool(&pool)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); + goto done; + } - if (!(profile = (sofia_profile_t *) switch_core_alloc(pool, sizeof(*profile)))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n"); - goto done; - } + if (!(profile = (sofia_profile_t *) switch_core_alloc(pool, sizeof(*profile)))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n"); + goto done; + } - if (!xprofilename) { - xprofilename = "unnamed"; - } + if (!xprofilename) { + xprofilename = "unnamed"; + } - profile->pool = pool; + profile->pool = pool; - profile->name = switch_core_strdup(profile->pool, xprofilename); - snprintf(url, sizeof(url), "sofia_reg_%s", xprofilename); - profile->dbname = switch_core_strdup(profile->pool, url); + profile->name = switch_core_strdup(profile->pool, xprofilename); + snprintf(url, sizeof(url), "sofia_reg_%s", xprofilename); + profile->dbname = switch_core_strdup(profile->pool, url); - profile->dtmf_duration = 100; - profile->codec_ms = 20; + profile->dtmf_duration = 100; + profile->codec_ms = 20; - for (param = switch_xml_child(xprofile, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); + for (param = switch_xml_child(settings, "param"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + char *val = (char *) switch_xml_attr_soft(param, "value"); - if (!strcasecmp(var, "debug")) { - profile->debug = atoi(val); - } else if (!strcasecmp(var, "use-rtp-timer") && switch_true(val)) { - switch_set_flag(profile, TFLAG_TIMER); - } else if (!strcasecmp(var, "rfc2833-pt")) { - profile->te = (switch_payload_t) atoi(val); - } else if (!strcasecmp(var, "sip-port")) { - profile->sip_port = atoi(val); - } else if (!strcasecmp(var, "vad")) { - if (!strcasecmp(val, "in")) { - switch_set_flag(profile, TFLAG_VAD_IN); - } else if (!strcasecmp(val, "out")) { - switch_set_flag(profile, TFLAG_VAD_OUT); - } else if (!strcasecmp(val, "both")) { - switch_set_flag(profile, TFLAG_VAD_IN); - switch_set_flag(profile, TFLAG_VAD_OUT); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invald option %s for VAD\n", val); - } - } else if (!strcasecmp(var, "ext-rtp-ip")) { - profile->extrtpip = switch_core_strdup(profile->pool, val); - } else if (!strcasecmp(var, "rtp-ip")) { - profile->rtpip = switch_core_strdup(profile->pool, val); - } else if (!strcasecmp(var, "sip-ip")) { - profile->sipip = switch_core_strdup(profile->pool, val); - } else if (!strcasecmp(var, "sip-domain")) { - profile->sipdomain = switch_core_strdup(profile->pool, val); - } else if (!strcasecmp(var, "rtp-timer-name")) { - profile->timer_name = switch_core_strdup(profile->pool, val); - } else if (!strcasecmp(var, "auth-calls")) { - if (switch_true(val)) { - profile->pflags |= PFLAG_AUTH_CALLS; - } - } else if (!strcasecmp(var, "accept-blind-reg")) { - if (switch_true(val)) { - profile->pflags |= PFLAG_BLIND_REG; - } - } else if (!strcasecmp(var, "auth-all-packets")) { - if (switch_true(val)) { - profile->pflags |= PFLAG_AUTH_ALL; - } - } else if (!strcasecmp(var, "ext-sip-ip")) { - profile->extsipip = switch_core_strdup(profile->pool, val); - } else if (!strcasecmp(var, "bitpacking")) { - if (!strcasecmp(val, "aal2")) { - profile->codec_flags = SWITCH_CODEC_FLAG_AAL2; - } - } else if (!strcasecmp(var, "username")) { - profile->username = switch_core_strdup(profile->pool, val); - } else if (!strcasecmp(var, "context")) { - profile->context = switch_core_strdup(profile->pool, val); - } else if (!strcasecmp(var, "alias")) { - sip_alias_node_t *node; - if ((node = switch_core_alloc(profile->pool, sizeof(*node)))) { - if ((node->url = switch_core_strdup(profile->pool, val))) { - node->next = profile->aliases; - profile->aliases = node; + if (!strcasecmp(var, "debug")) { + profile->debug = atoi(val); + } else if (!strcasecmp(var, "use-rtp-timer") && switch_true(val)) { + switch_set_flag(profile, TFLAG_TIMER); + } else if (!strcasecmp(var, "rfc2833-pt")) { + profile->te = (switch_payload_t) atoi(val); + } else if (!strcasecmp(var, "sip-port")) { + profile->sip_port = atoi(val); + } else if (!strcasecmp(var, "vad")) { + if (!strcasecmp(val, "in")) { + switch_set_flag(profile, TFLAG_VAD_IN); + } else if (!strcasecmp(val, "out")) { + switch_set_flag(profile, TFLAG_VAD_OUT); + } else if (!strcasecmp(val, "both")) { + switch_set_flag(profile, TFLAG_VAD_IN); + switch_set_flag(profile, TFLAG_VAD_OUT); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invald option %s for VAD\n", val); + } + } else if (!strcasecmp(var, "ext-rtp-ip")) { + profile->extrtpip = switch_core_strdup(profile->pool, val); + } else if (!strcasecmp(var, "rtp-ip")) { + profile->rtpip = switch_core_strdup(profile->pool, val); + } else if (!strcasecmp(var, "sip-ip")) { + profile->sipip = switch_core_strdup(profile->pool, val); + } else if (!strcasecmp(var, "sip-domain")) { + profile->sipdomain = switch_core_strdup(profile->pool, val); + } else if (!strcasecmp(var, "rtp-timer-name")) { + profile->timer_name = switch_core_strdup(profile->pool, val); + } else if (!strcasecmp(var, "auth-calls")) { + if (switch_true(val)) { + profile->pflags |= PFLAG_AUTH_CALLS; + } + } else if (!strcasecmp(var, "accept-blind-reg")) { + if (switch_true(val)) { + profile->pflags |= PFLAG_BLIND_REG; + } + } else if (!strcasecmp(var, "auth-all-packets")) { + if (switch_true(val)) { + profile->pflags |= PFLAG_AUTH_ALL; + } + } else if (!strcasecmp(var, "ext-sip-ip")) { + profile->extsipip = switch_core_strdup(profile->pool, val); + } else if (!strcasecmp(var, "bitpacking")) { + if (!strcasecmp(val, "aal2")) { + profile->codec_flags = SWITCH_CODEC_FLAG_AAL2; + } + } else if (!strcasecmp(var, "username")) { + profile->username = switch_core_strdup(profile->pool, val); + } else if (!strcasecmp(var, "context")) { + profile->context = switch_core_strdup(profile->pool, val); + } else if (!strcasecmp(var, "alias")) { + sip_alias_node_t *node; + if ((node = switch_core_alloc(profile->pool, sizeof(*node)))) { + if ((node->url = switch_core_strdup(profile->pool, val))) { + node->next = profile->aliases; + profile->aliases = node; + } + } + } else if (!strcasecmp(var, "dialplan")) { + profile->dialplan = switch_core_strdup(profile->pool, val); + } else if (!strcasecmp(var, "max-calls")) { + profile->max_calls = atoi(val); + } else if (!strcasecmp(var, "codec-prefs")) { + profile->codec_string = switch_core_strdup(profile->pool, val); + profile->codec_order_last = switch_separate_string(profile->codec_string, ',', profile->codec_order, SWITCH_MAX_CODECS); + } else if (!strcasecmp(var, "codec-ms")) { + profile->codec_ms = atoi(val); + } else if (!strcasecmp(var, "dtmf-duration")) { + int dur = atoi(val); + if (dur > 10 && dur < 8000) { + profile->dtmf_duration = dur; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Duration out of bounds!\n"); + } } } - } else if (!strcasecmp(var, "dialplan")) { - profile->dialplan = switch_core_strdup(profile->pool, val); - } else if (!strcasecmp(var, "max-calls")) { - profile->max_calls = atoi(val); - } else if (!strcasecmp(var, "codec-prefs")) { - profile->codec_string = switch_core_strdup(profile->pool, val); - profile->codec_order_last = switch_separate_string(profile->codec_string, ',', profile->codec_order, SWITCH_MAX_CODECS); - } else if (!strcasecmp(var, "codec-ms")) { - profile->codec_ms = atoi(val); - } else if (!strcasecmp(var, "dtmf-duration")) { - int dur = atoi(val); - if (dur > 10 && dur < 8000) { - profile->dtmf_duration = dur; - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Duration out of bounds!\n"); + + if (switch_test_flag(profile, TFLAG_TIMER) && !profile->timer_name) { + profile->timer_name = switch_core_strdup(profile->pool, "soft"); } + + if (!profile->username) { + profile->username = switch_core_strdup(profile->pool, "FreeSWITCH"); + } + + if (!profile->rtpip) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Setting ip to '127.0.0.1'\n"); + profile->rtpip = switch_core_strdup(profile->pool, "127.0.0.1"); + } + + if (!profile->sip_port) { + profile->sip_port = 5060; + } + + if (!profile->dialplan) { + profile->dialplan = switch_core_strdup(profile->pool, "default"); + } + + if (!profile->sipdomain) { + profile->sipdomain = switch_core_strdup(profile->pool, profile->sipip); + } + + snprintf(url, sizeof(url), "sip:%s:%d", profile->sipip, profile->sip_port); + profile->url = switch_core_strdup(profile->pool, url); + } + if (profile) { + if ((registrations = switch_xml_child(xprofile, "registrations"))) { + uint32_t reg_count = 0; + for (registration = switch_xml_child(registrations, "registration"); registration; registration = registration->next) { + char *name = (char *) switch_xml_attr_soft(registration, "name"); + outbound_reg_t *oreg; + + if (++reg_count > 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + "Sorry, only one registration per profile for now =(:::, ask the sofia team for NUTAG_IDENTITY!!!!\n"); + } + if (switch_strlen_zero(name)) { + name = "anonymous"; + } + + if ((oreg = switch_core_alloc(profile->pool, sizeof(*oreg)))) { + oreg->pool = profile->pool; + oreg->profile = profile; + oreg->name = switch_core_strdup(oreg->pool, name); + oreg->freq = 60; + + for (param = switch_xml_child(registration, "param"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + char *val = (char *) switch_xml_attr_soft(param, "value"); + + if (!strcmp(var, "register-scheme")) { + oreg->register_scheme = switch_core_strdup(oreg->pool, val); + } else if (!strcmp(var, "register-realm")) { + oreg->register_realm = switch_core_strdup(oreg->pool, val); + } else if (!strcmp(var, "register-username")) { + oreg->register_username = switch_core_strdup(oreg->pool, val); + } else if (!strcmp(var, "register-password")) { + oreg->register_password = switch_core_strdup(oreg->pool, val); + } else if (!strcmp(var, "register-from")) { + oreg->register_from = switch_core_strdup(oreg->pool, val); + } else if (!strcmp(var, "register-to")) { + oreg->register_to = switch_core_strdup(oreg->pool, val); + } else if (!strcmp(var, "register-proxy")) { + oreg->register_proxy = switch_core_strdup(oreg->pool, val); + } else if (!strcmp(var, "register-frequency")) { + oreg->expires_str = switch_core_strdup(oreg->pool, val); + oreg->freq = atoi(val); + } + } + if (switch_strlen_zero(oreg->register_scheme)) { + oreg->register_scheme = switch_core_strdup(oreg->pool, "Digest"); + } + if (switch_strlen_zero(oreg->register_realm)) { + oreg->register_realm = switch_core_strdup(oreg->pool, "freeswitch.org"); + } + if (switch_strlen_zero(oreg->register_username)) { + oreg->register_username = switch_core_strdup(oreg->pool, "freeswitch"); + } + if (switch_strlen_zero(oreg->register_password)) { + oreg->register_password = switch_core_strdup(oreg->pool, "works"); + } + if (switch_strlen_zero(oreg->register_from)) { + oreg->register_from = switch_core_strdup(oreg->pool, "FreeSWITCH "); + } + if (switch_strlen_zero(oreg->register_to)) { + oreg->register_to = switch_core_strdup(oreg->pool, "sip:freeswitch@freeswitch.org"); + } + if (switch_strlen_zero(oreg->register_proxy)) { + oreg->register_proxy = switch_core_strdup(oreg->pool, "sip:freeswitch@freeswitch.org"); + } + + if (switch_strlen_zero(oreg->expires_str)) { + oreg->expires_str = switch_core_strdup(oreg->pool, "300"); + } + + oreg->freq = atoi(oreg->expires_str); + + oreg->next = profile->registrations; + profile->registrations = oreg; + } + } + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Started Profile %s [%s]\n", profile->name, url); + launch_profile_thread(profile); + profile = NULL; } } - - if (switch_test_flag(profile, TFLAG_TIMER) && !profile->timer_name) { - profile->timer_name = switch_core_strdup(profile->pool, "soft"); - } - - if (!profile->username) { - profile->username = switch_core_strdup(profile->pool, "FreeSWITCH"); - } - - if (!profile->rtpip) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Setting ip to '127.0.0.1'\n"); - profile->rtpip = switch_core_strdup(profile->pool, "127.0.0.1"); - } - - if (!profile->sip_port) { - profile->sip_port = 5060; - } - - if (!profile->dialplan) { - profile->dialplan = switch_core_strdup(profile->pool, "default"); - } - - if (!profile->sipdomain) { - profile->sipdomain = switch_core_strdup(profile->pool, profile->sipip); - } - - snprintf(url, sizeof(url), "sip:%s:%d", profile->sipip, profile->sip_port); - profile->url = switch_core_strdup(profile->pool, url); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Started Profile %s [%s]\n", profile->name, url); - launch_profile_thread(profile); - } - done: if (xml) { switch_xml_free(xml); @@ -2612,7 +2866,7 @@ static void event_handler(switch_event_t *event) } if (sql) { - execute_sql(profile->dbname, sql, profile->reg_mutex); + execute_sql(profile->dbname, sql, profile->ireg_mutex); switch_core_db_free(sql); sql = NULL; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Propagating registration for %s@%s->%s@%s\n",