diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index 9f68b01c92..da01d9f6d6 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Tue Mar 10 14:52:49 CDT 2009 +Tue Mar 10 14:53:54 CDT 2009 diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/nta/Makefile.am index e36906a04d..ed708ee6ea 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/nta/Makefile.am @@ -16,17 +16,20 @@ INCLUDES = -I$(srcdir)/../ipt -I../ipt \ -I$(srcdir)/../tport -I../tport \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../features -I../features \ - -I$(srcdir)/../su -I../su + -I$(srcdir)/../su -I../su \ + -I$(top_srcdir)/s2check \ + -I$(srcdir)/../stun -I ../stun # ---------------------------------------------------------------------- # Build targets noinst_LTLIBRARIES = libnta.la -check_PROGRAMS = test_nta_api test_nta portbind +check_PROGRAMS = check_nta test_nta_api test_nta portbind dist_noinst_SCRIPTS = run_test_nta_api run_test_nta -TESTS = run_test_nta_api run_test_nta +TESTS = run_check_nta run_test_nta_api run_test_nta + TESTS_ENVIRONMENT = $(SHELL) # ---------------------------------------------------------------------- @@ -63,6 +66,19 @@ test_nta_LDFLAGS = -static MOSTLYCLEANFILES += .test[0-9]* +if HAVE_CHECK + +check_nta_SOURCES = check_nta.c check_nta.h \ + check_nta_api.c \ + check_nta_client.c + +check_nta_LDADD = ${LDADD} ${top_builddir}/s2check/libs2.a \ + @CHECK_LIBS@ + +else +check_nta_SOURCES = $(top_srcdir)/s2check/exit77.c +endif + # ---------------------------------------------------------------------- # Install and distribution rules diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/check_nta.c b/libs/sofia-sip/libsofia-sip-ua/nta/check_nta.c new file mode 100644 index 0000000000..0d594b7058 --- /dev/null +++ b/libs/sofia-sip/libsofia-sip-ua/nta/check_nta.c @@ -0,0 +1,482 @@ +/* + * This file is part of the Sofia-SIP package + * + * Copyright (C) 2008 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 check_nta.c + * @brief 2nd test Suite for Sofia SIP Transaction Engine + * + * @author Pekka Pessi + * + * @date Created: Wed Apr 30 12:48:27 EEST 2008 ppessi + */ + +#include "config.h" + +#undef NDEBUG + +#include "check_nta.h" + +#include "s2dns.h" +#include "s2base.h" +#include "s2sip.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* -- Globals -------------------------------------------------------------- */ + +struct s2nta *s2; + +/* -- main ----------------------------------------------------------------- */ + +static void usage(int exitcode) +{ + fprintf(exitcode ? stderr : stdout, + "usage: %s [--xml=logfile] case,...\n", s2_tester); + exit(exitcode); +} + +int main(int argc, char *argv[]) +{ + int i, failed = 0, selected = 0; + char const *xml = NULL; + Suite *suite; + SRunner *runner; + + s2_tester = "check_nta"; + s2_suite("NTA"); + + if (getenv("CHECK_NTA_VERBOSE")) + s2_start_stop = strtoul(getenv("CHECK_NTA_VERBOSE"), NULL, 10); + + for (i = 1; argv[i]; i++) { + if (su_strnmatch(argv[i], "--xml=", strlen("--xml="))) { + xml = argv[i] + strlen("--xml="); + } + else if (su_strmatch(argv[i], "--xml")) { + if (!(xml = argv[++i])) + usage(2); + } + else if (su_strmatch(argv[i], "-v")) { + s2_start_stop = 1; + } + else if (su_strmatch(argv[i], "-?") || + su_strmatch(argv[i], "-h") || + su_strmatch(argv[i], "--help")) + usage(0); + else { + s2_select_tests(argv[i]); + selected = 1; + } + } + + if (!selected) + s2_select_tests(getenv("CHECK_NTA_CASES")); + + suite = suite_create("Unit tests for nta (Sofia-SIP Transaction Engine)"); + + suite_add_tcase(suite, check_nta_api_1_0()); + suite_add_tcase(suite, check_nta_client_2_0()); + suite_add_tcase(suite, check_nta_client_2_1()); + + runner = srunner_create(suite); + + if (xml) + srunner_set_xml(runner, argv[1]); + + srunner_run_all(runner, CK_ENV); + failed = srunner_ntests_failed(runner); + srunner_free(runner); + + exit(failed ? EXIT_FAILURE : EXIT_SUCCESS); +} + + +/* -- NTA callbacks -------------------------------------------------------- */ + +struct event * +s2_nta_remove_event(struct event *e) +{ + if ((*e->prev = e->next)) + e->next->prev = e->prev; + e->prev = NULL, e->next = NULL; + return e; +} + +void +s2_nta_free_event(struct event *e) +{ + if (e) { + if (e->prev) { + if ((*e->prev = e->next)) + e->next->prev = e->prev; + } + if (e->msg) + msg_destroy(e->msg); + free(e); + } +} + +void +s2_nta_flush_events(void) +{ + while (s2->events) { + s2_nta_free_event(s2->events); + } +} + +struct event * +s2_nta_next_event(void) +{ + for (;;) { + if (s2->events) + return s2_nta_remove_event(s2->events); + su_root_step(s2->root, 1); + } +} + +struct event * +s2_nta_vwait_for(enum wait_for wait_for0, + void const *value0, + va_list va0) +{ + struct event *e; + + for (;;) { + for (e = s2->events; e; e = e->next) { + va_list va; + enum wait_for wait_for; + void const *value; + + va_copy(va, va0); + + for (wait_for = wait_for0, value = value0; + wait_for; + wait_for = va_arg(va, enum wait_for), + value = va_arg(va, void const *)) { + switch (wait_for) { + case wait_for_amagic: + if (value != e->amagic) + goto next; + break; + case wait_for_omagic: + if (value != e->omagic) + goto next; + break; + case wait_for_orq: + if (value != e->orq) + goto next; + break; + case wait_for_lmagic: + if (value != e->lmagic) + goto next; + break; + case wait_for_leg: + if (value != e->leg) + goto next; + break; + case wait_for_imagic: + if (value != e->imagic) + goto next; + break; + case wait_for_irq: + if (value != e->irq) + goto next; + break; + case wait_for_method: + if ((sip_method_t)value != e->method) + goto next; + break; + case wait_for_method_name: + if (!su_strmatch(value, e->method_name)) + goto next; + break; + case wait_for_status: + if ((int)value != e->status) + goto next; + break; + case wait_for_phrase: + if (!su_casematch(value, e->phrase)) + goto next; + break; + } + } + + next: + va_end(va); + + if (!wait_for) + return s2_nta_remove_event(e); + } + su_root_step(s2->root, 1); + } +} + +struct event * +s2_nta_wait_for(enum wait_for wait_for, + void const *value, + ...) +{ + struct event *e; + va_list va; + + va_start(va, value); + e = s2_nta_vwait_for(wait_for, value, va); + va_end(va); + + return e; +} + +int +s2_nta_check_request(enum wait_for wait_for, + void const *value, + ...) +{ + struct event *e; + va_list va; + + va_start(va, value); + e = s2_nta_vwait_for(wait_for, value, va); + va_end(va); + + s2_nta_free_event(e); + return e != NULL; +} + +int +s2_nta_msg_callback(nta_agent_magic_t *magic, + nta_agent_t *nta, + msg_t *msg, + sip_t *sip) +{ + struct event *e, **prev; + + e = calloc(1, sizeof *e); + + e->amagic = magic; + e->msg = msg; + e->sip = sip; + + if (sip->sip_request) { + e->method = sip->sip_request->rq_method; + e->method_name = sip->sip_request->rq_method_name; + } + else { + e->status = sip->sip_status->st_status; + e->phrase = sip->sip_status->st_phrase; + } + + for (prev = &s2->events; *prev; prev = &(*prev)->next) + ; + *prev = e, e->prev = prev; + + return 0; +} + +int +s2_nta_orq_callback(nta_outgoing_magic_t *magic, + nta_outgoing_t *orq, + sip_t const *sip) +{ + struct event *e, **prev; + + e = calloc(1, sizeof *e); + + e->omagic = magic; + e->orq = orq; + e->msg = nta_outgoing_getresponse(orq); + e->sip = sip_object(e->msg); + + e->status = nta_outgoing_status(orq); + e->phrase = sip ? sip->sip_status->st_phrase : ""; + + for (prev = &s2->events; *prev; prev = &(*prev)->next) + ; + *prev = e, e->prev = prev; + + return 0; +} + +int +s2_nta_leg_callback(nta_leg_magic_t *magic, + nta_leg_t *leg, + nta_incoming_t *irq, + sip_t const *sip) +{ + struct event *e, **prev; + + e = calloc(1, sizeof *e); + + e->lmagic = magic; + e->leg = leg; + e->irq = irq; + + e->msg = nta_incoming_getrequest(irq); + e->sip = sip_object(e->msg); + + e->method = e->sip->sip_request->rq_method; + e->method_name = e->sip->sip_request->rq_method_name; + + for (prev = &s2->events; *prev; prev = &(*prev)->next) + ; + *prev = e, e->prev = prev; + + return 0; +} + +int +s2_nta_irq_callback(nta_incoming_magic_t *magic, + nta_incoming_t *irq, + sip_t const *sip) +{ + struct event *e, **prev; + + e = calloc(1, sizeof *e); + + e->imagic = magic; + e->irq = irq; + e->msg = nta_incoming_getrequest_ackcancel(irq); + e->sip = sip_object(e->msg); + + e->method = e->sip ? e->sip->sip_request->rq_method : 0; + e->method_name = e->sip ? e->sip->sip_request->rq_method_name : NULL; + + for (prev = &s2->events; *prev; prev = &(*prev)->next) + ; + *prev = e, e->prev = prev; + + return 0; +} + +/* ====================================================================== */ + +SOFIAPUBVAR su_log_t nta_log[]; +SOFIAPUBVAR su_log_t sresolv_log[]; +SOFIAPUBVAR su_log_t tport_log[]; +SOFIAPUBVAR su_log_t su_log_default[]; + +void +s2_nta_setup_logs(int level) +{ + su_log_soft_set_level(su_log_default, level); + su_log_soft_set_level(tport_log, level); + su_log_soft_set_level(nta_log, level); + su_log_soft_set_level(sresolv_log, level); + + if (getenv("TPORT_LOG") == NULL && getenv("S2_TPORT_LOG") == NULL) { + if (s2sip) + tport_set_params(s2sip->master, TPTAG_LOG(level > 1), TAG_END()); + } +} + +void +s2_nta_setup(char const *label, + char const * const *transports, + tag_type_t tag, tag_value_t value, ...) +{ + ta_list ta; + + s2_setup(label); + s2_nta_setup_logs(0); + s2_dns_setup(s2base->root); + ta_start(ta, tag, value); + s2_sip_setup("example.org", transports, ta_tags(ta)); + ta_end(ta); + assert(s2sip->contact); + + s2_dns_domain("example.org", 1, + "s2", 1, s2sip->udp.contact ? s2sip->udp.contact->m_url : NULL, + "s2", 1, s2sip->tcp.contact ? s2sip->tcp.contact->m_url : NULL, + "s2", 1, s2sip->tls.contact ? s2sip->tls.contact->m_url : NULL, + NULL); +} + +nta_agent_t * +s2_nta_agent_setup(url_string_t const *bind_url, + nta_message_f *callback, + nta_agent_magic_t *magic, + tag_type_t tag, tag_value_t value, ...) +{ + ta_list ta; + + assert(s2base); + + s2 = su_home_new(sizeof *s2); assert(s2); + s2->root = su_root_clone(s2base->root, s2); assert(s2->root); + fail_unless(s2->root != NULL); + + ta_start(ta, tag, value); + s2->nta = + nta_agent_create(s2->root, + bind_url ? bind_url : URL_STRING_MAKE("sip:*:*"), + callback, + magic, + /* Use internal DNS server */ + /* Force sresolv to use localhost and s2dns as DNS server */ +#if HAVE_WIN32 + SRESTAG_RESOLV_CONF("NUL"), +#else + SRESTAG_RESOLV_CONF("/dev/null"), +#endif + ta_tags(ta)); + ta_end(ta); + + assert(s2->nta); + + if (callback == NULL) + s2->default_leg = nta_leg_tcreate(s2->nta, s2_nta_leg_callback, NULL, + NTATAG_NO_DIALOG(1), + TAG_END()); + + return s2->nta; +} + +void s2_nta_teardown(void) +{ + if (s2) { + s2_nta_flush_events(); + + if (s2->default_leg) + nta_leg_destroy(s2->default_leg), s2->default_leg = NULL; + nta_agent_destroy(s2->nta), s2->nta = NULL; + su_root_destroy(s2->root), s2->root = NULL; + su_home_unref(s2->home); + s2 = NULL; + } + + s2_dns_teardown(); + s2_sip_teardown(); + s2_teardown(); +} diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/check_nta.h b/libs/sofia-sip/libsofia-sip-ua/nta/check_nta.h new file mode 100644 index 0000000000..f543d48b5b --- /dev/null +++ b/libs/sofia-sip/libsofia-sip-ua/nta/check_nta.h @@ -0,0 +1,132 @@ +/* + * This file is part of the Sofia-SIP package + * + * Copyright (C) 2008 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 + */ + +#ifndef CHECK_NTA_H +#define CHECK_NTA_H + +#include + +#include +#include +#include + +#include + +#include "s2sip.h" + +extern struct s2nta { + su_home_t home[1]; + + nta_agent_t *nta; + + su_root_t *root; + + nta_leg_t *default_leg; + + struct event { + struct event *next, **prev; + + nta_agent_magic_t *amagic; + + nta_outgoing_magic_t *omagic; + nta_outgoing_t *orq; + + nta_leg_magic_t *lmagic; + nta_leg_t *leg; + + nta_incoming_magic_t *imagic; + nta_incoming_t *irq; + + sip_method_t method; + char const *method_name; + + int status; + char const *phrase; + + msg_t *msg; + sip_t *sip; + } *events; +} *s2; + +struct event *s2_nta_remove_event(struct event *e); +void s2_nta_free_event(struct event *e); +void s2_nta_flush_events(void); +struct event *s2_nta_next_event(void); + +enum wait_for { + wait_for_amagic = 1, + wait_for_omagic, + wait_for_orq, + wait_for_lmagic, + wait_for_leg, + wait_for_imagic, + wait_for_irq, + wait_for_method, + wait_for_method_name, + wait_for_status, + wait_for_phrase +}; + +struct event *s2_nta_vwait_for(enum wait_for, + void const *value, + va_list va); + +struct event *s2_nta_wait_for(enum wait_for, + void const *value, + ...); + +int s2_nta_check_for(enum wait_for, + void const *value, + ...); + +int s2_nta_msg_callback(nta_agent_magic_t *magic, + nta_agent_t *nta, + msg_t *msg, + sip_t *sip); +int s2_nta_orq_callback(nta_outgoing_magic_t *magic, + nta_outgoing_t *orq, + sip_t const *sip); +int s2_nta_leg_callback(nta_leg_magic_t *magic, + nta_leg_t *leg, + nta_incoming_t *irq, + sip_t const *sip); +int s2_nta_irq_callback(nta_incoming_magic_t *magic, + nta_incoming_t *irq, + sip_t const *sip); + +void s2_nta_setup_logs(int level); +void s2_nta_setup(char const *label, + char const * const *transports, + tag_type_t tag, tag_value_t value, ...); + +nta_agent_t *s2_nta_agent_setup(url_string_t const *bind_url, + nta_message_f *callback, + nta_agent_magic_t *magic, + tag_type_t tag, tag_value_t value, ...); +void s2_nta_teardown(void); + +TCase *check_nta_api_1_0(void); +TCase *check_nta_client_2_0(void); +TCase *check_nta_client_2_1(void); + +#endif diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/check_nta_api.c b/libs/sofia-sip/libsofia-sip-ua/nta/check_nta_api.c new file mode 100644 index 0000000000..3f623d2117 --- /dev/null +++ b/libs/sofia-sip/libsofia-sip-ua/nta/check_nta_api.c @@ -0,0 +1,268 @@ +/* + * This file is part of the Sofia-SIP package + * + * Copyright (C) 2008 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 check_nta_api.c + * + * @brief Check-driven tester for NTA API + * + * @author Pekka Pessi + * + * @copyright (C) 2009 Nokia Corporation. + */ + +#include "config.h" + +#include "check_nta.h" +#include "s2base.h" +#include "nta_internal.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define NONE ((void *)-1) + +static void +api_setup(void) +{ + s2_nta_setup("NTA", NULL, TAG_END()); +} + +static void +api_teardown(void) +{ + mark_point(); + s2_nta_teardown(); +} + +START_TEST(api_1_0_0) +{ + su_root_t *root = s2base->root; + nta_agent_t *nta; + su_home_t home[1]; + su_nanotime_t nano; + nta_agent_magic_t *amagic = (void *)(home + 1); + nta_outgoing_magic_t *omagic = (void *)(home + 2); + msg_t *msg; + + memset(home, 0, sizeof home); home->suh_size = (sizeof home); + su_home_init(home); + + fail_unless(nta_agent_create(NULL, + (url_string_t *)"sip:*:*", + NULL, + NULL, + TAG_END()) == NULL); + + fail_unless(nta_agent_create(root, + (url_string_t *)"http://localhost:*/invalid/bind/url", + NULL, + NULL, + TAG_END()) == NULL); + + fail_unless(nta_agent_create(root, + (url_string_t *)"sip:*:*;transport=XXX", + NULL, + NULL, + TAG_END()) == NULL); + mark_point(); + nta = nta_agent_create(root, + (url_string_t *)"sip:*:*", + NULL, + NULL, + TAG_END()); + fail_unless(nta != NULL); + + mark_point(); + nta_agent_destroy(NULL); + mark_point(); + nta_agent_destroy(nta); + + mark_point(); + nta = nta_agent_create(root, + (url_string_t *)"sip:*:*", + s2_nta_msg_callback, + amagic, + TAG_END()); + fail_unless(nta != NULL); + + fail_unless(nta_agent_contact(NULL) == NULL); + fail_unless(nta_agent_via(NULL) == NULL); + fail_if(strcmp(nta_agent_version(nta), nta_agent_version(NULL))); + fail_unless(nta_agent_magic(NULL) == NULL); + fail_unless(nta_agent_magic(nta) == amagic); + fail_unless(nta_agent_add_tport(NULL, NULL, TAG_END()) == -1); + fail_unless(nta_agent_newtag(home, "tag=%s", NULL) == NULL); + fail_unless(nta_agent_newtag(home, "tag=%s", nta) != NULL); + + fail_unless(nta_msg_create(NULL, 0) == NULL); + fail_unless(nta_msg_complete(NULL) == -1); + + fail_unless((msg = nta_msg_create(nta, 0)) != NULL); + fail_unless(nta_msg_complete(msg) == -1); + fail_unless( + nta_msg_request_complete(msg, NULL, SIP_METHOD(FOO), NULL) == -1); + fail_unless(nta_is_internal_msg(NULL) == 0); + fail_unless(nta_is_internal_msg(msg) == 0); + fail_unless(msg_set_flags(msg, NTA_INTERNAL_MSG)); + fail_unless(nta_is_internal_msg(msg) == 1); + mark_point(); msg_destroy(msg); mark_point(); + + fail_unless(nta_leg_tcreate(NULL, NULL, NULL, TAG_END()) == NULL); + mark_point(); nta_leg_destroy(NULL); mark_point(); + fail_unless(nta_leg_magic(NULL, NULL) == NULL); + mark_point(); nta_leg_bind(NULL, NULL, NULL); mark_point(); + fail_unless(nta_leg_tag(NULL, "fidsafsa") == NULL); + fail_unless(nta_leg_rtag(NULL, "fidsafsa") == NULL); + fail_unless(nta_leg_get_tag(NULL) == NULL); + fail_unless(nta_leg_client_route(NULL, NULL, NULL) == -1); + fail_unless(nta_leg_client_reroute(NULL, NULL, NULL, 0) == -1); + fail_unless(nta_leg_server_route(NULL, NULL, NULL) == -1); + fail_unless(nta_leg_by_uri(NULL, NULL) == NULL); + fail_unless( + nta_leg_by_dialog(NULL, NULL, NULL, NULL, NULL, NULL, NULL) == NULL); + fail_unless( + nta_leg_by_dialog(nta, NULL, NULL, NULL, NULL, NULL, NULL) == NULL); + + fail_unless(nta_leg_make_replaces(NULL, NULL, 1) == NULL); + fail_unless(nta_leg_by_replaces(NULL, NULL) == NULL); + + fail_unless(nta_incoming_create(NULL, NULL, NULL, NULL, TAG_END()) == NULL); + fail_unless(nta_incoming_create(nta, NULL, NULL, NULL, TAG_END()) == NULL); + + mark_point(); nta_incoming_bind(NULL, NULL, NULL); mark_point(); + fail_unless(nta_incoming_magic(NULL, NULL) == NULL); + + fail_unless(nta_incoming_find(NULL, NULL, NULL) == NULL); + fail_unless(nta_incoming_find(nta, NULL, NULL) == NULL); + + fail_unless(nta_incoming_tag(NULL, NULL) == NULL); + fail_unless(nta_incoming_gettag(NULL) == NULL); + + fail_unless(nta_incoming_status(NULL) == 400); + fail_unless(nta_incoming_method(NULL) == sip_method_invalid); + fail_unless(nta_incoming_method_name(NULL) == NULL); + fail_unless(nta_incoming_url(NULL) == NULL); + fail_unless(nta_incoming_cseq(NULL) == 0); + fail_unless(nta_incoming_received(NULL, &nano) == 0); + fail_unless(nano == 0); + + fail_unless(nta_incoming_set_params(NULL, TAG_END()) == -1); + + fail_unless(nta_incoming_getrequest(NULL) == NULL); + fail_unless(nta_incoming_getrequest_ackcancel(NULL) == NULL); + fail_unless(nta_incoming_getresponse(NULL) == NULL); + + fail_unless( + nta_incoming_complete_response(NULL, NULL, 800, "foo", TAG_END()) == -1); + + fail_unless(nta_incoming_treply(NULL, SIP_200_OK, TAG_END()) == -1); + fail_unless(nta_incoming_mreply(NULL, NULL) == -1); + + mark_point(); nta_incoming_destroy(NULL); mark_point(); + + fail_unless( + nta_outgoing_tcreate(NULL, s2_nta_orq_callback, omagic, + URL_STRING_MAKE("sip:localhost"), + SIP_METHOD_MESSAGE, + URL_STRING_MAKE("sip:localhost"), + TAG_END()) == NULL); + + fail_unless( + nta_outgoing_mcreate(NULL, s2_nta_orq_callback, omagic, + URL_STRING_MAKE("sip:localhost"), + NULL, + TAG_END()) == NULL); + + fail_unless(nta_outgoing_default(NULL, NULL, NULL) == NULL); + + fail_unless(nta_outgoing_bind(NULL, NULL, NULL) == -1); + fail_unless(nta_outgoing_magic(NULL, NULL) == NULL); + + fail_unless(nta_outgoing_status(NULL) == 500); + fail_unless(nta_outgoing_method(NULL) == sip_method_invalid); + fail_unless(nta_outgoing_method_name(NULL) == NULL); + fail_unless(nta_outgoing_cseq(NULL) == 0); + + fail_unless(nta_outgoing_delay(NULL) == UINT_MAX); + fail_unless(nta_outgoing_request_uri(NULL) == NULL); + fail_unless(nta_outgoing_route_uri(NULL) == NULL); + + fail_unless(nta_outgoing_getresponse(NULL) == NULL); + fail_unless(nta_outgoing_getrequest(NULL) == NULL); + + fail_unless(nta_outgoing_tagged(NULL, NULL, NULL, NULL, NULL) == NULL); + fail_unless(nta_outgoing_cancel(NULL) == -1); + fail_unless(nta_outgoing_tcancel(NULL, NULL, NULL, TAG_END()) == NULL); + mark_point(); nta_outgoing_destroy(NULL); mark_point(); + + fail_unless(nta_outgoing_find(NULL, NULL, NULL, NULL) == NULL); + fail_unless(nta_outgoing_find(nta, NULL, NULL, NULL) == NULL); + + fail_unless(nta_outgoing_status(NONE) == 500); + fail_unless(nta_outgoing_method(NONE) == sip_method_invalid); + fail_unless(nta_outgoing_method_name(NONE) == NULL); + fail_unless(nta_outgoing_cseq(NONE) == 0); + + fail_unless(nta_outgoing_delay(NONE) == UINT_MAX); + fail_unless(nta_outgoing_request_uri(NONE) == NULL); + fail_unless(nta_outgoing_route_uri(NONE) == NULL); + + fail_unless(nta_outgoing_getresponse(NONE) == NULL); + fail_unless(nta_outgoing_getrequest(NONE) == NULL); + + fail_unless(nta_outgoing_tagged(NONE, NULL, NULL, NULL, NULL) == NULL); + fail_unless(nta_outgoing_cancel(NONE) == -1); + fail_unless(nta_outgoing_tcancel(NONE, NULL, NULL, TAG_END()) == NULL); + mark_point(); nta_outgoing_destroy(NONE); mark_point(); + + fail_unless(nta_reliable_treply(NULL, NULL, NULL, 0, NULL, TAG_END()) == NULL); + fail_unless(nta_reliable_mreply(NULL, NULL, NULL, NULL) == NULL); + mark_point(); nta_reliable_destroy(NULL); mark_point(); + + mark_point(); nta_agent_destroy(nta); mark_point(); + mark_point(); su_home_deinit(home); mark_point(); +} +END_TEST + +/* ---------------------------------------------------------------------- */ + +TCase *check_nta_api_1_0(void) +{ + TCase *tc = tcase_create("NTA 1 - API"); + + tcase_add_checked_fixture(tc, api_setup, api_teardown); + + tcase_set_timeout(tc, 10); + + tcase_add_test(tc, api_1_0_0); + + return tc; +} diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/check_nta_client.c b/libs/sofia-sip/libsofia-sip-ua/nta/check_nta_client.c new file mode 100644 index 0000000000..e80289f538 --- /dev/null +++ b/libs/sofia-sip/libsofia-sip-ua/nta/check_nta_client.c @@ -0,0 +1,388 @@ +/* + * This file is part of the Sofia-SIP package + * + * Copyright (C) 2008 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 check_nta_client.c + * + * @brief Check-driven tester for NTA client transactions + * + * @author Pekka Pessi + * + * @copyright (C) 2009 Nokia Corporation. + */ + +#include "config.h" + +#include "check_nta.h" +#include "s2base.h" +#include "s2dns.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define NONE ((void *)-1) + +static void +client_setup(void) +{ + s2_nta_setup("NTA", NULL, TAG_END()); + s2_nta_agent_setup(URL_STRING_MAKE("sip:0.0.0.0:*"), NULL, NULL, + NTATAG_DEFAULT_PROXY("sip:example.org"), + TAG_END()); +} + +static void +client_setup_udp_only_server(void) +{ + char const * const transports[] = { "udp", NULL }; + + s2_nta_setup("NTA", transports, TAG_END()); + s2_nta_agent_setup(URL_STRING_MAKE("sip:0.0.0.0:*"), NULL, NULL, + NTATAG_DEFAULT_PROXY(s2sip->contact->m_url), + TAG_END()); +} + +static void +client_setup_tcp_only_server(void) +{ + char const * const transports[] = { "tcp", NULL }; + + s2_nta_setup("NTA", transports, TAG_END()); + s2_nta_agent_setup(URL_STRING_MAKE("sip:0.0.0.0:*"), NULL, NULL, + NTATAG_DEFAULT_PROXY(s2sip->contact->m_url), + TAG_END()); +} + +static void +client_teardown(void) +{ + mark_point(); + s2_nta_teardown(); +} + +START_TEST(client_2_0_0) +{ + nta_outgoing_t *orq; + struct message *request; + struct event *response; + + s2_case("2.0.0", "Send MESSAGE", + "Basic non-INVITE transaction with outbound proxy"); + + orq = nta_outgoing_tcreate(s2->default_leg, + s2_nta_orq_callback, NULL, NULL, + SIP_METHOD_MESSAGE, + URL_STRING_MAKE("sip:test2.0.example.org"), + SIPTAG_FROM_STR(""), + TAG_END()); + fail_unless(orq != NULL); + request = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); + fail_unless(request != NULL); + s2_sip_respond_to(request, NULL, 200, "2.0.0", TAG_END()); + response = s2_nta_wait_for(wait_for_orq, orq, + wait_for_status, 200, + 0); + s2_sip_free_message(request); + s2_nta_free_event(response); + nta_outgoing_destroy(orq); +} +END_TEST + +START_TEST(client_2_0_1) +{ + nta_outgoing_t *orq; + struct message *request; + struct event *response; + + s2_case("2.0.0", "Send MESSAGE", + "Basic non-INVITE transaction with " + "numeric per-transaction outbound proxy"); + + orq = nta_outgoing_tcreate(s2->default_leg, + s2_nta_orq_callback, NULL, + (url_string_t *)s2sip->contact->m_url, + SIP_METHOD_MESSAGE, + URL_STRING_MAKE("sip:test2.0.example.org"), + SIPTAG_FROM_STR(""), + TAG_END()); + fail_unless(orq != NULL); + request = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); + fail_unless(request != NULL); + s2_sip_respond_to(request, NULL, 200, "OK 2.0.1", TAG_END()); + response = s2_nta_wait_for(wait_for_orq, orq, + wait_for_status, 200, + 0); + s2_sip_free_message(request); + s2_nta_free_event(response); + nta_outgoing_destroy(orq); +} +END_TEST + +START_TEST(client_2_0_2) +{ + nta_outgoing_t *orq; + struct message *request; + struct event *response; + + char payload[2048]; + + s2_case("2.0.2", "Send MESSAGE", + "Basic non-INVITE transaction exceeding " + "default path MTU (1300 bytes)"); + + memset(payload, 'x', sizeof payload); + payload[(sizeof payload) - 1] = '\0'; + + orq = nta_outgoing_tcreate(s2->default_leg, + s2_nta_orq_callback, NULL, NULL, + SIP_METHOD_MESSAGE, + URL_STRING_MAKE("sip:test2.0.example.org"), + SIPTAG_FROM_STR(""), + SIPTAG_PAYLOAD_STR(payload), + TAG_END()); + fail_unless(orq != NULL); + request = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); + fail_unless(request != NULL); + fail_unless(request->sip->sip_via->v_protocol == sip_transport_tcp); + + s2_sip_respond_to(request, NULL, 200, "OK 2.0.2", TAG_END()); + response = s2_nta_wait_for(wait_for_orq, orq, + wait_for_status, 200, + 0); + s2_nta_free_event(response); + nta_outgoing_destroy(orq); +} +END_TEST + +/* ---------------------------------------------------------------------- */ + +TCase *check_nta_client_2_0(void) +{ + TCase *tc = tcase_create("NTA 2.0 - Client"); + + tcase_add_checked_fixture(tc, client_setup, client_teardown); + + tcase_set_timeout(tc, 2); + + tcase_add_test(tc, client_2_0_0); + tcase_add_test(tc, client_2_0_1); + tcase_add_test(tc, client_2_0_2); + + return tc; +} + +/* ---------------------------------------------------------------------- */ + +START_TEST(client_2_1_0) +{ + nta_outgoing_t *orq; + struct message *request; + struct event *response; + + char payload[2048]; + + s2_case("2.1.0", "Try UDP after trying with TCP", + "TCP connect() is refused"); + + memset(payload, 'x', sizeof payload); + payload[(sizeof payload) - 1] = '\0'; + + client_setup_udp_only_server(); + + orq = nta_outgoing_tcreate(s2->default_leg, + s2_nta_orq_callback, NULL, NULL, + SIP_METHOD_MESSAGE, + URL_STRING_MAKE("sip:test2.0.example.org"), + SIPTAG_FROM_STR(""), + SIPTAG_PAYLOAD_STR(payload), + TAG_END()); + fail_unless(orq != NULL); + + request = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); + fail_unless(request != NULL); + fail_unless(request->sip->sip_via->v_protocol == sip_transport_udp); + s2_sip_respond_to(request, NULL, 200, "OK", TAG_END()); + s2_sip_free_message(request); + + response = s2_nta_wait_for(wait_for_orq, orq, + wait_for_status, 200, + 0); + s2_nta_free_event(response); + nta_outgoing_destroy(orq); +} +END_TEST + +#undef SU_LOG + +#include "tport_internal.h" + +tport_vtable_t hacked_tcp_vtable; + +/* Make TCP connection to 192.168.255.2:9999 */ +static tport_t * +hacked_tcp_connect(tport_primary_t *pri, + su_addrinfo_t *ai, + tp_name_t const *tpn) +{ + su_addrinfo_t fake_ai[1]; + su_sockaddr_t fake_addr[1]; + uint32_t fake_ip = htonl(0xc0a8ff02); /* 192.168.255.2 */ + + *fake_ai = *ai; + assert(ai->ai_addrlen <= (sizeof fake_addr)); + fake_ai->ai_addr = memcpy(fake_addr, ai->ai_addr, ai->ai_addrlen); + + fake_ai->ai_family = AF_INET; + fake_addr->su_family = AF_INET; + memcpy(&fake_addr->su_sin.sin_addr, &fake_ip, sizeof fake_ip); + fake_addr->su_sin.sin_port = htons(9999); + + return tport_base_connect(pri, fake_ai, ai, tpn); +} + +START_TEST(client_2_1_1) +{ + tport_t *tp; + + nta_outgoing_t *orq; + struct message *request; + struct event *response; + + char payload[2048]; + + s2_case("2.1.1", "Try UDP after trying with TCP", + "TCP connect() times out"); + + memset(payload, 'x', sizeof payload); + payload[(sizeof payload) - 1] = '\0'; + + client_setup_udp_only_server(); + + hacked_tcp_vtable = tport_tcp_vtable; + hacked_tcp_vtable.vtp_connect = hacked_tcp_connect; + fail_unless(tport_tcp_vtable.vtp_connect == NULL); + + for (tp = tport_primaries(nta_agent_tports(s2->nta)); + tp; + tp = tport_next(tp)) { + if (tport_is_tcp(tp)) { + tp->tp_pri->pri_vtable = &hacked_tcp_vtable; + break; + } + } + + orq = nta_outgoing_tcreate(s2->default_leg, + s2_nta_orq_callback, NULL, + NULL, + SIP_METHOD_MESSAGE, + URL_STRING_MAKE("sip:test2.0.example.org"), + SIPTAG_FROM_STR(""), + SIPTAG_PAYLOAD_STR(payload), + TAG_END()); + fail_unless(orq != NULL); + + s2_fast_forward(1, s2->root); + s2_fast_forward(1, s2->root); + s2_fast_forward(1, s2->root); + s2_fast_forward(1, s2->root); + s2_fast_forward(1, s2->root); + + request = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); + fail_unless(request != NULL); + fail_unless(request->sip->sip_via->v_protocol == sip_transport_udp); + s2_sip_respond_to(request, NULL, 200, "OK", TAG_END()); + s2_sip_free_message(request); + + response = s2_nta_wait_for(wait_for_orq, orq, + wait_for_status, 200, + 0); + s2_nta_free_event(response); + nta_outgoing_destroy(orq); +} +END_TEST + +START_TEST(client_2_1_2) +{ + nta_outgoing_t *orq; + struct message *request; + struct event *response; + url_t udpurl[1]; + + s2_case("2.1.2", "Send MESSAGE", + "Non-INVITE transaction to TCP-only server"); + + client_setup_tcp_only_server(); + + *udpurl = *s2sip->tcp.contact->m_url; + udpurl->url_params = "transport=udp"; + + /* Create DNS records for both UDP and TCP */ + s2_dns_domain("udptcp.org", 1, + "s2", 1, udpurl, + "s2", 1, s2sip->tcp.contact->m_url, + NULL); + + orq = nta_outgoing_tcreate(s2->default_leg, + s2_nta_orq_callback, NULL, + URL_STRING_MAKE("sip:udptcp.org"), + SIP_METHOD_MESSAGE, + URL_STRING_MAKE("sip:test2.0.example.org"), + SIPTAG_FROM_STR(""), + TAG_END()); + fail_unless(orq != NULL); + request = s2_sip_wait_for_request(SIP_METHOD_MESSAGE); + fail_unless(request != NULL); + s2_sip_respond_to(request, NULL, 200, "2.0.0", TAG_END()); + s2_sip_free_message(request); + response = s2_nta_wait_for(wait_for_orq, orq, + wait_for_status, 200, + 0); + s2_nta_free_event(response); + nta_outgoing_destroy(orq); +} +END_TEST + + +TCase *check_nta_client_2_1(void) +{ + TCase *tc = tcase_create("NTA 2.1 - Client"); + + tcase_add_checked_fixture(tc, NULL, client_teardown); + + tcase_set_timeout(tc, 20); + + tcase_add_test(tc, client_2_1_0); + tcase_add_test(tc, client_2_1_1); + tcase_add_test(tc, client_2_1_2); + + return tc; +} diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/run_check_nta b/libs/sofia-sip/libsofia-sip-ua/nta/run_check_nta new file mode 100644 index 0000000000..772cd95c4c --- /dev/null +++ b/libs/sofia-sip/libsofia-sip-ua/nta/run_check_nta @@ -0,0 +1,2 @@ +#!/bin/sh +$VALGRIND exec ./check_nta "$@" \ No newline at end of file