peliminary sofia inbound reg support rm all traces of sofia and rebuild or face certian doom
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2843 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
3f59051b0a
commit
5a3a8297ef
|
@ -476,6 +476,12 @@
|
|||
</section>
|
||||
|
||||
<section name="directory" description="User Directory">
|
||||
<domain name="mydomain.com">
|
||||
<user id="1000">
|
||||
<param name="password" value="mypass"/>
|
||||
<param name="mypref" value="myval"/>
|
||||
</user>
|
||||
</domain>
|
||||
</section>
|
||||
|
||||
</document>
|
||||
|
|
|
@ -53,7 +53,18 @@ typedef struct private_object private_object_t;
|
|||
#include <sofia-sip/sip_status.h>
|
||||
#include <sofia-sip/sdp.h>
|
||||
#include <sofia-sip/sip_protos.h>
|
||||
#define DBFILE "sofia"
|
||||
|
||||
static char reg_sql[] =
|
||||
"CREATE TABLE sip_registrations (\n"
|
||||
" user VARCHAR(255),\n"
|
||||
" host VARCHAR(255),\n"
|
||||
" contact VARCHAR(255),\n"
|
||||
" expires INTEGER(8)"
|
||||
");\n";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static const char modname[] = "mod_sofia";
|
||||
#define STRLEN 15
|
||||
|
@ -97,11 +108,14 @@ static struct {
|
|||
switch_hash_t *profile_hash;
|
||||
switch_mutex_t *hash_mutex;
|
||||
uint32_t callid;
|
||||
int32_t running;
|
||||
switch_mutex_t *mutex;
|
||||
} globals;
|
||||
|
||||
struct sofia_profile {
|
||||
int debug;
|
||||
char *name;
|
||||
char *dbname;
|
||||
char *dialplan;
|
||||
char *context;
|
||||
char *extrtpip;
|
||||
|
@ -127,6 +141,8 @@ struct sofia_profile {
|
|||
sip_alias_node_t *aliases;
|
||||
switch_payload_t te;
|
||||
uint32_t codec_flags;
|
||||
switch_mutex_t *reg_mutex;
|
||||
switch_core_db_t *db;
|
||||
};
|
||||
|
||||
|
||||
|
@ -234,6 +250,13 @@ static void sip_i_invite(nua_t *nua,
|
|||
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,
|
||||
sip_t const *sip,
|
||||
tagi_t tags[]);
|
||||
|
||||
static void event_callback(nua_event_t event,
|
||||
int status,
|
||||
char const *phrase,
|
||||
|
@ -254,6 +277,83 @@ static switch_status_t config_sofia(int reload);
|
|||
|
||||
/* BODY OF THE MODULE */
|
||||
/*************************************************************************************************************************************************************/
|
||||
struct callback_t {
|
||||
char *val;
|
||||
switch_size_t len;
|
||||
int matches;
|
||||
};
|
||||
|
||||
static int find_callback(void *pArg, int argc, char **argv, char **columnNames){
|
||||
struct callback_t *cbt = (struct callback_t *) pArg;
|
||||
|
||||
switch_copy_string(cbt->val, argv[0], cbt->len);
|
||||
cbt->matches++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int del_callback(void *pArg, int argc, char **argv, char **columnNames){
|
||||
switch_event_t *s_event;
|
||||
|
||||
if (argc >=3 ) {
|
||||
if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_EXPIRE) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "user", "%s", argv[0]);
|
||||
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "host", "%s", argv[1]);
|
||||
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "contact", "%s", argv[2]);
|
||||
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%d", argv[3]);
|
||||
switch_event_fire(&s_event);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void check_expire(sofia_profile_t *profile, time_t now)
|
||||
{
|
||||
char sql[1024];
|
||||
char *errmsg;
|
||||
|
||||
switch_mutex_lock(profile->reg_mutex);
|
||||
snprintf(sql, sizeof(sql), "select * from sip_registrations where expires > 0 and expires < %ld", (long) now);
|
||||
switch_core_db_exec(profile->db, sql, del_callback, NULL, &errmsg);
|
||||
|
||||
if (errmsg) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s][%s]\n", sql, errmsg);
|
||||
switch_core_db_free(errmsg);
|
||||
errmsg = NULL;
|
||||
}
|
||||
|
||||
snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and expires < %ld", (long) now);
|
||||
switch_core_db_persistant_execute(profile->db, sql, 1);
|
||||
switch_mutex_unlock(profile->reg_mutex);
|
||||
}
|
||||
|
||||
static char *find_reg_url(sofia_profile_t *profile, char *user, char *host, char *val, switch_size_t len)
|
||||
{
|
||||
char *errmsg;
|
||||
struct callback_t cbt = {0};
|
||||
|
||||
|
||||
cbt.val = val;
|
||||
cbt.len = len;
|
||||
switch_mutex_lock(profile->reg_mutex);
|
||||
if (host) {
|
||||
snprintf(val, len, "select contact from sip_registrations where user='%s' and host='%s'", user, host);
|
||||
} else {
|
||||
snprintf(val, len, "select contact from sip_registrations where user='%s'", user);
|
||||
}
|
||||
|
||||
switch_core_db_exec(profile->db, val, find_callback, &cbt, &errmsg);
|
||||
|
||||
if (errmsg) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s][%s]\n", val, errmsg);
|
||||
switch_core_db_free(errmsg);
|
||||
errmsg = NULL;
|
||||
}
|
||||
|
||||
switch_mutex_unlock(profile->reg_mutex);
|
||||
return cbt.matches ? val : NULL;
|
||||
}
|
||||
|
||||
|
||||
static void set_local_sdp(private_object_t *tech_pvt)
|
||||
{
|
||||
char buf[1024];
|
||||
|
@ -1151,6 +1251,7 @@ static switch_status_t sofia_outgoing_channel(switch_core_session_t *session, sw
|
|||
switch_caller_profile_t *caller_profile = NULL;
|
||||
private_object_t *tech_pvt = NULL;
|
||||
switch_channel_t *channel;
|
||||
char *host;
|
||||
|
||||
*new_session = NULL;
|
||||
|
||||
|
@ -1181,10 +1282,18 @@ static switch_status_t sofia_outgoing_channel(switch_core_session_t *session, sw
|
|||
terminate_session(&nsession, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER, __LINE__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
tech_pvt->dest = switch_core_session_alloc(nsession, strlen(dest) + 5);
|
||||
snprintf(tech_pvt->dest, strlen(dest) + 5, "sip:%s", dest);
|
||||
|
||||
|
||||
if ((host = strchr(dest, '%'))) {
|
||||
char buf[128];
|
||||
*host++ = '\0';
|
||||
find_reg_url(profile, dest, host, buf, sizeof(buf));
|
||||
tech_pvt->dest = switch_core_session_strdup(nsession, buf);
|
||||
dest = tech_pvt->dest + 4;
|
||||
} else {
|
||||
tech_pvt->dest = switch_core_session_alloc(nsession, strlen(dest) + 5);
|
||||
snprintf(tech_pvt->dest, strlen(dest) + 5, "sip:%s", dest);
|
||||
}
|
||||
|
||||
channel = switch_core_session_get_channel(nsession);
|
||||
attach_private(nsession, profile, tech_pvt, dest);
|
||||
caller_profile = switch_caller_profile_clone(nsession, outbound_profile);
|
||||
|
@ -1553,6 +1662,106 @@ 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,
|
||||
sip_t const *sip,
|
||||
tagi_t tags[])
|
||||
{
|
||||
sip_from_t const *from = sip->sip_from;
|
||||
sip_expires_t const *expires = sip->sip_expires;
|
||||
//sip_to_t const *to = sip->sip_to;
|
||||
sip_contact_t const *contact = sip->sip_contact;
|
||||
// SIP_407_PROXY_AUTH_REQUIRED
|
||||
switch_xml_t domain, xml, user, param;
|
||||
char params[1024] = "";
|
||||
char *sql;
|
||||
switch_event_t *s_event;
|
||||
char *from_user = (char *) from->a_url->url_user;
|
||||
char *from_host = (char *) from->a_url->url_host;
|
||||
char *contact_user = (char *) contact->m_url->url_user;
|
||||
char *contact_host = (char *) contact->m_url->url_host;
|
||||
char buf[512];
|
||||
|
||||
snprintf(params, sizeof(params), "from_user=%s&from_host=%s&contact_user=%s&contact_host=%s",
|
||||
from_user,
|
||||
from_host,
|
||||
contact_user,
|
||||
contact_host
|
||||
);
|
||||
|
||||
|
||||
if (switch_xml_locate("directory", "domain", "name", (char *)from->a_url->url_host, &xml, &domain, params) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of directory failed\n");
|
||||
nua_respond(nh, SIP_401_UNAUTHORIZED, SIPTAG_CONTACT(contact), TAG_END());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(user = switch_xml_find_child(domain, "user", "id", from_user))) {
|
||||
nua_respond(nh, SIP_401_UNAUTHORIZED, SIPTAG_CONTACT(contact), TAG_END());
|
||||
switch_xml_free(xml);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (param = switch_xml_child(user, "param"); param; param = param->next) {
|
||||
char *var = (char *) switch_xml_attr_soft(param, "name");
|
||||
char *val = (char *) switch_xml_attr_soft(param, "value");
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "param [%s]=[%s]\n", var, val);
|
||||
}
|
||||
|
||||
|
||||
if (!find_reg_url(profile, from_user, from_host, buf, sizeof(buf))) {
|
||||
sql = switch_core_db_mprintf("insert into sip_registrations values ('%q','%q','sip:%q@%q',%ld)",
|
||||
from_user,
|
||||
from_host,
|
||||
contact_user,
|
||||
contact_host,
|
||||
(long) time(NULL) + (long)expires->ex_delta);
|
||||
} else {
|
||||
sql = switch_core_db_mprintf("update sip_registrations set contact='sip:%q@%q', expires=%ld where user='%q' and host='%q'",
|
||||
contact_user,
|
||||
contact_host,
|
||||
(long) time(NULL) + (long)expires->ex_delta,
|
||||
from_user,
|
||||
from_host);
|
||||
|
||||
}
|
||||
|
||||
if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_REGISTER) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from_user", "%s", from_user);
|
||||
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from_host", "%s", from_host);
|
||||
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "contact_user", "%s", contact_user);
|
||||
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "contact_host", "%s", contact_host);
|
||||
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "expires", "%ld", (long)expires->ex_delta);
|
||||
switch_event_fire(&s_event);
|
||||
}
|
||||
if (sql) {
|
||||
switch_mutex_lock(profile->reg_mutex);
|
||||
switch_core_db_persistant_execute(profile->db, sql, 25);
|
||||
switch_core_db_free(sql);
|
||||
sql = NULL;
|
||||
switch_mutex_unlock(profile->reg_mutex);
|
||||
}
|
||||
|
||||
switch_xml_free(xml);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Got a Register from [%s@%s] contact [%s@%s] expires %ld\n",
|
||||
from_user,
|
||||
from_host,
|
||||
contact_user,
|
||||
contact_host,
|
||||
(long)expires->ex_delta
|
||||
);
|
||||
|
||||
|
||||
nua_respond(nh, SIP_200_OK, SIPTAG_CONTACT(contact), TAG_END());
|
||||
//nua_respond(nh, SIP_407_PROXY_AUTH_REQUIRED, TAG_END());
|
||||
}
|
||||
|
||||
static void event_callback(nua_event_t event,
|
||||
int status,
|
||||
char const *phrase,
|
||||
|
@ -1605,6 +1814,10 @@ static void event_callback(nua_event_t event,
|
|||
sip_i_invite(nua, profile, nh, session, sip, tags);
|
||||
break;
|
||||
|
||||
case nua_i_register:
|
||||
sip_i_register (nua, profile, nh, session, sip, tags);
|
||||
break;
|
||||
|
||||
case nua_i_prack:
|
||||
//sip_i_prack(nua, profile, nh, session, sip, tags);
|
||||
break;
|
||||
|
@ -1695,11 +1908,14 @@ static void event_callback(nua_event_t event,
|
|||
}
|
||||
}
|
||||
|
||||
#define REG_SECONDS 30
|
||||
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;
|
||||
|
||||
|
||||
profile->s_root = su_root_create(NULL);
|
||||
profile->nua = nua_create(profile->s_root, /* Event loop */
|
||||
|
@ -1712,8 +1928,7 @@ static void *SWITCH_THREAD_FUNC profile_thread_run(switch_thread_t *thread, void
|
|||
NUTAG_EARLY_MEDIA(1),
|
||||
NUTAG_AUTOANSWER(0),
|
||||
NUTAG_AUTOALERT(0),
|
||||
//NUTAG_ALLOW("REGISTER"),
|
||||
//SIPTAG_ALLOW_STR("REGISTER"),
|
||||
NUTAG_ALLOW("REGISTER"),
|
||||
SIPTAG_SUPPORTED_STR("100rel, precondition"),
|
||||
TAG_END());
|
||||
|
||||
|
@ -1728,17 +1943,46 @@ static void *SWITCH_THREAD_FUNC profile_thread_run(switch_thread_t *thread, void
|
|||
nua_set_params(node->nua,
|
||||
NUTAG_EARLY_MEDIA(1),
|
||||
NUTAG_AUTOANSWER(0),
|
||||
NUTAG_ALLOW("REGISTER"),
|
||||
SIPTAG_SUPPORTED_STR("100rel, precondition"),
|
||||
NUTAG_AUTOALERT(0),
|
||||
TAG_END());
|
||||
|
||||
}
|
||||
|
||||
su_root_run(profile->s_root);
|
||||
|
||||
if ((profile->db = switch_core_db_open_file(profile->dbname))) {
|
||||
switch_core_db_test_reactive(profile->db, "select * from sip_registrations", reg_sql);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open SQL Database!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch_mutex_init(&profile->reg_mutex, SWITCH_MUTEX_NESTED, profile->pool);
|
||||
|
||||
switch_mutex_lock(globals.mutex);
|
||||
globals.running = 1;
|
||||
switch_mutex_unlock(globals.mutex);
|
||||
|
||||
loops = REG_SECONDS;
|
||||
|
||||
while(globals.running == 1) {
|
||||
if (++loops >= REG_SECONDS) {
|
||||
check_expire(profile, time(NULL));
|
||||
loops = 0;
|
||||
}
|
||||
|
||||
su_root_step(profile->s_root, 1000);
|
||||
//su_root_run(profile->s_root);
|
||||
}
|
||||
|
||||
su_root_destroy(profile->s_root);
|
||||
|
||||
pool = profile->pool;
|
||||
switch_core_destroy_memory_pool(&pool);
|
||||
switch_mutex_lock(globals.mutex);
|
||||
globals.running = 0;
|
||||
switch_mutex_unlock(globals.mutex);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1764,7 +2008,7 @@ static switch_status_t config_sofia(int reload)
|
|||
char *cf = "sofia.conf";
|
||||
switch_xml_t cfg, xml = NULL, xprofile, param;
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
|
||||
|
||||
if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf);
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
|
@ -1791,10 +2035,15 @@ static switch_status_t config_sofia(int reload)
|
|||
if (!xprofilename) {
|
||||
xprofilename = "unnamed";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
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->dtmf_duration = 100;
|
||||
profile->codec_ms = 20;
|
||||
|
@ -1910,7 +2159,6 @@ static switch_status_t config_sofia(int reload)
|
|||
|
||||
}
|
||||
|
||||
|
||||
SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename)
|
||||
{
|
||||
|
||||
|
@ -1920,6 +2168,8 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_mod
|
|||
}
|
||||
|
||||
memset(&globals, 0, sizeof(globals));
|
||||
switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, module_pool);
|
||||
|
||||
su_init();
|
||||
|
||||
|
||||
|
@ -1939,10 +2189,17 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_mod
|
|||
|
||||
SWITCH_MOD_DECLARE(switch_status_t) switch_module_shutdown(void)
|
||||
{
|
||||
/* Adding Note so we can destroy these properly. Will remind tony.
|
||||
* nua_destroy (nua);
|
||||
* su_root_destroy (root);
|
||||
*/
|
||||
|
||||
switch_mutex_lock(globals.mutex);
|
||||
if (globals.running == 1) {
|
||||
globals.running = -1;
|
||||
}
|
||||
switch_mutex_unlock(globals.mutex);
|
||||
|
||||
while(globals.running) {
|
||||
switch_yield(1000);
|
||||
}
|
||||
|
||||
su_deinit();
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
|
|
@ -168,8 +168,7 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_find_child(switch_xml_t node, char *chil
|
|||
|
||||
for (p = switch_xml_child(node, childname); p; p = p->next) {
|
||||
const char *aname = switch_xml_attr(p, attrname);
|
||||
|
||||
if (!strcasecmp(aname, value)) {
|
||||
if (aname && value && !strcasecmp(aname, value)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue