mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-15 00:22:35 +00:00
MODENDP-77 Gateway event subscriptions.
Merged with minor modifications. Still needs to add support for reload/rescan. git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@10525 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
ee35d990d5
commit
d16d7ffd7d
@ -1063,6 +1063,7 @@ typedef uint32_t switch_io_flag_t;
|
|||||||
SWITCH_EVENT_DTMF - DTMF was sent
|
SWITCH_EVENT_DTMF - DTMF was sent
|
||||||
SWITCH_EVENT_MESSAGE - A Basic Message
|
SWITCH_EVENT_MESSAGE - A Basic Message
|
||||||
SWITCH_EVENT_PRESENCE_IN - Presence in
|
SWITCH_EVENT_PRESENCE_IN - Presence in
|
||||||
|
SWITCH_EVENT_NOTIFY_IN - Received incoming NOTIFY from gateway subscription
|
||||||
SWITCH_EVENT_PRESENCE_OUT - Presence out
|
SWITCH_EVENT_PRESENCE_OUT - Presence out
|
||||||
SWITCH_EVENT_PRESENCE_PROBE - Presence probe
|
SWITCH_EVENT_PRESENCE_PROBE - Presence probe
|
||||||
SWITCH_EVENT_MESSAGE_WAITING - A message is waiting
|
SWITCH_EVENT_MESSAGE_WAITING - A message is waiting
|
||||||
@ -1121,6 +1122,7 @@ typedef enum {
|
|||||||
SWITCH_EVENT_DTMF,
|
SWITCH_EVENT_DTMF,
|
||||||
SWITCH_EVENT_MESSAGE,
|
SWITCH_EVENT_MESSAGE,
|
||||||
SWITCH_EVENT_PRESENCE_IN,
|
SWITCH_EVENT_PRESENCE_IN,
|
||||||
|
SWITCH_EVENT_NOTIFY_IN,
|
||||||
SWITCH_EVENT_PRESENCE_OUT,
|
SWITCH_EVENT_PRESENCE_OUT,
|
||||||
SWITCH_EVENT_PRESENCE_PROBE,
|
SWITCH_EVENT_PRESENCE_PROBE,
|
||||||
SWITCH_EVENT_MESSAGE_WAITING,
|
SWITCH_EVENT_MESSAGE_WAITING,
|
||||||
|
@ -60,6 +60,9 @@ static const switch_state_handler_table_t noop_state_handler = { 0 };
|
|||||||
struct sofia_gateway;
|
struct sofia_gateway;
|
||||||
typedef struct sofia_gateway sofia_gateway_t;
|
typedef struct sofia_gateway sofia_gateway_t;
|
||||||
|
|
||||||
|
struct sofia_gateway_subscription;
|
||||||
|
typedef struct sofia_gateway_subscription sofia_gateway_subscription_t;
|
||||||
|
|
||||||
struct sofia_profile;
|
struct sofia_profile;
|
||||||
typedef struct sofia_profile sofia_profile_t;
|
typedef struct sofia_profile sofia_profile_t;
|
||||||
#define NUA_MAGIC_T sofia_profile_t
|
#define NUA_MAGIC_T sofia_profile_t
|
||||||
@ -272,6 +275,31 @@ typedef enum {
|
|||||||
SOFIA_GATEWAY_UP
|
SOFIA_GATEWAY_UP
|
||||||
} sofia_gateway_status_t;
|
} sofia_gateway_status_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SUB_STATE_UNSUBED,
|
||||||
|
SUB_STATE_TRYING,
|
||||||
|
SUB_STATE_SUBSCRIBE,
|
||||||
|
SUB_STATE_SUBED,
|
||||||
|
SUB_STATE_UNSUBSCRIBE,
|
||||||
|
SUB_STATE_FAILED,
|
||||||
|
SUB_STATE_EXPIRED,
|
||||||
|
SUB_STATE_NOSUB,
|
||||||
|
v_STATE_LAST
|
||||||
|
} sub_state_t;
|
||||||
|
|
||||||
|
struct sofia_gateway_subscription {
|
||||||
|
sofia_gateway_t *gateway;
|
||||||
|
char *expires_str;
|
||||||
|
char *event; /* eg, 'message-summary' to subscribe to MWI events */
|
||||||
|
char *content_type; /* eg, application/simple-message-summary in the case of MWI events */
|
||||||
|
uint32_t freq;
|
||||||
|
int32_t retry_seconds;
|
||||||
|
time_t expires;
|
||||||
|
time_t retry;
|
||||||
|
sub_state_t state;
|
||||||
|
struct sofia_gateway_subscription *next;
|
||||||
|
};
|
||||||
|
|
||||||
struct sofia_gateway {
|
struct sofia_gateway {
|
||||||
sofia_private_t *sofia_private;
|
sofia_private_t *sofia_private;
|
||||||
nua_handle_t *nh;
|
nua_handle_t *nh;
|
||||||
@ -306,6 +334,7 @@ struct sofia_gateway {
|
|||||||
switch_event_t *vars;
|
switch_event_t *vars;
|
||||||
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
|
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
|
||||||
struct sofia_gateway *next;
|
struct sofia_gateway *next;
|
||||||
|
sofia_gateway_subscription_t *subscriptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -622,6 +651,7 @@ void sofia_glue_execute_sql(sofia_profile_t *profile, char **sqlp, switch_bool_t
|
|||||||
void sofia_glue_actually_execute_sql(sofia_profile_t *profile, switch_bool_t master, char *sql, switch_mutex_t *mutex);
|
void sofia_glue_actually_execute_sql(sofia_profile_t *profile, switch_bool_t master, char *sql, switch_mutex_t *mutex);
|
||||||
void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot);
|
void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot);
|
||||||
void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now);
|
void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now);
|
||||||
|
void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now);
|
||||||
void sofia_reg_unregister(sofia_profile_t *profile);
|
void sofia_reg_unregister(sofia_profile_t *profile);
|
||||||
switch_status_t sofia_glue_ext_address_lookup(sofia_profile_t *profile, private_object_t *tech_pvt, char **ip, switch_port_t *port, char *sourceip, switch_memory_pool_t *pool);
|
switch_status_t sofia_glue_ext_address_lookup(sofia_profile_t *profile, private_object_t *tech_pvt, char **ip, switch_port_t *port, char *sourceip, switch_memory_pool_t *pool);
|
||||||
|
|
||||||
@ -660,6 +690,8 @@ switch_status_t sofia_reg_add_gateway(char *key, sofia_gateway_t *gateway);
|
|||||||
sofia_gateway_t *sofia_reg_find_gateway__(const char *file, const char *func, int line, const char *key);
|
sofia_gateway_t *sofia_reg_find_gateway__(const char *file, const char *func, int line, const char *key);
|
||||||
#define sofia_reg_find_gateway(x) sofia_reg_find_gateway__(__FILE__, __SWITCH_FUNC__, __LINE__, x)
|
#define sofia_reg_find_gateway(x) sofia_reg_find_gateway__(__FILE__, __SWITCH_FUNC__, __LINE__, x)
|
||||||
|
|
||||||
|
sofia_gateway_subscription_t *sofia_find_gateway_subscription(sofia_gateway_t *gateway_ptr, const char *event);
|
||||||
|
|
||||||
void sofia_reg_release_gateway__(const char *file, const char *func, int line, sofia_gateway_t *gateway);
|
void sofia_reg_release_gateway__(const char *file, const char *func, int line, sofia_gateway_t *gateway);
|
||||||
#define sofia_reg_release_gateway(x) sofia_reg_release_gateway__(__FILE__, __SWITCH_FUNC__, __LINE__, x);
|
#define sofia_reg_release_gateway(x) sofia_reg_release_gateway__(__FILE__, __SWITCH_FUNC__, __LINE__, x);
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ void sofia_handle_sip_i_notify(switch_core_session_t *session, int status,
|
|||||||
switch_channel_t *channel = NULL;
|
switch_channel_t *channel = NULL;
|
||||||
private_object_t *tech_pvt = NULL;
|
private_object_t *tech_pvt = NULL;
|
||||||
switch_event_t *s_event = NULL;
|
switch_event_t *s_event = NULL;
|
||||||
|
sofia_gateway_subscription_t *gw_sub_ptr;
|
||||||
|
|
||||||
/* make sure we have a proper event */
|
/* make sure we have a proper event */
|
||||||
if (!sip || !sip->sip_event) {
|
if (!sip || !sip->sip_event) {
|
||||||
@ -172,21 +173,60 @@ void sofia_handle_sip_i_notify(switch_core_session_t *session, int status,
|
|||||||
nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END());
|
nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if no session, assume it could be an incoming notify from a gateway subscription */
|
||||||
|
if (session) {
|
||||||
|
/* make sure we have a proper "talk" event */
|
||||||
|
if (strcasecmp(sip->sip_event->o_type, "talk")) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
/* make sure we have a proper "talk" event */
|
if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||||
if (!session || strcasecmp(sip->sip_event->o_type, "talk")) {
|
switch_channel_answer(channel);
|
||||||
goto error;
|
switch_channel_set_variable(channel, "auto_answer_destination", switch_channel_get_variable(channel, "destination_number"));
|
||||||
}
|
switch_ivr_session_transfer(session, "auto_answer", NULL, NULL);
|
||||||
|
nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END());
|
||||||
|
return;
|
||||||
if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
}
|
||||||
switch_channel_answer(channel);
|
|
||||||
switch_channel_set_variable(channel, "auto_answer_destination", switch_channel_get_variable(channel, "destination_number"));
|
|
||||||
switch_ivr_session_transfer(session, "auto_answer", NULL, NULL);
|
|
||||||
nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS(nua), TAG_END());
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!sofia_private || !sofia_private->gateway) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Gateway information missing\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find the corresponding gateway subscription (if any) */
|
||||||
|
if (!(gw_sub_ptr = sofia_find_gateway_subscription(sofia_private->gateway, sip->sip_event->o_type))) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
|
||||||
|
"Could not find gateway subscription. Gateway: %s. Subscription Event: %s\n",
|
||||||
|
sofia_private->gateway->name, sip->sip_event->o_type);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(gw_sub_ptr->state == SUB_STATE_SUBED || gw_sub_ptr->state == SUB_STATE_SUBSCRIBE)) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
|
||||||
|
"Ignoring notify due to subscription state: %d\n",
|
||||||
|
gw_sub_ptr->state);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dispatch freeswitch event */
|
||||||
|
if (switch_event_create(&s_event, SWITCH_EVENT_NOTIFY_IN) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "event", "%s", sip->sip_event->o_type);
|
||||||
|
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "pl_data", "%s", sip->sip_payload->pl_data);
|
||||||
|
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "sip_content_type", "%s", sip->sip_content_type->c_type);
|
||||||
|
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "port", "%d", sofia_private->gateway->profile->sip_port);
|
||||||
|
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "module_name", "%s", "mod_sofia");
|
||||||
|
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "profile_name", "%s", sofia_private->gateway->profile->name);
|
||||||
|
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "profile_uri", "%s", sofia_private->gateway->profile->url);
|
||||||
|
switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "gateway_name", "%s", sofia_private->gateway->name);
|
||||||
|
switch_event_fire(&s_event);
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "dispatched freeswitch event for message-summary NOTIFY\n");
|
||||||
|
} else {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create event\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
nua_respond(nh, 481, "Subscription Does Not Exist", NUTAG_WITH_THIS(nua), TAG_END());
|
nua_respond(nh, 481, "Subscription Does Not Exist", NUTAG_WITH_THIS(nua), TAG_END());
|
||||||
@ -565,6 +605,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread
|
|||||||
sofia_reg_check_gateway(profile, switch_timestamp(NULL));
|
sofia_reg_check_gateway(profile, switch_timestamp(NULL));
|
||||||
gateway_loops = 0;
|
gateway_loops = 0;
|
||||||
}
|
}
|
||||||
|
sofia_sub_check_gateway(profile, time(NULL));
|
||||||
loops = 0;
|
loops = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -859,9 +900,56 @@ static void logger(void *logarg, char const *fmt, va_list ap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void parse_gateway_subscriptions(sofia_profile_t *profile, sofia_gateway_t *gateway, switch_xml_t gw_subs_tag)
|
||||||
|
{
|
||||||
|
switch_xml_t subscription_tag, param;
|
||||||
|
|
||||||
|
for (subscription_tag = switch_xml_child(gw_subs_tag, "subscription"); subscription_tag; subscription_tag = subscription_tag->next) {
|
||||||
|
sofia_gateway_subscription_t *gw_sub;
|
||||||
|
|
||||||
|
if ((gw_sub = switch_core_alloc(profile->pool, sizeof(*gw_sub)))) {
|
||||||
|
char *expire_seconds = "3600", *retry_seconds = "30", *content_type = "NO_CONTENT_TYPE";
|
||||||
|
char *event = (char *) switch_xml_attr_soft(subscription_tag, "event");
|
||||||
|
gw_sub->event = switch_core_strdup(gateway->pool, event);
|
||||||
|
gw_sub->gateway = gateway;
|
||||||
|
gw_sub->next = NULL;
|
||||||
|
|
||||||
|
for (param = switch_xml_child(subscription_tag, "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, "expire-seconds")) {
|
||||||
|
expire_seconds = val;
|
||||||
|
} else if (!strcmp(var, "retry-seconds")) {
|
||||||
|
retry_seconds = val;
|
||||||
|
} else if (!strcmp(var, "content-type")) {
|
||||||
|
content_type = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gw_sub->retry_seconds = atoi(retry_seconds);
|
||||||
|
if (gw_sub->retry_seconds < 10) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "INVALID: retry_seconds correcting the value to 30\n");
|
||||||
|
gw_sub->retry_seconds = 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
gw_sub->expires_str = switch_core_strdup(gateway->pool, expire_seconds);
|
||||||
|
|
||||||
|
if ((gw_sub->freq = atoi(gw_sub->expires_str)) < 5) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
|
||||||
|
"Invalid Freq: %d. Setting Register-Frequency to 3600\n", gw_sub->freq);
|
||||||
|
gw_sub->freq = 3600;
|
||||||
|
}
|
||||||
|
gw_sub->freq -= 2;
|
||||||
|
gw_sub->content_type = switch_core_strdup(gateway->pool, content_type);
|
||||||
|
gw_sub->next = gateway->subscriptions;
|
||||||
|
}
|
||||||
|
gateway->subscriptions = gw_sub;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
|
static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
|
||||||
{
|
{
|
||||||
switch_xml_t gateway_tag, param;
|
switch_xml_t gateway_tag, param, gw_subs_tag;
|
||||||
sofia_gateway_t *gp;
|
sofia_gateway_t *gp;
|
||||||
|
|
||||||
for (gateway_tag = switch_xml_child(gateways_tag, "gateway"); gateway_tag; gateway_tag = gateway_tag->next) {
|
for (gateway_tag = switch_xml_child(gateways_tag, "gateway"); gateway_tag; gateway_tag = gateway_tag->next) {
|
||||||
@ -969,6 +1057,10 @@ static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((gw_subs_tag = switch_xml_child(gateway_tag, "subscriptions"))) {
|
||||||
|
parse_gateway_subscriptions(profile, gateway, gw_subs_tag);
|
||||||
|
}
|
||||||
|
|
||||||
if (switch_strlen_zero(realm)) {
|
if (switch_strlen_zero(realm)) {
|
||||||
realm = name;
|
realm = name;
|
||||||
}
|
}
|
||||||
|
@ -1617,12 +1617,66 @@ void sofia_presence_handle_sip_i_subscribe(int status,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sofia_gateway_subscription_t *sofia_find_gateway_subscription(sofia_gateway_t *gateway_ptr, const char *event) {
|
||||||
|
sofia_gateway_subscription_t *gw_sub_ptr;
|
||||||
|
for (gw_sub_ptr = gateway_ptr->subscriptions; gw_sub_ptr; gw_sub_ptr = gw_sub_ptr->next) {
|
||||||
|
if (!strcasecmp(gw_sub_ptr->event, event)) {
|
||||||
|
/* this is the gateway subscription we are interested in */
|
||||||
|
return gw_sub_ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void sofia_presence_handle_sip_r_subscribe(int status,
|
void sofia_presence_handle_sip_r_subscribe(int status,
|
||||||
char const *phrase,
|
char const *phrase,
|
||||||
nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
|
nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
|
||||||
tagi_t tags[])
|
tagi_t tags[])
|
||||||
{
|
{
|
||||||
|
sip_event_t const *o = NULL;
|
||||||
|
sofia_gateway_subscription_t *gw_sub_ptr;
|
||||||
|
|
||||||
|
if (!sip) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tl_gets(tags, SIPTAG_EVENT_REF(o), TAG_END());
|
||||||
|
/* o->o_type: message-summary (for example) */
|
||||||
|
if (!o) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Event information not given\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sofia_private || !sofia_private->gateway) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Gateway information missing\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the subscription if one exists */
|
||||||
|
if (!(gw_sub_ptr = sofia_find_gateway_subscription(sofia_private->gateway, o->o_type))) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Could not find gateway subscription. Gateway: %s. Subscription Event: %s\n",
|
||||||
|
sofia_private->gateway->name, o->o_type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the subscription status for the subscription */
|
||||||
|
switch (status) {
|
||||||
|
case 200:
|
||||||
|
/* TODO: in the spec it is possible for the other side to change the original expiry time,
|
||||||
|
* this needs to be researched (eg, what sip header this information will be in) and implemented.
|
||||||
|
* Although, since it seems the sofia stack is pretty much handling the subscription expiration
|
||||||
|
* anyway, then maybe its not even worth bothering.
|
||||||
|
*/
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "got 200 OK response, updated state to SUB_STATE_SUBSCRIBE.\n");
|
||||||
|
gw_sub_ptr->state = SUB_STATE_SUBSCRIBE;
|
||||||
|
break;
|
||||||
|
case 100:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "status (%d) != 200, updated state to SUB_STATE_FAILED.\n", status);
|
||||||
|
gw_sub_ptr->state = SUB_STATE_FAILED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sofia_presence_handle_sip_i_publish(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
|
void sofia_presence_handle_sip_i_publish(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
|
||||||
|
@ -77,6 +77,107 @@ void sofia_reg_unregister(sofia_profile_t *profile)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sofia_sub_check_gateway(sofia_profile_t *profile, time_t now)
|
||||||
|
{
|
||||||
|
/* NOTE: A lot of the mechanism in place here for refreshing subscriptions is
|
||||||
|
* pretty much redundant, as the sofia stack takes it upon itself to
|
||||||
|
* refresh subscriptions on its own, based on the value of the Expires
|
||||||
|
* header (which we control in the outgoing subscription request)
|
||||||
|
*/
|
||||||
|
sofia_gateway_t *gateway_ptr;
|
||||||
|
|
||||||
|
for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
|
||||||
|
sofia_gateway_subscription_t *gw_sub_ptr;
|
||||||
|
|
||||||
|
for (gw_sub_ptr = gateway_ptr->subscriptions; gw_sub_ptr; gw_sub_ptr = gw_sub_ptr->next) {
|
||||||
|
int ss_state = nua_callstate_authenticating;
|
||||||
|
sub_state_t ostate = gw_sub_ptr->state;
|
||||||
|
|
||||||
|
if (!now) {
|
||||||
|
gw_sub_ptr->state = ostate = SUB_STATE_UNSUBED;
|
||||||
|
gw_sub_ptr->expires_str = "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ostate) {
|
||||||
|
case SUB_STATE_NOSUB:
|
||||||
|
break;
|
||||||
|
case SUB_STATE_SUBSCRIBE:
|
||||||
|
gw_sub_ptr->expires = now + gw_sub_ptr->freq;
|
||||||
|
gw_sub_ptr->state = SUB_STATE_SUBED;
|
||||||
|
break;
|
||||||
|
case SUB_STATE_UNSUBSCRIBE:
|
||||||
|
gw_sub_ptr->state = SUB_STATE_NOSUB;
|
||||||
|
|
||||||
|
/* not tested .. */
|
||||||
|
nua_unsubscribe(gateway_ptr->nh,
|
||||||
|
NUTAG_URL(gateway_ptr->register_url),
|
||||||
|
SIPTAG_EVENT_STR(gw_sub_ptr->event),
|
||||||
|
SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type),
|
||||||
|
SIPTAG_TO_STR(gateway_ptr->register_from),
|
||||||
|
SIPTAG_FROM_STR(gateway_ptr->register_from),
|
||||||
|
SIPTAG_CONTACT_STR(gateway_ptr->register_contact),
|
||||||
|
TAG_NULL());
|
||||||
|
|
||||||
|
break;
|
||||||
|
case SUB_STATE_UNSUBED:
|
||||||
|
if ((gateway_ptr->nh = nua_handle(gateway_ptr->profile->nua, NULL,
|
||||||
|
NUTAG_URL(gateway_ptr->register_proxy),
|
||||||
|
SIPTAG_TO_STR(gateway_ptr->register_to),
|
||||||
|
NUTAG_CALLSTATE_REF(ss_state),
|
||||||
|
SIPTAG_FROM_STR(gateway_ptr->register_from), TAG_END()))) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "subscribing to [%s] on gateway [%s]\n", gw_sub_ptr->event, gateway_ptr->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
gateway_ptr->sofia_private = malloc(sizeof(*gateway_ptr->sofia_private));
|
||||||
|
switch_assert(gateway_ptr->sofia_private);
|
||||||
|
|
||||||
|
memset(gateway_ptr->sofia_private, 0, sizeof(*gateway_ptr->sofia_private));
|
||||||
|
|
||||||
|
gateway_ptr->sofia_private->gateway = gateway_ptr;
|
||||||
|
nua_handle_bind(gateway_ptr->nh, gateway_ptr->sofia_private);
|
||||||
|
|
||||||
|
if (now) {
|
||||||
|
nua_subscribe(gateway_ptr->nh,
|
||||||
|
NUTAG_URL(gateway_ptr->register_url),
|
||||||
|
SIPTAG_EVENT_STR(gw_sub_ptr->event),
|
||||||
|
SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type),
|
||||||
|
SIPTAG_TO_STR(gateway_ptr->register_from),
|
||||||
|
SIPTAG_FROM_STR(gateway_ptr->register_from),
|
||||||
|
SIPTAG_CONTACT_STR(gateway_ptr->register_contact),
|
||||||
|
SIPTAG_EXPIRES_STR(gw_sub_ptr->expires_str), // sofia stack bases its auto-refresh stuff on this
|
||||||
|
TAG_NULL());
|
||||||
|
gw_sub_ptr->retry = now + gw_sub_ptr->retry_seconds;
|
||||||
|
} else {
|
||||||
|
nua_unsubscribe(gateway_ptr->nh,
|
||||||
|
NUTAG_URL(gateway_ptr->register_url),
|
||||||
|
SIPTAG_EVENT_STR(gw_sub_ptr->event),
|
||||||
|
SIPTAG_ACCEPT_STR(gw_sub_ptr->content_type),
|
||||||
|
SIPTAG_FROM_STR(gateway_ptr->register_from),
|
||||||
|
SIPTAG_TO_STR(gateway_ptr->register_from),
|
||||||
|
SIPTAG_CONTACT_STR(gateway_ptr->register_contact),
|
||||||
|
SIPTAG_EXPIRES_STR(gw_sub_ptr->expires_str),
|
||||||
|
TAG_NULL());
|
||||||
|
}
|
||||||
|
gw_sub_ptr->state = SUB_STATE_TRYING;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SUB_STATE_FAILED:
|
||||||
|
case SUB_STATE_TRYING:
|
||||||
|
if (gw_sub_ptr->retry && now >= gw_sub_ptr->retry) {
|
||||||
|
gw_sub_ptr->state = SUB_STATE_UNSUBED;
|
||||||
|
gw_sub_ptr->retry = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (now >= gw_sub_ptr->expires) {
|
||||||
|
gw_sub_ptr->state = SUB_STATE_UNSUBED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now)
|
void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now)
|
||||||
{
|
{
|
||||||
sofia_gateway_t *gateway_ptr, *last = NULL;
|
sofia_gateway_t *gateway_ptr, *last = NULL;
|
||||||
|
@ -142,6 +142,7 @@ static char *EVENT_NAMES[] = {
|
|||||||
"DTMF",
|
"DTMF",
|
||||||
"MESSAGE",
|
"MESSAGE",
|
||||||
"PRESENCE_IN",
|
"PRESENCE_IN",
|
||||||
|
"NOTIFY_IN",
|
||||||
"PRESENCE_OUT",
|
"PRESENCE_OUT",
|
||||||
"PRESENCE_PROBE",
|
"PRESENCE_PROBE",
|
||||||
"MESSAGE_WAITING",
|
"MESSAGE_WAITING",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user