Commit 5cdf1687 authored by Pekka Pessi's avatar Pekka Pessi

nua: add NUTAG_APPL_EVENT() tag (sofia-sip/nua_tag.h)

parent b5b1b410
......@@ -857,6 +857,118 @@ START_TEST(notify_6_3_5)
}
END_TEST
START_TEST(notify_6_3_6)
{
nua_handle_t *nh;
struct event *subscribe;
struct message *notify, *response;
sip_t *sip;
S2_CASE("6.3.6", "Explicit refresh with NUTAG_APPL_EVENT()",
"Process subscription refresh by application");
nua_set_params(nua,
NUTAG_APPL_METHOD("SUBSCRIBE"),
NUTAG_APPL_EVENT("presence"),
SIPTAG_ALLOW_EVENTS_STR("presence"),
TAG_END());
fail_unless_event(nua_r_set_params, 200);
s2_sip_request_to(dialog, SIP_METHOD_SUBSCRIBE, NULL,
SIPTAG_EVENT_STR("presence"),
TAG_END());
subscribe = s2_wait_for_event(nua_i_subscribe, 100);
nh = subscribe->nh;
nua_respond(nh, SIP_202_ACCEPTED,
NUTAG_WITH_SAVED(subscribe->event),
TAG_END());
s2_free_event(subscribe);
response = s2_sip_wait_for_response(202, SIP_METHOD_SUBSCRIBE);
s2_sip_update_dialog(dialog, response);
fail_unless(response->sip->sip_expires != NULL);
s2_sip_free_message(response);
nua_notify(nh,
NUTAG_SUBSTATE(nua_substate_active),
SIPTAG_PAYLOAD_STR(presence_closed),
TAG_END());
notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY);
fail_unless(notify != NULL);
sip = notify->sip;
fail_unless(sip->sip_subscription_state != NULL);
fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate,
"active"));
s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END());
fail_unless_event(nua_r_notify, 200);
s2_sip_request_to(dialog, SIP_METHOD_SUBSCRIBE, NULL,
SIPTAG_EVENT_STR("presence"),
TAG_END());
subscribe = s2_wait_for_event(nua_i_subscribe, 100);
nh = subscribe->nh;
nua_respond(nh, SIP_202_ACCEPTED,
NUTAG_WITH_SAVED(subscribe->event),
TAG_END());
s2_free_event(subscribe);
response = s2_sip_wait_for_response(202, SIP_METHOD_SUBSCRIBE);
s2_sip_update_dialog(dialog, response);
fail_unless(response->sip->sip_expires != NULL);
s2_sip_free_message(response);
notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY);
fail_unless(notify != NULL);
sip = notify->sip;
fail_unless(sip->sip_subscription_state != NULL);
fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate,
"active"));
s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END());
fail_unless_event(nua_r_notify, 200);
/* Now clear list of application events */
nua_set_params(nua,
NUTAG_APPL_EVENT(NULL),
NUTAG_SUB_EXPIRES(360),
TAG_END());
fail_unless_event(nua_r_set_params, 200);
s2_sip_request_to(dialog, SIP_METHOD_SUBSCRIBE, NULL,
SIPTAG_EVENT_STR("presence"),
TAG_END());
/* Automatically responded && refreshed */
subscribe = s2_wait_for_event(nua_i_subscribe, 200);
s2_free_event(subscribe);
response = s2_sip_wait_for_response(200, SIP_METHOD_SUBSCRIBE);
s2_sip_update_dialog(dialog, response);
fail_unless(response->sip->sip_expires != NULL);
fail_unless(response->sip->sip_expires->ex_delta == 360);
s2_sip_free_message(response);
notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY);
fail_unless(notify != NULL);
sip = notify->sip;
fail_unless(sip->sip_subscription_state != NULL);
fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate,
"active"));
s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END());
fail_unless_event(nua_r_notify, 200);
nua_handle_destroy(nh);
notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY);
sip = notify->sip;
fail_unless(sip->sip_subscription_state != NULL);
fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate,
"terminated"));
s2_sip_respond_to(notify, dialog, SIP_481_NO_TRANSACTION, TAG_END());
}
END_TEST
TCase *notifier_tcase(int threading)
{
TCase *tc = tcase_create("6.3 - Basic event server with NOTIFY ");
......@@ -871,6 +983,7 @@ TCase *notifier_tcase(int threading)
tcase_add_test(tc, notify_6_3_3);
tcase_add_test(tc, notify_6_3_4);
tcase_add_test(tc, notify_6_3_5);
tcase_add_test(tc, notify_6_3_6);
}
return tc;
}
......
......@@ -244,6 +244,7 @@ int nua_subscribe_server_preprocess(nua_server_request_t *sr)
/* Maximum expiration time */
unsigned long expires = sip->sip_expires ? sip->sip_expires->ex_delta : 3600;
sip_time_t now = sip_now();
sip_allow_events_t *appl_event = NH_PGET(nh, appl_event);
assert(nh && nh->nh_nua->nua_dhandle != nh);
......@@ -255,10 +256,17 @@ int nua_subscribe_server_preprocess(nua_server_request_t *sr)
if (du == NULL)
return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR);
}
else {
else if (!msg_header_find_param((void *)appl_event, event)) {
unsigned max_expires;
/* Refresh existing subscription */
if (su_strmatch(event, "refer"))
expires = NH_PGET(nh, refer_expires);
max_expires = NH_PGET(nh, refer_expires);
else
max_expires = NH_PGET(nh, sub_expires);
if (expires >= max_expires)
expires = max_expires;
SR_STATUS1(sr, SIP_200_OK);
}
......@@ -796,6 +804,10 @@ static void nua_notify_usage_refresh(nua_handle_t *nh,
if (cr) {
int terminating = 0;
SU_DEBUG_7(("%s(%p, %p, %p): using existing cr=%p\n",
"nua_notify_usage_refresh",
(void *)nh, (void *)ds, (void *)du, (void *)cr));
if (nu->nu_expires && nu->nu_expires <= now)
terminating = 1;
else if (nu->nu_requested && nu->nu_requested <= now)
......@@ -805,6 +817,11 @@ static void nua_notify_usage_refresh(nua_handle_t *nh,
return;
}
else {
SU_DEBUG_7(("%s(%p, %p, %p): new NOTIFY cr for %s\n",
"nua_notify_usage_refresh",
(void *)nh, (void *)ds, (void *)du,
du->du_event ? du->du_event->o_type : "<implicit>"));
if (nua_client_create(nh, e, &nua_notify_client_methods, NULL) >= 0)
return;
}
......
......@@ -274,6 +274,8 @@ int nua_stack_init_instance(nua_handle_t *nh, tagi_t const *tags)
* NUTAG_ALLOW(), SIPTAG_ALLOW(), and SIPTAG_ALLOW_STR() \n
* NUTAG_ALLOW_EVENTS(), SIPTAG_ALLOW_EVENTS(), and
* SIPTAG_ALLOW_EVENTS_STR() \n
* NUTAG_APPL_EVENT() \n
* NUTAG_APPL_METHOD() \n
* NUTAG_AUTO100() \n
* NUTAG_AUTO302() \n
* NUTAG_AUTO305() \n
......@@ -401,6 +403,8 @@ int nua_stack_init_instance(nua_handle_t *nh, tagi_t const *tags)
* NUTAG_ALLOW(), SIPTAG_ALLOW(), and SIPTAG_ALLOW_STR() \n
* NUTAG_ALLOW_EVENTS(), SIPTAG_ALLOW_EVENTS(), and
* SIPTAG_ALLOW_EVENTS_STR() \n
* NUTAG_APPL_EVENT() \n
* NUTAG_APPL_METHOD() \n
* NUTAG_AUTH_CACHE() \n
* NUTAG_AUTO100() \n
* NUTAG_AUTO302() \n
......@@ -926,6 +930,28 @@ static int nhp_set_tags(su_home_t *home,
else if (ok)
NHP_SET(nhp, allow_events, allow_events);
}
else if (tag == nutag_appl_event) {
int ok;
sip_allow_events_t *appl_event = NULL;
tag_value_t value = t->t_value;
if (value == 0)
value = (tag_value_t)NUA_NONE;
ok = nhp_merge_lists(home,
sip_allow_events_class,
&appl_event,
nhp->nhp_appl_event,
NHP_ISSET(nhp, appl_event), /* already set */
0, /* dup it, don't make */
1, /* merge with old value */
value);
if (ok < 0)
return -1;
else if (ok)
NHP_SET(nhp, appl_event, appl_event);
}
/* NUTAG_APPL_METHOD(appl_method) */
else if (tag == nutag_appl_method) {
if (t->t_value == 0) {
......@@ -1168,6 +1194,7 @@ int nhp_save_params(nua_handle_t *nh,
NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, allow);
NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, supported);
NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, allow_events);
NHP_ZAP_OVERRIDEN(old, dst, msg_header_free, appl_event);
NHP_ZAP_OVERRIDEN(old, dst, su_free, user_agent);
NHP_ZAP_OVERRIDEN(old, dst, su_free, organization);
NHP_ZAP_OVERRIDEN(old, dst, su_free, m_display);
......@@ -1486,6 +1513,7 @@ int nua_stack_set_smime_params(nua_t *nua, tagi_t const *tags)
* @param sip NULL
* @param tags
* NUTAG_ACCEPT_MULTIPART() \n
* NUTAG_APPL_EVENT() \n
* NUTAG_APPL_METHOD() \n
* NUTAG_AUTH_CACHE() \n
* NUTAG_AUTOACK() \n
......@@ -1709,6 +1737,7 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
TIF_STR(NUTAG_APPL_METHOD, appl_method),
TIF(SIPTAG_ALLOW_EVENTS, allow_events),
TIF_STR(SIPTAG_ALLOW_EVENTS_STR, allow_events),
TIF_STR(NUTAG_APPL_EVENT, appl_event),
TIF_SIP(SIPTAG_USER_AGENT, user_agent),
TIF(SIPTAG_USER_AGENT_STR, user_agent),
TIF(NUTAG_USER_AGENT, user_agent),
......
......@@ -135,6 +135,7 @@ struct nua_handle_preferences
sip_allow_t *nhp_allow;
sip_supported_t *nhp_supported;
sip_allow_events_t *nhp_allow_events;
sip_allow_events_t *nhp_appl_event;
char const *nhp_user_agent;
char const *nhp_organization;
......@@ -210,6 +211,7 @@ struct nua_handle_preferences
unsigned nhb_supported:1;
unsigned nhb_allow_events:1;
unsigned nhb_appl_event:1;
unsigned nhb_user_agent:1;
unsigned nhb_organization:1;
......
......@@ -292,6 +292,7 @@
* - NUTAG_SUB_EXPIRES()
* - NUTAG_ALLOW_EVENTS(), SIPTAG_ALLOW_EVENTS(), and
* SIPTAG_ALLOW_EVENTS_STR()
* - NUTAG_APPL_EVENT()
* - @ref NUTAG_ALLOW("SUBSCRIBE"),
* @ref NUTAG_APPL_METHOD("SUBSCRIBE")
*
......@@ -2771,8 +2772,9 @@ tag_typedef_t nutag_allow = STRTAG_TYPEDEF(allow);
* Valid event name, or comma-separated list of them.
*
* @sa @AllowEvents, @RFC3265, @RFC3903, #nua_i_subscribe, #nua_i_publish,
* #nua_i_refer, nua_notify(), nua_refer(),
* nua_subscribe(), nua_publish(), SIPTAG_ALLOW_EVENTS(),
* SIPTAG_ALLOW_EVENTS_STR()
* SIPTAG_ALLOW_EVENTS_STR(), NUTAG_APPL_EVENT()
*
* @NEW_1_12_4.
*
......@@ -2785,6 +2787,45 @@ tag_typedef_t nutag_allow_events = STRTAG_TYPEDEF(allow_events);
*/
/**@def NUTAG_APPL_EVENT()
*
* List events which the application handles always.
*
* When nua stack receives a SUBSCRIBE request for an already existing
* subscription, it can either automatically refresh the subscription
* or, if the event name is listed in NUTAG_APPL_EVENT() list, it
* is passed to application, pass the SUBSCRIBE request to application.
*
* The list of application events is cleared with
* NUTAG_APPL_EVENT(NULL).
*
* @par Used with
* nua_set_params() \n
* nua_set_hparams() \n
* any handle-specific nua call
*
* @par Parameter type
* char const *
*
* @par Values
* Valid event name, or comma-separated list of them.
*
* @sa @AllowEvents, @RFC3265, @RFC3903, #nua_i_subscribe,
* #nua_i_publish, #nua_i_refer, nua_notify(), nua_refer(),
* nua_subscribe(), nua_publish(), NUTAG_ALLOW_EVENTS(),
*
* @NEW_UNRELEASED
*
* Corresponding tag taking reference parameter is
* NUTAG_APPL_EVENT_REF().
*/
tag_typedef_t nutag_appl_event = STRTAG_TYPEDEF(appl_event);
/**@def NUTAG_APPL_EVENT_REF(x)
* Reference tag for NUTAG_APPL_EVENT().
*/
/**@def NUTAG_APPL_METHOD()
*
* Indicate that a method (or methods) are handled by application.
......
......@@ -65,6 +65,8 @@ typedef NUA_MAGIC_T nua_magic_t;
/** Application context for NUA handle. */
typedef NUA_HMAGIC_T nua_hmagic_t;
#define NUA_NONE ((void *)(intptr_t)-1)
/**Network change event levels given to NUTAG_DETECT_NETWORK_UPDATES().
*
* @sa NUTAG_DETECT_NETWORK_UPDATES(), #nua_i_network_changed
......
......@@ -475,7 +475,6 @@ SOFIAPUBVAR tag_typedef_t nutag_appl_method;
#define NUTAG_APPL_METHOD_REF(x) nutag_appl_method_ref, tag_str_vr(&(x))
SOFIAPUBVAR tag_typedef_t nutag_appl_method_ref;
#define NUTAG_SUPPORTED(x) nutag_supported, tag_str_v(x)
SOFIAPUBVAR tag_typedef_t nutag_supported;
#define NUTAG_SUPPORTED_REF(x) nutag_supported_ref, tag_str_vr(&(x))
......@@ -486,6 +485,11 @@ SOFIAPUBVAR tag_typedef_t nutag_allow_events;
#define NUTAG_ALLOW_EVENTS_REF(x) nutag_allow_events_ref, tag_str_vr(&(x))
SOFIAPUBVAR tag_typedef_t nutag_allow_events_ref;
#define NUTAG_APPL_EVENT(x) nutag_appl_event, tag_str_v(x)
SOFIAPUBVAR tag_typedef_t nutag_appl_event;
#define NUTAG_APPL_EVENT_REF(x) nutag_appl_event_ref, tag_str_vr(&(x))
SOFIAPUBVAR tag_typedef_t nutag_appl_event_ref;
#define NUTAG_CALLSTATE(x) nutag_callstate, tag_int_v(x)
SOFIAPUBVAR tag_typedef_t nutag_callstate;
#define NUTAG_CALLSTATE_REF(x) nutag_callstate_ref, tag_int_vr(&(x))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment