freeswitch/libs/sofia-sip/libsofia-sip-ua/nua/test_simple.c

1838 lines
54 KiB
C

/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2005 Nokia Corporation.
*
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
/**@CFILE test_nua_simple.c
* @brief NUA-11: Test SIMPLE methods: MESSAGE, PUBLISH and SUBSCRIBE/NOTIFY.
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Martti Mela <Martti Mela@nokia.com>
*
* @date Created: Wed Aug 17 12:12:12 EEST 2005 ppessi
*/
#include "config.h"
#include "test_nua.h"
#include <sofia-sip/su_tag_class.h>
#if HAVE_FUNC
#elif HAVE_FUNCTION
#define __func__ __FUNCTION__
#else
#define __func__ "test_simple"
#endif
extern int accept_request(CONDITION_PARAMS);
int save_until_nth_final_response(CONDITION_PARAMS);
int accept_n_notifys(CONDITION_PARAMS);
int test_message(struct context *ctx)
{
BEGIN();
struct endpoint *a = &ctx->a, *b = &ctx->b;
struct call *a_call = a->call, *b_call = b->call;
struct event *e;
sip_t const *sip;
url_t url[1];
/* Message test
A B
|-------MESSAGE----->|
|<-------200---------|
| |
*/
if (print_headings)
printf("TEST NUA-11.1.1: MESSAGE\n");
if (ctx->proxy_tests)
*url = *b->to->a_url;
else
*url = *b->contact->m_url;
/* Test that query part is included in request sent to B */
url->url_headers = "organization=United%20Testers";
TEST_1(a_call->nh = nua_handle(a->nua, a_call, TAG_END()));
MESSAGE(a, a_call, a_call->nh,
NUTAG_URL(url),
SIPTAG_SUBJECT_STR("NUA-11.1.1"),
SIPTAG_CONTENT_TYPE_STR("text/plain"),
SIPTAG_PAYLOAD_STR("Hello hellO!\n"),
TAG_END());
run_ab_until(ctx, -1, save_until_final_response, -1, save_until_received);
/* Client events:
nua_message(), nua_r_message
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_message);
TEST(e->data->e_status, 200);
TEST_1(!e->next);
/*
Server events:
nua_i_message
*/
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_message);
TEST(e->data->e_status, 200);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_subject && sip->sip_subject->g_string);
TEST_S(sip->sip_subject->g_string, "NUA-11.1.1");
TEST_1(sip->sip_organization);
TEST_S(sip->sip_organization->g_string, "United Testers");
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
free_events_in_list(ctx, b->events);
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
if (print_headings)
printf("TEST NUA-11.1.1: PASSED\n");
/* MESSAGE as application method
A B
|-------MESSAGE----->|
|<-------202---------|
| |
*/
if (print_headings)
printf("TEST NUA-11.1.2: MESSAGE\n");
nua_set_params(b->nua, NUTAG_APPL_METHOD("MESSAGE"), TAG_END());
run_b_until(ctx, nua_r_set_params, until_final_response);
TEST_1(a_call->nh = nua_handle(a->nua, a_call, TAG_END()));
MESSAGE(a, a_call, a_call->nh,
NUTAG_URL(url),
SIPTAG_SUBJECT_STR("NUA-11.1.2"),
SIPTAG_CONTENT_TYPE_STR("text/plain"),
SIPTAG_PAYLOAD_STR("Hello hellO!\n"),
TAG_END());
run_ab_until(ctx, -1, save_until_final_response, -1, accept_request);
/* Client events:
nua_message(), nua_r_message
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_message);
TEST(e->data->e_status, 202);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip_user_agent(sip));
TEST_S(sip_user_agent(sip)->g_value, "007");
TEST_1(!e->next);
/*
Server events:
nua_i_message
*/
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_message);
TEST(e->data->e_status, 100);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_subject && sip->sip_subject->g_string);
TEST_S(sip->sip_subject->g_string, "NUA-11.1.2");
TEST_1(sip->sip_organization);
TEST_S(sip->sip_organization->g_string, "United Testers");
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
free_events_in_list(ctx, b->events);
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
if (print_headings)
printf("TEST NUA-11.1.2: PASSED\n");
/* Message test
A
|-------MESSAGE--\
|<---------------/
|--------200-----\
|<---------------/
|
*/
if (print_headings)
printf("TEST NUA-11.2: MESSAGE to myself\n");
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(a->to), TAG_END()));
MESSAGE(a, a_call, a_call->nh,
/* We cannot reach us by using our contact! */
NUTAG_URL(!ctx->p && !ctx->proxy_tests ? a->contact->m_url : NULL),
SIPTAG_SUBJECT_STR("NUA-11.2"),
SIPTAG_CONTENT_TYPE_STR("text/plain"),
SIPTAG_PAYLOAD_STR("Hello hellO!\n"),
TAG_END());
run_a_until(ctx, -1, save_until_final_response);
/* Events:
nua_message(), nua_i_message, nua_r_message
*/
TEST_1(e = a->specials->head);
while (e->data->e_event == nua_i_outbound)
e = e->next;
TEST_E(e->data->e_event, nua_i_message);
TEST(e->data->e_status, 200);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_subject && sip->sip_subject->g_string);
TEST_S(sip->sip_subject->g_string, "NUA-11.2");
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_message);
TEST(e->data->e_status, 200);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
free_events_in_list(ctx, a->specials);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
if (print_headings)
printf("TEST NUA-11.2: PASSED\n");
END();
}
int accept_request(CONDITION_PARAMS)
{
msg_t *with = nua_current_request(nua);
if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
return 0;
save_event_in_list(ctx, event, ep, call);
if (status < 200) {
RESPOND(ep, call, nh, SIP_202_ACCEPTED,
NUTAG_WITH(with),
SIPTAG_USER_AGENT_STR("007"),
TAG_END());
return 1;
}
return 0;
}
char const *test_etag = "tagtag";
int respond_with_etag(CONDITION_PARAMS)
{
msg_t *with = nua_current_request(nua);
if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
return 1;
save_event_in_list(ctx, event, ep, call);
switch (event) {
char const *etag;
case nua_i_publish:
etag = sip->sip_if_match ? sip->sip_if_match->g_value : NULL;
if (sip->sip_if_match && (etag == NULL || strcmp(etag, test_etag))) {
RESPOND(ep, call, nh, SIP_412_PRECONDITION_FAILED,
NUTAG_WITH(with),
TAG_END());
}
else {
RESPOND(ep, call, nh, SIP_200_OK,
NUTAG_WITH(with),
SIPTAG_ETAG_STR(test_etag),
SIPTAG_EXPIRES_STR("3600"),
SIPTAG_EXPIRES(sip->sip_expires), /* overrides 3600 */
TAG_END());
}
return 1;
default:
return 0;
}
}
static int close_handle(CONDITION_PARAMS)
{
if (call->nh == nh)
call->nh = NULL;
nua_handle_destroy(nh);
return 1;
}
int test_publish(struct context *ctx)
{
BEGIN();
struct endpoint *a = &ctx->a, *b = &ctx->b;
struct call *a_call = a->call, *b_call = b->call;
struct event *e;
sip_t const *sip;
/* PUBLISH test
A B
|-------PUBLISH----->|
|<-------405---------| (method not allowed by default)
| |
|-------PUBLISH----->|
|<-------501---------| (no events allowed)
| |
|-------PUBLISH----->|
|<-------489---------| (event not allowed by default)
| |
|-------PUBLISH----->|
|<-------200---------| (event allowed, responded)
| |
|-----un-PUBLISH---->|
|<-------200---------| (event allowed, responded)
*/
if (print_headings)
printf("TEST NUA-11.3: PUBLISH\n");
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
PUBLISH(a, a_call, a_call->nh,
TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
SIPTAG_EVENT_STR("presence"),
SIPTAG_CONTENT_TYPE_STR("text/urllist"),
SIPTAG_PAYLOAD_STR("sip:example.com\n"),
TAG_END());
run_ab_until(ctx, -1, save_until_final_response, -1, NULL);
/* Client events:
nua_publish(), nua_r_publish
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_publish);
TEST(e->data->e_status, 405);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
free_events_in_list(ctx, b->events);
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
nua_set_params(b->nua, NUTAG_ALLOW("PUBLISH"), TAG_END());
run_b_until(ctx, nua_r_set_params, until_final_response);
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
PUBLISH(a, a_call, a_call->nh,
TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
SIPTAG_EVENT_STR("presence"),
SIPTAG_CONTENT_TYPE_STR("text/urllist"),
SIPTAG_PAYLOAD_STR("sip:example.com\n"),
TAG_END());
run_a_until(ctx, -1, save_until_final_response);
/* Client events:
nua_publish(), nua_r_publish
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_publish);
TEST(e->data->e_status, 501); /* Not implemented */
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
/* Allow presence event */
nua_set_params(b->nua, NUTAG_ALLOW_EVENTS("presence"), TAG_END());
run_b_until(ctx, nua_r_set_params, until_final_response);
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
PUBLISH(a, a_call, a_call->nh,
TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
SIPTAG_EVENT_STR("reg"),
SIPTAG_CONTENT_TYPE_STR("text/urllist"),
SIPTAG_PAYLOAD_STR("sip:example.com\n"),
TAG_END());
run_a_until(ctx, -1, save_until_final_response);
/* Client events:
nua_publish(), nua_r_publish
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_publish);
TEST(e->data->e_status, 489); /* Bad Event */
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
PUBLISH(a, a_call, a_call->nh,
TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
SIPTAG_EVENT_STR("presence"),
SIPTAG_CONTENT_TYPE_STR("text/urllist"),
SIPTAG_PAYLOAD_STR("sip:example.com\n"),
SIPTAG_EXPIRES_STR("5"),
TAG_END());
run_ab_until(ctx, -1, save_until_final_response, -1, respond_with_etag);
/* Client events:
nua_publish(), nua_r_publish
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_publish);
TEST(e->data->e_status, 200);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_etag);
TEST_S(sip->sip_etag->g_string, test_etag);
TEST_1(!e->next);
/*
Server events:
nua_i_publish
*/
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_publish);
TEST(e->data->e_status, 100);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
free_events_in_list(ctx, b->events);
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
if (!ctx->expensive && 0)
goto skip_republish;
run_ab_until(ctx, -1, save_until_final_response, -1, respond_with_etag);
/* Client events: nua_r_publish
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_publish);
TEST(e->data->e_status, 200);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_etag);
TEST_S(sip->sip_etag->g_string, test_etag);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
/*
Server events:
nua_i_publish
*/
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_publish);
TEST(e->data->e_status, 100);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_if_match);
TEST_S(sip->sip_if_match->g_string, "tagtag");
TEST_1(!sip->sip_content_type);
TEST_1(!sip->sip_payload);
TEST_1(!e->next);
free_events_in_list(ctx, b->events);
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
skip_republish:
UNPUBLISH(a, a_call, a_call->nh, TAG_END());
run_ab_until(ctx, -1, save_until_final_response, -1, respond_with_etag);
/* Client events:
nua_publish(), nua_r_publish
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_unpublish);
TEST(e->data->e_status, 200);
TEST_1(!e->next);
/*
Server events:
nua_i_publish
*/
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_publish);
TEST(e->data->e_status, 100);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
free_events_in_list(ctx, b->events);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
/* Let server close handle without responding to PUBLISH */
PUBLISH(a, a_call, a_call->nh,
TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
SIPTAG_EVENT_STR("presence"),
SIPTAG_CONTENT_TYPE_STR("text/urllist"),
SIPTAG_PAYLOAD_STR("sip:example.com\n"),
TAG_END());
run_ab_until(ctx, -1, save_until_final_response, -1, close_handle);
/* Client events:
nua_publish(), nua_r_publish
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_publish);
TEST(e->data->e_status, 500);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
/* No Event header */
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
PUBLISH(a, a_call, a_call->nh,
TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
SIPTAG_CONTENT_TYPE_STR("text/urllist"),
SIPTAG_PAYLOAD_STR("sip:example.com\n"),
TAG_END());
run_ab_until(ctx, -1, save_until_final_response, -1, save_events);
/* Client events:
nua_publish(), nua_r_publish
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_publish);
TEST(e->data->e_status, 489);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
/*
Server events: nothing
*/
TEST_1(!b->events->head);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
if (print_headings)
printf("TEST NUA-11.3: PASSED\n");
END();
}
static char const presence_open[] =
"<?xml version='1.0' encoding='UTF-8'?>\n"
"<presence xmlns='urn:ietf:params:xml:ns:cpim-pidf' \n"
" entity='pres:bob@example.org'>\n"
" <tuple id='ksac9udshce'>\n"
" <status><basic>open</basic></status>\n"
" <contact priority='1.0'>sip:bob@example.org</contact>\n"
" </tuple>\n"
"</presence>\n";
static char const presence_closed[] =
"<?xml version='1.0' encoding='UTF-8'?>\n"
"<presence xmlns='urn:ietf:params:xml:ns:cpim-pidf' \n"
" entity='pres:bob@example.org'>\n"
" <tuple id='ksac9udshce'>\n"
" <status><basic>closed</basic></status>\n"
" </tuple>\n"
"</presence>\n";
int accept_and_notify_twice(CONDITION_PARAMS)
{
msg_t *with = nua_current_request(nua);
if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
return 0;
save_event_in_list(ctx, event, ep, call);
switch (event) {
case nua_i_subscribe:
if (status < 200) {
NOTIFY(ep, call, nh,
SIPTAG_EVENT(sip->sip_event),
SIPTAG_CONTENT_TYPE_STR("application/pidf+xml"),
SIPTAG_PAYLOAD_STR(presence_closed),
NUTAG_SUBSTATE(nua_substate_pending),
TAG_END());
NOTIFY(ep, call, nh,
SIPTAG_EVENT(sip->sip_event),
SIPTAG_CONTENT_TYPE_STR("application/pidf+xml"),
SIPTAG_PAYLOAD_STR(presence_open),
NUTAG_SUBSTATE(nua_substate_active),
TAG_END());
RESPOND(ep, call, nh, SIP_202_ACCEPTED,
NUTAG_WITH(with),
SIPTAG_EXPIRES_STR("360"),
TAG_END());
}
return 0;
case nua_r_notify:
return status >= 200 &&
tl_find(tags, nutag_substate)->t_value == nua_substate_active;
default:
return 0;
}
}
int accept_and_notify(CONDITION_PARAMS)
{
msg_t *with = nua_current_request(nua);
if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
return 0;
save_event_in_list(ctx, event, ep, call);
switch (event) {
case nua_i_subscribe:
if (status < 200) {
RESPOND(ep, call, nh, SIP_202_ACCEPTED,
NUTAG_WITH(with),
SIPTAG_EXPIRES_STR("360"),
TAG_END());
NOTIFY(ep, call, nh,
SIPTAG_EVENT(sip->sip_event),
SIPTAG_CONTENT_TYPE_STR("application/pidf+xml"),
SIPTAG_PAYLOAD_STR(presence_closed),
NUTAG_SUBSTATE(nua_substate_pending),
TAG_END());
}
return 0;
case nua_r_notify:
return status >= 200;
default:
return 0;
}
}
int save_and_notify(CONDITION_PARAMS)
{
if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
return 0;
save_event_in_list(ctx, event, ep, call);
switch (event) {
case nua_i_subscribe:
NOTIFY(ep, call, nh,
SIPTAG_EVENT(sip->sip_event),
SIPTAG_CONTENT_TYPE_STR("application/pidf+xml"),
SIPTAG_PAYLOAD_STR(presence_closed),
NUTAG_SUBSTATE(nua_substate_active),
TAG_END());
return 0;
case nua_r_notify:
return status >= 200;
default:
return 0;
}
}
extern int save_until_notified_and_responded(CONDITION_PARAMS);
extern int save_until_notified(CONDITION_PARAMS);
int test_subscribe_notify(struct context *ctx)
{
BEGIN();
struct endpoint *a = &ctx->a, *b = &ctx->b;
struct call *a_call = a->call, *b_call = b->call;
struct event *e, *en1, *en2, *es;
sip_t const *sip;
tagi_t const *n_tags, *r_tags;
if (print_headings)
printf("TEST NUA-11.4: notifier server using nua_notify()\n");
if (print_headings)
printf("TEST NUA-11.4.1: establishing subscription\n");
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
SUBSCRIBE(a, a_call, a_call->nh, NUTAG_URL(b->contact->m_url),
SIPTAG_EVENT_STR("presence"),
SIPTAG_EXPIRES_STR("333"),
SIPTAG_ACCEPT_STR("application/xpidf, application/pidf+xml"),
TAG_END());
run_ab_until(ctx, -1, save_until_notified_and_responded,
-1, accept_and_notify_twice);
/* Client events:
nua_subscribe(), nua_i_notify/nua_r_subscribe/nua_i_notify
*/
for (en1 = en2 = es = NULL, e = a->events->head; e; e = e->next) {
if (en1 == NULL && e->data->e_event == nua_i_notify)
en1 = e;
else if (en2 == NULL && e->data->e_event == nua_i_notify)
en2 = e;
else if (e->data->e_event == nua_r_subscribe)
es = e;
else
TEST_1(!e);
}
TEST_1(e = en1);
TEST_E(e->data->e_event, nua_i_notify);
TEST_1(tl_find(e->data->e_tags, nutag_substate));
TEST(tl_find(e->data->e_tags, nutag_substate)->t_value, nua_substate_pending);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_event); TEST_S(sip->sip_event->o_type, "presence");
TEST_1(sip->sip_content_type);
TEST_S(sip->sip_content_type->c_type, "application/pidf+xml");
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "pending");
TEST_1(sip->sip_subscription_state->ss_expires);
TEST_1(e = es); TEST_E(e->data->e_event, nua_r_subscribe);
TEST_1(e->data->e_status == 202 || e->data->e_status == 200);
TEST_1(tl_find(e->data->e_tags, nutag_substate));
if (es == a->events->head)
TEST(tl_find(e->data->e_tags, nutag_substate)->t_value, nua_substate_embryonic);
else
TEST(tl_find(e->data->e_tags, nutag_substate)->t_value, nua_substate_pending);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_expires);
TEST_1(sip->sip_expires->ex_delta <= 333);
free_events_in_list(ctx, a->events);
/* Server events: nua_i_subscribe, nua_r_notify */
TEST_1(e = b->events->head);
TEST_E(e->data->e_event, nua_i_subscribe);
TEST_E(e->data->e_status, 100);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_pending);
free_events_in_list(ctx, b->events);
if (print_headings)
printf("TEST NUA-11.4.1: PASSED\n");
/* ---------------------------------------------------------------------- */
/* NOTIFY with updated content
A B
| |
|<------NOTIFY-------|
|-------200 OK------>|
| |
*/
if (print_headings)
printf("TEST NUA-11.4.2: send NOTIFY\n");
/* Update presence data */
NOTIFY(b, b_call, b_call->nh,
NUTAG_SUBSTATE(nua_substate_active),
SIPTAG_EVENT_STR("presence"),
SIPTAG_CONTENT_TYPE_STR("application/pidf+xml"),
SIPTAG_PAYLOAD_STR(presence_open),
TAG_END());
run_ab_until(ctx, -1, save_until_notified,
-1, save_until_final_response);
/* subscriber events:
nua_i_notify
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_notify);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_event); TEST_S(sip->sip_event->o_type, "presence");
TEST_1(sip->sip_content_type);
TEST_S(sip->sip_content_type->c_type, "application/pidf+xml");
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "active");
TEST_1(sip->sip_subscription_state->ss_expires);
n_tags = e->data->e_tags;
TEST_1(tl_find(n_tags, nutag_substate));
TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_active);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
/* Notifier events: nua_r_notify */
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_r_notify);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_active);
free_events_in_list(ctx, b->events);
if (print_headings)
printf("TEST NUA-11.4.2: PASSED\n");
/* ---------------------------------------------------------------------- */
/* Re-SUBSCRIBE
A B
| |
|<------NOTIFY-------|
|-------200 OK------>|
| |
*/
if (print_headings)
printf("TEST NUA-11.4.3: re-SUBSCRIBE\n");
/* Set default expiration time */
nua_set_hparams(b_call->nh, NUTAG_SUB_EXPIRES(365), TAG_END());
run_b_until(ctx, nua_r_set_params, until_final_response);
SUBSCRIBE(a, a_call, a_call->nh, NUTAG_URL(b->contact->m_url),
SIPTAG_EVENT_STR("presence"),
SIPTAG_EXPIRES_STR("3600"),
SIPTAG_ACCEPT_STR("application/xpidf, application/pidf+xml"),
TAG_END());
run_ab_until(ctx, -1, save_until_notified_and_responded,
-1, save_until_final_response);
/* Client events:
nua_subscribe(), nua_i_notify/nua_r_subscribe
*/
for (en1 = en2 = es = NULL, e = a->events->head; e; e = e->next) {
if (en1 == NULL && e->data->e_event == nua_i_notify)
en1 = e;
else if (e->data->e_event == nua_r_subscribe)
es = e;
else
TEST_1(!e);
}
TEST_1(e = en1);
TEST_E(e->data->e_event, nua_i_notify);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_event); TEST_S(sip->sip_event->o_type, "presence");
TEST_1(sip->sip_content_type);
TEST_S(sip->sip_content_type->c_type, "application/pidf+xml");
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "active");
TEST_1(sip->sip_subscription_state->ss_expires);
n_tags = e->data->e_tags;
TEST_1(tl_find(n_tags, nutag_substate));
TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_active);
TEST_1(e = es); TEST_E(e->data->e_event, nua_r_subscribe);
TEST_1(tl_find(e->data->e_tags, nutag_substate));
TEST(tl_find(e->data->e_tags, nutag_substate)->t_value, nua_substate_active);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_expires);
TEST_1(sip->sip_expires->ex_delta <= 365);
free_events_in_list(ctx, a->events);
/* Server events: nua_i_subscribe, nua_r_notify */
TEST_1(e = b->events->head);
TEST_E(e->data->e_event, nua_i_subscribe);
TEST_E(e->data->e_status, 100);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_active);
free_events_in_list(ctx, b->events);
if (print_headings)
printf("TEST NUA-11.4.3: PASSED\n");
/* ---------------------------------------------------------------------- */
/* un-SUBSCRIBE
A B
| |
|------SUBSCRIBE---->|
|<--------202--------|
|<------NOTIFY-------|
|-------200 OK------>|
| |
*/
if (print_headings)
printf("TEST NUA-11.4.4: un-SUBSCRIBE\n");
UNSUBSCRIBE(a, a_call, a_call->nh, TAG_END());
run_ab_until(ctx, -1, save_until_final_response,
-1, save_until_final_response);
/* Client events:
nua_unsubscribe(), nua_i_notify/nua_r_unsubscribe
*/
for (en1 = en2 = es = NULL, e = a->events->head; e; e = e->next) {
if (en1 == NULL && e->data->e_event == nua_i_notify)
en1 = e;
else if (e->data->e_event == nua_r_unsubscribe)
es = e;
else
TEST_1(!e);
}
if (en1) {
TEST_1(e = en1); TEST_E(e->data->e_event, nua_i_notify);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_event);
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "terminated");
TEST_1(!sip->sip_subscription_state->ss_expires);
n_tags = e->data->e_tags;
TEST_1(tl_find(n_tags, nutag_substate));
TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_terminated);
}
TEST_1(e = es); TEST_E(e->data->e_event, nua_r_unsubscribe);
TEST(e->data->e_status, 200);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_terminated);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_expires);
TEST_1(sip->sip_expires->ex_delta == 0);
free_events_in_list(ctx, a->events);
/* Notifier events: nua_r_notify */
TEST_1(e = b->events->head);
TEST_E(e->data->e_event, nua_i_subscribe);
TEST(e->data->e_status, 200);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(tl_find(e->data->e_tags, nutag_substate));
TEST(tl_find(e->data->e_tags, nutag_substate)->t_value,
nua_substate_terminated);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify);
TEST_1(e->data->e_status >= 200);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_terminated);
free_events_in_list(ctx, b->events);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
if (print_headings)
printf("TEST NUA-11.4.4: PASSED\n");
if (print_headings)
printf("TEST NUA-11.4: PASSED\n");
END();
}
/* ---------------------------------------------------------------------- */
/* Subscriber gracefully terminates dialog upon 483 */
static
size_t change_status_to_483(void *a, void *message, size_t len);
int save_until_notified_and_responded_twice(CONDITION_PARAMS);
int save_until_notify_responded_twice(CONDITION_PARAMS);
int accept_subscription_until_terminated(CONDITION_PARAMS);
int test_subscribe_notify_graceful(struct context *ctx)
{
if (!ctx->nat)
return 0;
BEGIN();
struct endpoint *a = &ctx->a, *b = &ctx->b;
struct call *a_call = a->call, *b_call = b->call;
struct event *e, *en1, *en2, *es;
sip_t const *sip;
tagi_t const *n_tags, *r_tags;
struct nat_filter *f;
if (print_headings)
printf("TEST NUA-11.5.1: establishing subscription\n");
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
SUBSCRIBE(a, a_call, a_call->nh, NUTAG_URL(b->contact->m_url),
SIPTAG_EVENT_STR("presence"),
SIPTAG_ACCEPT_STR("application/xpidf, application/pidf+xml"),
TAG_END());
run_ab_until(ctx, -1, save_until_notified_and_responded,
-1, accept_and_notify);
/* Client events:
nua_subscribe(), nua_i_notify/nua_r_subscribe
*/
for (en1 = en2 = es = NULL, e = a->events->head; e; e = e->next) {
if (en1 == NULL && e->data->e_event == nua_i_notify)
en1 = e;
else if (es == NULL && e->data->e_event == nua_r_subscribe)
es = e;
else
TEST_1(!e);
}
TEST_1(e = en1); TEST_E(e->data->e_event, nua_i_notify);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_event); TEST_S(sip->sip_event->o_type, "presence");
TEST_1(sip->sip_content_type);
TEST_S(sip->sip_content_type->c_type, "application/pidf+xml");
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "pending");
TEST_1(sip->sip_subscription_state->ss_expires);
n_tags = e->data->e_tags;
TEST_1(tl_find(n_tags, nutag_substate));
TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_pending);
TEST_1(e = es); TEST_E(e->data->e_event, nua_r_subscribe);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
if (es == a->events->head)
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_embryonic);
else
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_pending);
free_events_in_list(ctx, a->events);
/* Server events: nua_i_subscribe, nua_r_notify */
TEST_1(e = b->events->head);
TEST_E(e->data->e_event, nua_i_subscribe);
TEST_E(e->data->e_status, 100);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_pending);
free_events_in_list(ctx, b->events);
if (print_headings)
printf("TEST NUA-11.5.1: PASSED\n");
if (print_headings)
printf("TEST NUA-11.5.2: terminate gracefully upon 483\n");
TEST_1(f = test_nat_add_filter(ctx->nat,
change_status_to_483, NULL,
nat_inbound));
SUBSCRIBE(a, a_call, a_call->nh, TAG_END());
run_ab_until(ctx, -1, save_until_notified_and_responded_twice,
-1, accept_subscription_until_terminated);
#if 0
/* Client events:
nua_unsubscribe(), nua_i_notify/nua_r_unsubscribe
*/
TEST_1(e = a->events->head);
if (e->data->e_event == nua_i_notify) {
TEST_E(e->data->e_event, nua_i_notify);
n_tags = e->data->e_tags;
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_event);
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "terminated");
TEST_1(!sip->sip_subscription_state->ss_expires);
TEST_1(tl_find(n_tags, nutag_substate));
TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_terminated);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_unsubscribe);
TEST(e->data->e_status, 200);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_terminated);
}
else {
TEST_E(e->data->e_event, nua_r_unsubscribe);
TEST(e->data->e_status, 200);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_terminated);
}
TEST_1(!e->next);
/* Notifier events: nua_r_notify */
TEST_1(e = b->events->head);
TEST_E(e->data->e_event, nua_i_subscribe);
TEST(e->data->e_status, 200);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(tl_find(e->data->e_tags, nutag_substate));
TEST(tl_find(e->data->e_tags, nutag_substate)->t_value,
nua_substate_terminated);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify);
TEST_1(e->data->e_status >= 200);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_terminated);
#endif
free_events_in_list(ctx, a->events);
free_events_in_list(ctx, b->events);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
test_nat_remove_filter(ctx->nat, f);
if (print_headings)
printf("TEST NUA-11.5.2: PASSED\n");
END();
}
static
size_t change_status_to_483(void *a, void *message, size_t len)
{
(void)a;
if (strncmp("SIP/2.0 2", message, 9) == 0) {
memcpy(message, "SIP/2.0 483", 11);
}
return len;
}
int save_until_notified_and_responded_twice(CONDITION_PARAMS)
{
save_event_in_list(ctx, event, ep, call);
if (event == nua_i_notify) {
if (ep->flags.bit0)
ep->flags.bit1 = 1;
ep->flags.bit0 = 1;
}
if (event == nua_r_subscribe || event == nua_r_unsubscribe) {
if (status >= 300)
return 1;
else if (status >= 200) {
if (ep->flags.bit2)
ep->flags.bit3 = 1;
ep->flags.bit2 = 1;
}
}
return ep->flags.bit0 && ep->flags.bit1 && ep->flags.bit2 && ep->flags.bit3;
}
int save_until_notify_responded_twice(CONDITION_PARAMS)
{
save_event_in_list(ctx, event, ep, call);
if (event == nua_r_notify) {
if (ep->flags.bit0)
ep->flags.bit1 = 1;
ep->flags.bit0 = 1;
}
return ep->flags.bit0 && ep->flags.bit1;
}
/* ---------------------------------------------------------------------- */
/* Unsolicited NOTIFY */
int accept_notify(CONDITION_PARAMS);
int test_newsub_notify(struct context *ctx)
{
BEGIN();
struct endpoint *a = &ctx->a, *b = &ctx->b;
struct call *a_call = a->call, *b_call = b->call;
struct event *e;
sip_t const *sip;
sip_call_id_t *i;
tagi_t const *n_tags, *r_tags;
#if 0
if (print_headings)
printf("TEST NUA-11.7.1: rejecting NOTIFY without subscription locally\n");
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
NOTIFY(a, a_call, a_call->nh, NUTAG_URL(b->contact->m_url),
SIPTAG_SUBJECT_STR("NUA-11.7.1"),
SIPTAG_EVENT_STR("message-summary"),
SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"),
SIPTAG_PAYLOAD_STR("Messages-Waiting: yes"),
TAG_END());
run_a_until(ctx, -1, save_until_final_response);
/* Client events:
nua_notify(), nua_r_notify
*/
TEST_1(e = a->events->head);
TEST_E(e->data->e_event, nua_r_notify);
TEST(e->data->e_status, 481);
TEST_1(!e->data->e_msg);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
if (print_headings)
printf("TEST NUA-11.7.1: PASSED\n");
if (print_headings)
printf("TEST NUA-11.7.2: rejecting NOTIFY without subscription\n");
TEST_1(i = sip_call_id_create(nua_handle_home(a_call->nh), NULL));
NOTIFY(a, a_call, a_call->nh, NUTAG_URL(b->contact->m_url),
NUTAG_NEWSUB(1),
SIPTAG_SUBJECT_STR("NUA-11.7.2 first"),
SIPTAG_FROM_STR("<sip:alice@example.com>;tag=nua-11.7.2"),
SIPTAG_CALL_ID(i),
SIPTAG_CSEQ_STR("1 NOTIFY"),
SIPTAG_EVENT_STR("message-summary"),
SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"),
SIPTAG_PAYLOAD_STR("Messages-Waiting: yes"),
TAG_END());
run_a_until(ctx, -1, save_until_final_response);
/* Client events:
nua_notify(), nua_r_notify
*/
TEST_1(e = a->events->head);
TEST_E(e->data->e_event, nua_r_notify);
TEST(e->data->e_status, 481);
TEST_1(e->data->e_msg);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
/* 2nd NOTIFY using same dialog */
/* Check that server really discards the dialog */
NOTIFY(a, a_call, a_call->nh, NUTAG_URL(b->contact->m_url),
NUTAG_NEWSUB(1),
SIPTAG_SUBJECT_STR("NUA-11.7.2 second"),
SIPTAG_FROM_STR("<sip:alice@example.com>;tag=nua-11.7.2"),
SIPTAG_CALL_ID(i),
SIPTAG_CSEQ_STR("2 NOTIFY"),
SIPTAG_EVENT_STR("message-summary"),
SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"),
SIPTAG_PAYLOAD_STR("Messages-Waiting: yes"),
TAG_END());
run_a_until(ctx, -1, save_until_final_response);
/* Client events:
nua_notify(), nua_r_notify
*/
TEST_1(e = a->events->head);
TEST_E(e->data->e_event, nua_r_notify);
TEST(e->data->e_status, 481);
TEST_1(e->data->e_msg);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
if (print_headings)
printf("TEST NUA-11.7.2: PASSED\n");
/* ---------------------------------------------------------------------- */
if (print_headings)
printf("TEST NUA-11.7.3: accept NOTIFY\n");
nua_set_params(b->nua, NUTAG_APPL_METHOD("NOTIFY"), TAG_END());
run_b_until(ctx, nua_r_set_params, until_final_response);
NOTIFY(a, a_call, a_call->nh,
NUTAG_URL(b->contact->m_url),
NUTAG_NEWSUB(1),
SIPTAG_SUBJECT_STR("NUA-11.7.3"),
SIPTAG_EVENT_STR("message-summary"),
SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"),
SIPTAG_PAYLOAD_STR("Messages-Waiting: yes"),
TAG_END());
run_ab_until(ctx, -1, save_until_final_response, -1, accept_notify);
/* Notifier events: nua_r_notify */
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_notify);
TEST(e->data->e_status, 200);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_terminated);
/* subscriber events:
nua_i_notify
*/
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_notify);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "terminated");
n_tags = e->data->e_tags;
TEST_1(tl_find(n_tags, nutag_substate));
TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_terminated);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
free_events_in_list(ctx, b->events);
if (print_headings)
printf("TEST NUA-11.7.3: PASSED\n");
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
#else
(void)i;
nua_set_params(b->nua, NUTAG_APPL_METHOD("NOTIFY"), TAG_END());
run_b_until(ctx, nua_r_set_params, until_final_response);
#endif
/* ---------------------------------------------------------------------- */
if (print_headings)
printf("TEST NUA-11.7.4: multiple unsolicited NOTIFYs\n");
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
NOTIFY(a, a_call, a_call->nh,
NUTAG_URL(b->contact->m_url),
NUTAG_NEWSUB(1),
SIPTAG_EXPIRES_STR("10"),
SIPTAG_SUBJECT_STR("NUA-11.7.4aa"),
SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"),
SIPTAG_PAYLOAD_STR("Messages-Waiting: no"),
TAG_END());
NOTIFY(a, a_call, a_call->nh,
NUTAG_URL(b->contact->m_url),
NUTAG_NEWSUB(1),
SIPTAG_SUBSCRIPTION_STATE_STR("active; expires=333"),
SIPTAG_SUBJECT_STR("NUA-11.7.4a"),
SIPTAG_EVENT_STR("message-summary"),
SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"),
SIPTAG_PAYLOAD_STR("Messages-Waiting: no"),
TAG_END());
NOTIFY(a, a_call, a_call->nh,
NUTAG_URL(b->contact->m_url),
NUTAG_NEWSUB(1),
SIPTAG_SUBSCRIPTION_STATE_STR("active; expires=3000"),
SIPTAG_SUBJECT_STR("NUA-11.7.4b"),
SIPTAG_EVENT_STR("message-summary"),
SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"),
SIPTAG_PAYLOAD_STR("Messages-Waiting: yes"),
TAG_END());
NOTIFY(a, a_call, a_call->nh,
NUTAG_URL(b->contact->m_url),
NUTAG_NEWSUB(1),
SIPTAG_SUBSCRIPTION_STATE_STR("terminated"),
SIPTAG_SUBJECT_STR("NUA-11.7.4c"),
SIPTAG_EVENT_STR("message-summary"),
SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"),
SIPTAG_PAYLOAD_STR("Messages-Waiting: yes"),
TAG_END());
a->state.n = 4;
b->state.n = 4;
run_ab_until(ctx, -1, save_until_nth_final_response,
-1, accept_n_notifys);
/* Notifier events: nua_r_notify nua_r_notify */
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_notify);
TEST(e->data->e_status, 200);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_terminated);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify);
TEST(e->data->e_status, 200);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_active);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify);
TEST(e->data->e_status, 200);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_active);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify);
TEST(e->data->e_status, 200);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_terminated);
TEST_1(!e->next);
/* subscriber events:
nua_i_notify
*/
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_notify);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "terminated");
n_tags = e->data->e_tags;
TEST_1(tl_find(n_tags, nutag_substate));
TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_terminated);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_notify);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "active");
n_tags = e->data->e_tags;
TEST_1(tl_find(n_tags, nutag_substate));
TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_active);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_notify);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "active");
n_tags = e->data->e_tags;
TEST_1(tl_find(n_tags, nutag_substate));
TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_active);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_notify);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "terminated");
n_tags = e->data->e_tags;
TEST_1(tl_find(n_tags, nutag_substate));
TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_terminated);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
free_events_in_list(ctx, b->events);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
if (print_headings)
printf("TEST NUA-11.7.4: PASSED\n");
/* ---------------------------------------------------------------------- */
if (print_headings)
printf("TEST NUA-11.7.5: multiple unsolicited NOTIFYs\n");
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
NOTIFY(a, a_call, a_call->nh,
NUTAG_URL(b->contact->m_url),
NUTAG_NEWSUB(1),
SIPTAG_SUBSCRIPTION_STATE_STR("active; expires=333"),
SIPTAG_SUBJECT_STR("NUA-11.7.5a"),
SIPTAG_EVENT_STR("message-summary"),
SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"),
SIPTAG_PAYLOAD_STR("Messages-Waiting: no"),
TAG_END());
NOTIFY(a, a_call, a_call->nh,
NUTAG_URL(b->contact->m_url),
NUTAG_NEWSUB(1),
SIPTAG_SUBSCRIPTION_STATE_STR("active; expires=3000"),
SIPTAG_SUBJECT_STR("NUA-11.7.5b"),
SIPTAG_EVENT_STR("message-summary"),
SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"),
SIPTAG_PAYLOAD_STR("Messages-Waiting: yes"),
TAG_END());
NOTIFY(a, a_call, a_call->nh,
NUTAG_URL(b->contact->m_url),
NUTAG_NEWSUB(1),
SIPTAG_SUBSCRIPTION_STATE_STR("terminated"),
SIPTAG_SUBJECT_STR("NUA-11.7.5c"),
SIPTAG_EVENT_STR("message-summary"),
SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"),
SIPTAG_PAYLOAD_STR("Messages-Waiting: yes"),
TAG_END());
a->state.n = 3;
b->state.n = 3;
run_ab_until(ctx, -1, save_until_nth_final_response,
-1, accept_n_notifys);
/* Notifier events: nua_r_notify nua_r_notify */
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_notify);
TEST(e->data->e_status, 200);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_active);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify);
TEST(e->data->e_status, 200);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_active);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify);
TEST(e->data->e_status, 200);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_terminated);
TEST_1(!e->next);
/* subscriber events:
nua_i_notify
*/
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_notify);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "active");
n_tags = e->data->e_tags;
TEST_1(tl_find(n_tags, nutag_substate));
TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_active);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_notify);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "active");
n_tags = e->data->e_tags;
TEST_1(tl_find(n_tags, nutag_substate));
TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_active);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_notify);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "terminated");
n_tags = e->data->e_tags;
TEST_1(tl_find(n_tags, nutag_substate));
TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_terminated);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
free_events_in_list(ctx, b->events);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
if (print_headings)
printf("TEST NUA-11.7.5: PASSED\n");
/* ---------------------------------------------------------------------- */
#if 0
if (print_headings)
printf("TEST NUA-11.7.6: unsolicited NOTIFY handle destroyed\n");
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
NOTIFY(a, a_call, a_call->nh,
NUTAG_URL(b->contact->m_url),
NUTAG_NEWSUB(1),
SIPTAG_SUBSCRIPTION_STATE_STR("active; expires=333"),
SIPTAG_SUBJECT_STR("NUA-11.7.6a"),
SIPTAG_EVENT_STR("message-summary"),
SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"),
SIPTAG_PAYLOAD_STR("Messages-Waiting: no"),
TAG_END());
NOTIFY(a, a_call, a_call->nh,
NUTAG_URL(b->contact->m_url),
NUTAG_NEWSUB(1),
SIPTAG_SUBSCRIPTION_STATE_STR("active; expires=3000"),
SIPTAG_SUBJECT_STR("NUA-11.7.6b"),
SIPTAG_EVENT_STR("message-summary"),
SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"),
SIPTAG_PAYLOAD_STR("Messages-Waiting: yes"),
TAG_END());
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
a->state.n = 3;
b->state.n = 3;
run_b_until(ctx, -1, accept_n_notifys);
/* subscriber events:
nua_i_notify
*/
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_notify);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "active");
n_tags = e->data->e_tags;
TEST_1(tl_find(n_tags, nutag_substate));
TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_active);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_notify);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "active");
n_tags = e->data->e_tags;
TEST_1(tl_find(n_tags, nutag_substate));
TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_active);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_notify);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "terminated");
n_tags = e->data->e_tags;
TEST_1(tl_find(n_tags, nutag_substate));
TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_terminated);
TEST_1(!e->next);
free_events_in_list(ctx, b->events);
if (print_headings)
printf("TEST NUA-11.7.6: PASSED\n");
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
#endif
if (print_headings)
printf("TEST NUA-11.7: PASSED\n");
END();
}
/**Terminate when received notify.
* Respond to NOTIFY with 200 OK if it has not been responded.
* Save events (except nua_i_active or terminated).
*/
int accept_notify(CONDITION_PARAMS)
{
if (event == nua_i_notify && status < 200)
RESPOND(ep, call, nh, SIP_200_OK,
NUTAG_WITH_THIS(ep->nua),
TAG_END());
save_event_in_list(ctx, event, ep, call);
return event == nua_i_notify;
}
int save_until_nth_final_response(CONDITION_PARAMS)
{
save_event_in_list(ctx, event, ep, call);
if (nua_r_set_params <= event && event < nua_i_network_changed
&& status >= 200) {
if (ep->state.n > 0)
ep->state.n--;
return ep->state.n == 0;
}
return 0;
}
int accept_n_notifys(CONDITION_PARAMS)
{
tagi_t const *substate = tl_find(tags, nutag_substate);
if (event == nua_i_notify && status < 200)
RESPOND(ep, call, nh, SIP_200_OK,
NUTAG_WITH_THIS(ep->nua),
TAG_END());
save_event_in_list(ctx, event, ep, call);
if (event != nua_i_notify)
return 0;
if (ep->state.n > 0)
ep->state.n--;
if (ep->state.n == 0)
return 1;
if (substate && substate->t_value == nua_substate_terminated) {
if (call && call->nh == nh) {
call->nh = NULL;
nua_handle_destroy(nh);
}
}
return 0;
}
/* ======================================================================== */
int save_until_subscription_terminated(CONDITION_PARAMS);
int accept_subscription_until_terminated(CONDITION_PARAMS);
/* Timeout subscription */
int test_subscription_timeout(struct context *ctx)
{
BEGIN();
struct endpoint *a = &ctx->a, *b = &ctx->b;
struct call *a_call = a->call, *b_call = b->call;
struct event *e, *en, *es;
sip_t const *sip;
tagi_t const *n_tags, *r_tags;
if (print_headings)
printf("TEST NUA-11.8: subscribe and wait until subscription times out\n");
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
METHOD(a, a_call, a_call->nh,
NUTAG_METHOD("SUBSCRIBE"),
NUTAG_URL(b->contact->m_url),
SIPTAG_EVENT_STR("presence"),
SIPTAG_ACCEPT_STR("application/xpidf, application/pidf+xml"),
SIPTAG_EXPIRES_STR("2"),
NUTAG_APPL_METHOD("NOTIFY"),
NUTAG_DIALOG(2),
TAG_END());
run_ab_until(ctx,
-1, save_until_subscription_terminated,
-1, accept_subscription_until_terminated);
/* Client events:
nua_method(), nua_i_notify/nua_r_method, nua_i_notify
*/
TEST_1(en = event_by_type(a->events->head, nua_i_notify));
TEST_1(es = event_by_type(a->events->head, nua_r_method));
TEST_1(e = en); TEST_E(e->data->e_event, nua_i_notify);
TEST_1(sip = sip_object(e->data->e_msg));
n_tags = e->data->e_tags;
TEST_1(e = es); TEST_E(e->data->e_event, nua_r_method);
r_tags = e->data->e_tags;
TEST_1(sip->sip_event); TEST_S(sip->sip_event->o_type, "presence");
TEST_1(sip->sip_content_type);
TEST_S(sip->sip_content_type->c_type, "application/pidf+xml");
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "pending");
TEST_1(sip->sip_subscription_state->ss_expires);
TEST_1(tl_find(n_tags, nutag_substate));
TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_pending);
if (es->next == en)
e = en->next;
else
e = es->next;
TEST_1(e); TEST_E(e->data->e_event, nua_i_notify);
n_tags = e->data->e_tags;
TEST_1(tl_find(n_tags, nutag_substate));
TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_terminated);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_event);
TEST_1(sip->sip_subscription_state);
TEST_S(sip->sip_subscription_state->ss_substate, "terminated");
TEST_1(!sip->sip_subscription_state->ss_expires);
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
/* Server events: nua_i_subscribe, nua_r_notify */
TEST_1(e = b->events->head);
TEST_E(e->data->e_event, nua_i_subscribe);
TEST_E(e->data->e_status, 100);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_pending);
/* Notifier events: 2nd nua_r_notify */
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify);
TEST_1(e->data->e_status >= 200);
r_tags = e->data->e_tags;
TEST_1(tl_find(r_tags, nutag_substate));
TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_terminated);
free_events_in_list(ctx, b->events);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
if (print_headings)
printf("TEST NUA-11.8: PASSED\n");
END();
}
int save_until_subscription_terminated(CONDITION_PARAMS)
{
void *with = nua_current_request(nua);
save_event_in_list(ctx, event, ep, call);
if (event == nua_i_notify) {
if (status < 200)
RESPOND(ep, call, nh, SIP_200_OK, NUTAG_WITH(with), TAG_END());
tags = tl_find(tags, nutag_substate);
return tags && tags->t_value == nua_substate_terminated;
}
return 0;
}
int accept_subscription_until_terminated(CONDITION_PARAMS)
{
void *with = nua_current_request(nua);
save_event_in_list(ctx, event, ep, call);
if (event == nua_i_subscribe && status < 200) {
RESPOND(ep, call, nh, SIP_202_ACCEPTED,
NUTAG_WITH(with),
SIPTAG_EXPIRES_STR("360"),
TAG_END());
NOTIFY(ep, call, nh,
SIPTAG_EVENT(sip->sip_event),
SIPTAG_CONTENT_TYPE_STR("application/pidf+xml"),
SIPTAG_PAYLOAD_STR(presence_closed),
NUTAG_SUBSTATE(nua_substate_pending),
TAG_END());
}
else if (event == nua_r_notify) {
tags = tl_find(tags, nutag_substate);
return tags && tags->t_value == nua_substate_terminated;
}
return 0;
}
/* ======================================================================== */
/* Test simple methods: MESSAGE, PUBLISH, SUBSCRIBE/NOTIFY */
int test_simple(struct context *ctx)
{
return 0
|| test_message(ctx)
|| test_publish(ctx)
|| test_subscribe_notify(ctx)
|| test_subscribe_notify_graceful(ctx)
|| test_newsub_notify(ctx)
|| test_subscription_timeout(ctx)
;
}