/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * 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 * @author Martti Mela * * @date Created: Wed Aug 17 12:12:12 EEST 2005 ppessi */ #include "config.h" #include "test_nua.h" #include #if HAVE_FUNC #elif HAVE_FUNCTION #define __func__ __FUNCTION__ #else #define __func__ "test_simple" #endif 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: 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"), 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"); 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: 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.1b"), 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->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.1b"); TEST_1(e = e->next); 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); nua_handle_destroy(a_call->nh), a_call->nh = NULL; if (print_headings) printf("TEST NUA-11.2: PASSED\n"); END(); } 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 0; 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, "tagtag"))) { 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("tagtag"), SIPTAG_EXPIRES_STR("3600"), SIPTAG_EXPIRES(sip->sip_expires), /* overrides 3600 */ TAG_END()); } return 1; default: return 0; } } 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"), 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, "tagtag"); 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; 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; if (print_headings) printf("TEST NUA-11.3: PASSED\n"); END(); } static char const presence_open[] = "\n" "\n" " \n" " open\n" " sip:bob@example.org\n" " \n" "\n"; static char const presence_closed[] = "\n" "\n" " \n" " closed\n" " \n" "\n"; 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; } } 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; sip_t const *sip; tagi_t const *n_tags, *r_tags; if (print_headings) printf("TEST NUA-11.4: establishing subscription without notifier\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 */ TEST_1(e = a->events->head); if (e->data->e_event == nua_i_notify) { 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 = e->next); TEST_E(e->data->e_event, nua_r_subscribe); 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); } else { TEST_E(e->data->e_event, nua_r_subscribe); TEST(e->data->e_status, 202); 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_embryonic); TEST_1(e = e->next); 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(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); 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); free_events_in_list(ctx, b->events); if (print_headings) printf("TEST NUA-11.4: PASSED\n"); /* ---------------------------------------------------------------------- */ /* NOTIFY with updated content A B | | |<------NOTIFY-------| |-------200 OK------>| | | */ if (print_headings) printf("TEST NUA-11.5: 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.5: PASSED\n"); /* ---------------------------------------------------------------------- */ /* un-SUBSCRIBE A B | | |------SUBSCRIBE---->| |<--------202--------| |<------NOTIFY-------| |-------200 OK------>| | | */ if (print_headings) printf("TEST NUA-11.6: 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 */ 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); 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.6: PASSED\n"); END(); } /* ======================================================================== */ /* Test simple methods: MESSAGE, PUBLISH, SUBSCRIBE/NOTIFY */ int test_simple(struct context *ctx) { return test_message(ctx) || test_publish(ctx) || test_subscribe_notify(ctx) ; }