diff --git a/libs/sofia-sip/Makefile.am b/libs/sofia-sip/Makefile.am index a60e0c8898..5539a0b267 100644 --- a/libs/sofia-sip/Makefile.am +++ b/libs/sofia-sip/Makefile.am @@ -7,7 +7,7 @@ AUTOMAKE_OPTIONS = foreign 1.7 -SUBDIRS = libsofia-sip-ua $(GLIB_SUBDIRS) utils packages +SUBDIRS = libsofia-sip-ua $(GLIB_SUBDIRS) utils packages tests DIST_SUBDIRS = libsofia-sip-ua libsofia-sip-ua-glib utils packages \ win32 open_c diff --git a/libs/sofia-sip/configure.ac b/libs/sofia-sip/configure.ac index 00fe8a32be..58cadbea90 100644 --- a/libs/sofia-sip/configure.ac +++ b/libs/sofia-sip/configure.ac @@ -100,6 +100,10 @@ SAC_SOFIA_SU SAC_OPENSSL SAC_TPORT +dnl Check is used for testing +PKG_CHECK_MODULES(CHECK, check >= 0.9.4, have_check="yes", have_check="no") +AM_CONDITIONAL(HAVE_CHECK, test x"$have_check" = "xyes") + ### internal modules ### ---------------- AC_DEFINE([HAVE_SOFIA_SIP], 1, [Define to 1 always]) @@ -122,11 +126,12 @@ fi AM_CONDITIONAL([HAVE_STUN], [test "x$enable_stun" = xyes]) AC_ARG_ENABLE(nth, -[ --disable-nth disable nth and http modules (enabled)], +[ --disable-nth disable HTTP-related modules nth and http (enabled)], , enable_nth=yes) AM_CONDITIONAL([HAVE_NTH], [test "x$enable_nth" = xyes]) if test x$enable_nth = xyes ; then AC_DEFINE([HAVE_SOFIA_NTH], 1, [Define to 1 if we use NTH library]) + AC_DEFINE([HAVE_SOFIA_HTTP], 1, [Define to 1 if we use HTTP parser library]) fi dnl Disable NTLM support by default @@ -325,6 +330,7 @@ libsofia-sip-ua-glib/su-glib/Makefile libsofia-sip-ua-glib/su-glib/Doxyfile utils/Makefile utils/Doxyfile +tests/Makefile win32/Makefile win32/config.h open_c/Makefile diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c index 3bd34df648..d010f9ca14 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c +++ b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c @@ -2780,12 +2780,26 @@ void nta_msg_discard(nta_agent_t *agent, msg_t *msg) msg_destroy(msg); } +/** Check if the headers are from response generated locally by NTA. */ +int nta_sip_is_internal(sip_t const *sip) +{ + return + sip == NULL /* No message generated */ + || (sip->sip_flags & NTA_INTERNAL_MSG) == NTA_INTERNAL_MSG; +} + /** Check if the message is internally generated by NTA. */ -int nta_is_internal_msg(msg_t const *msg) +int nta_msg_is_internal(msg_t const *msg) { return msg_get_flags(msg, NTA_INTERNAL_MSG) == NTA_INTERNAL_MSG; } +/** Check if the message is internally generated by NTA. + * + * @deprecated Use nta_msg_is_internal() instead + */ +int nta_is_internal_msg(msg_t const *msg) { return nta_msg_is_internal(msg); } + /* ====================================================================== */ /* 5) Stateless operation */ @@ -6343,6 +6357,7 @@ static int outgoing_features(nta_agent_t *agent, nta_outgoing_t *orq, msg_t *msg, sip_t *sip, tagi_t *tags); static void outgoing_prepare_send(nta_outgoing_t *orq); +static void outgoing_send_via(nta_outgoing_t *orq, tport_t *tp); static void outgoing_send(nta_outgoing_t *orq, int retransmit); static void outgoing_try_tcp_instead(nta_outgoing_t *orq); static void outgoing_try_udp_instead(nta_outgoing_t *orq); @@ -6884,7 +6899,7 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent, int invite_100rel = agent->sa_invite_100rel; tagi_t const *t; - tport_t const *override_tport = NULL; + tport_t *override_tport = NULL; if (!agent->sa_tport_ip6) res_order = nta_res_ip4_only; @@ -6988,11 +7003,16 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent, tpn = tport_name(override_tport); orq->orq_user_tport = 1; } - } - if (route_url) { + if (route_url && !orq->orq_user_tport) { invalid = nta_tpn_by_url(home, orq->orq_tpn, &scheme, &port, route_url); + + if (override_tport) { /* Use transport protocol name from transport */ + if (strcmp(orq->orq_tpn->tpn_proto, "*") == 0) + orq->orq_tpn->tpn_proto = tport_name(override_tport)->tpn_proto; + } + resolved = tport_name_is_resolved(orq->orq_tpn); orq->orq_url = url_hdup(home, sip->sip_request->rq_url); if (route_url != (url_string_t *)agent->sa_default_proxy) @@ -7015,7 +7035,11 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent, sip_fragment_clear(sip->sip_request->rq_common); } - orq->orq_tpn->tpn_ident = tp_ident; + if (!override_tport) + orq->orq_tpn->tpn_ident = tp_ident; + else + orq->orq_tpn->tpn_ident = tport_name(override_tport)->tpn_ident; + if (comp == NULL) orq->orq_tpn->tpn_comp = comp; @@ -7100,7 +7124,9 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent, agent->sa_stats->as_client_tr++; orq->orq_hash = NTA_HASH(sip->sip_call_id, sip->sip_cseq->cs_seq); - if (resolved) + if (orq->orq_user_tport) + outgoing_send_via(orq, override_tport); + else if (resolved) outgoing_prepare_send(orq); #if HAVE_SOFIA_SRESOLV else @@ -7146,7 +7172,6 @@ outgoing_prepare_send(nta_outgoing_t *orq) tpn->tpn_port = ""; tp = tport_by_name(sa->sa_tports, tpn); - orq->orq_tport = tport_ref(tp); if (tpn->tpn_port[0] == '\0') { if (sips || tport_has_tls(tp)) @@ -7155,17 +7180,28 @@ outgoing_prepare_send(nta_outgoing_t *orq) tpn->tpn_port = "5060"; } - if (!orq->orq_tport) { - if (sips) { - SU_DEBUG_3(("nta outgoing create: no secure transport\n")); - outgoing_reply(orq, SIP_416_UNSUPPORTED_URI, 1); - } - else { - SU_DEBUG_3(("nta outgoing create: no transport protocol\n")); - outgoing_reply(orq, 503, "No transport", 1); - } - return; + if (tp) { + outgoing_send_via(orq, tp); } + else if (sips) { + SU_DEBUG_3(("nta outgoing create: no secure transport\n")); + outgoing_reply(orq, SIP_416_UNSUPPORTED_URI, 1); + } + else { + SU_DEBUG_3(("nta outgoing create: no transport protocol\n")); + outgoing_reply(orq, 503, "No transport", 1); + } +} + +/** Send request using given transport */ +static void +outgoing_send_via(nta_outgoing_t *orq, tport_t *tp) +{ + tport_t *old_tp = orq->orq_tport; + + orq->orq_tport = tport_ref(tp); + + if (old_tp) tport_unref(old_tp); if (outgoing_insert_via(orq, agent_tport_via(tp)) < 0) { SU_DEBUG_3(("nta outgoing create: cannot insert Via line\n")); @@ -7198,13 +7234,14 @@ outgoing_prepare_send(nta_outgoing_t *orq) if (orq->orq_delayed) { SU_DEBUG_5(("nta: delayed sending %s (%u)\n", orq->orq_method_name, orq->orq_cseq->cs_seq)); - outgoing_queue(sa->sa_out.delayed, orq); + outgoing_queue(orq->orq_agent->sa_out.delayed, orq); return; } outgoing_send(orq, 0); } + /** Send a request */ static void outgoing_send(nta_outgoing_t *orq, int retransmit) @@ -7226,6 +7263,11 @@ outgoing_send(nta_outgoing_t *orq, int retransmit) return; } + if (orq->orq_user_tport && !tport_is_clear_to_send(orq->orq_tport)) { + outgoing_tport_error(agent, orq, NULL, orq->orq_request, EPIPE); + return; + } + if (!retransmit) orq->orq_sent = now; diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta.h b/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta.h index 50fd4d735d..2d34688774 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta.h +++ b/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta.h @@ -170,7 +170,8 @@ SOFIAPUBFUN int nta_msg_request_complete(msg_t *msg, char const *method_name, url_string_t const *req_url); -SOFIAPUBFUN int nta_is_internal_msg(msg_t const *msg); +SOFIAPUBFUN int nta_msg_is_internal(msg_t const *msg); +SOFIAPUBFUN int nta_sip_is_internal(sip_t const *sip); /* ---------------------------------------------------------------------- * 5) Leg-level prototypes @@ -479,6 +480,8 @@ SOFIAPUBFUN void nta_reliable_destroy(nta_reliable_t *); SOFIAPUBFUN void nta_msg_discard(nta_agent_t *agent, msg_t *msg); +SOFIAPUBFUN int nta_is_internal_msg(msg_t const *msg); + SOFIA_END_DECLS #endif diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/test_nta.c b/libs/sofia-sip/libsofia-sip-ua/nta/test_nta.c index 4cc562fbc0..8314f8279e 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/test_nta.c +++ b/libs/sofia-sip/libsofia-sip-ua/nta/test_nta.c @@ -35,6 +35,7 @@ #include "config.h" typedef struct agent_t agent_t; +typedef struct client_t client_t; #define SU_ROOT_MAGIC_T agent_t @@ -44,7 +45,8 @@ typedef struct agent_t agent_t; #define NTA_AGENT_MAGIC_T agent_t #define NTA_LEG_MAGIC_T agent_t -#define NTA_OUTGOING_MAGIC_T agent_t +#define NTA_OUTGOING_MAGIC_T client_t +#define NTA_OUTGOING_MAGIC_T0 agent_t #define NTA_INCOMING_MAGIC_T agent_t #define NTA_RELIABLE_MAGIC_T agent_t @@ -59,6 +61,7 @@ typedef struct agent_t agent_t; #include #include #include +#include #include @@ -99,6 +102,24 @@ struct sigcomp_compartment; char const name[] = "test_nta"; +typedef struct invite_client_t invite_client_t; + +typedef int client_check_f(client_t *, nta_outgoing_t *, sip_t const *); +typedef int client_deinit_f(client_t *); + +struct client_t { + agent_t *c_ag; + char const *c_name; + client_check_f * c_check; + client_check_f * const * c_checks; + client_deinit_f * c_deinit; + void *c_extra; + nta_outgoing_t *c_orq; + int c_status; + int c_final; + int c_errors; +}; + struct agent_t { su_home_t ag_home[1]; int ag_flags; @@ -114,8 +135,7 @@ struct agent_t { unsigned ag_drop; nta_outgoing_t *ag_orq; - int ag_status; - unsigned ag_canceled:1, ag_acked:1, :0; + unsigned ag_running :1, ag_canceled:1, ag_acked:1, :0; char const *ag_comp; struct sigcomp_compartment *ag_client_compartment; @@ -147,12 +167,8 @@ struct agent_t { nta_leg_t *ag_tag_remote; /**< If this is set, outgoing_callback() * tags it with the tag from remote. */ - int ag_tag_status; /**< Which response established dialog */ - msg_param_t ag_call_tag; /**< Tag used to establish dialog */ - nta_reliable_t *ag_reliable; - sip_via_t *ag_out_via; /**< Outgoing via */ sip_via_t *ag_in_via; /**< Incoming via */ sip_content_type_t *ag_content_type; @@ -160,6 +176,7 @@ struct agent_t { msg_t *ag_probe_msg; + /* Dummy servers */ char const *ag_sink_port; su_socket_t ag_sink_socket, ag_down_socket; @@ -241,8 +258,8 @@ void leg_zap(agent_t *ag, nta_leg_t *leg) else if (leg == ag->ag_bob_leg) ag->ag_bob_leg = NULL; else - printf("%s:%u: %s: did not exist\n", - __FILE__, __LINE__, __func__); + printf("%s:%u: %s: did not exist\n", + __FILE__, __LINE__, __func__); nta_leg_destroy(leg); } @@ -344,76 +361,71 @@ int new_leg_callback_200(agent_t *ag, } -int outgoing_callback(agent_t *ag, +static client_check_f * const default_checks[]; + +int outgoing_callback(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) { - BEGIN(); - - int status = sip->sip_status->st_status; + agent_t *ag = ctx->c_ag; + int status = nta_outgoing_status(orq); + client_check_f * const *checks; if (tstflags & tst_verbatim) { - printf("%s: %s: %s %03d %s\n", name, __func__, - sip->sip_status->st_version, - sip->sip_status->st_status, - sip->sip_status->st_phrase); + if (sip) + printf("%s: %s: response %s %03d %s\n", name, ctx->c_name, + sip->sip_status->st_version, + sip->sip_status->st_status, + sip->sip_status->st_phrase); + else + printf("%s: %s: callback %03d\n", name, ctx->c_name, + status); } - TEST_P(orq, ag->ag_orq); - - ag->ag_status = status; - - if (status < 200) - return 0; - - if (ag->ag_comp) { + if (status >= 200 && ag->ag_comp) { /* XXX */ nta_compartment_decref(&ag->ag_client_compartment); - ag->ag_client_compartment = nta_outgoing_compartment(orq); + ag->ag_client_compartment = nta_outgoing_compartment(ctx->c_orq); } - if (ag->ag_out_via == NULL) - ag->ag_out_via = sip_via_dup(ag->ag_home, sip->sip_via); + if (status > ctx->c_status) + ctx->c_status = status; + if (status >= 200) + ctx->c_final = 1; - if (ag->ag_tag_remote) { - TEST_S(nta_leg_rtag(ag->ag_tag_remote, sip->sip_to->a_tag), - sip->sip_to->a_tag); - ag->ag_tag_remote = NULL; - } + if (ctx->c_check && ctx->c_check(ctx, orq, sip)) + ctx->c_errors++; - TEST_1(sip->sip_to && sip->sip_to->a_tag); + checks = ctx->c_checks; - nta_outgoing_destroy(orq); - ag->ag_orq = NULL; + for (checks = checks ? checks : default_checks; *checks; checks++) + if ((*checks)(ctx, ctx->c_orq, sip)) + ctx->c_errors++; - END(); + return 0; } -static -int test_magic_branch(agent_t *ag, sip_t const *sip) +/** Deinit client. Return nonzero if client checks failed. */ +static +int client_deinit(client_t *c) { - BEGIN(); - - if (sip) { - TEST_1(sip->sip_via); - TEST_S(sip->sip_via->v_branch, "MagicalBranch"); - } + int errors = c->c_errors; - END(); + if (c->c_deinit && c->c_deinit(c)) + errors++; + + if (c->c_orq) nta_outgoing_destroy(c->c_orq), c->c_orq = NULL; + + c->c_errors = 0; + c->c_status = 0; + + return errors; } -static -int magic_callback(agent_t *ag, - nta_outgoing_t *orq, - sip_t const *sip) -{ - test_magic_branch(ag, sip); - return outgoing_callback(ag, orq, sip); -} -void -nta_test_run(agent_t *ag) +static +void nta_test_run(agent_t *ag) { - for (ag->ag_status = 0; ag->ag_status < 200;) { + for (ag->ag_running = 1; ag->ag_running;) { if (tstflags & tst_verbatim) { fputs(".", stdout); fflush(stdout); } @@ -421,10 +433,50 @@ nta_test_run(agent_t *ag) } } -void -nta_test_run_until_acked(agent_t *ag) + +/** Run client test. Return nonzero if client checks failed. */ +static +int client_run_with(client_t *c, int expected, void (*runner)(client_t *c)) { - ag->ag_status = 0; + int resulting; + + TEST_1(c->c_orq != NULL); + + runner(c); + + resulting = c->c_status; + + if (client_deinit(c)) + return 1; + + if (expected) + TEST(resulting, expected); + + return 0; +} + +static +void until_final_received(client_t *c) +{ + for (c->c_final = 0; !c->c_final; ) { + if (tstflags & tst_verbatim) { + fputs(".", stdout); fflush(stdout); + } + su_root_step(c->c_ag->ag_root, 500L); + } +} + +static +int client_run(client_t *c, int expected) +{ + return client_run_with(c, expected, until_final_received); +} + +static +void until_server_acked(client_t *c) +{ + agent_t *ag = c->c_ag; + for (ag->ag_acked = 0; !ag->ag_acked;) { if (tstflags & tst_verbatim) { fputs(".", stdout); fflush(stdout); @@ -433,10 +485,17 @@ nta_test_run_until_acked(agent_t *ag) } } -void -nta_test_run_until_canceled(agent_t *ag) +static +int client_run_until_acked(client_t *c, int expected) { - ag->ag_status = 0; + return client_run_with(c, expected, until_server_acked); +} + +void +until_server_canceled(client_t *c) +{ + agent_t *ag = c->c_ag; + for (ag->ag_canceled = 0; !ag->ag_canceled;) { if (tstflags & tst_verbatim) { fputs(".", stdout); fflush(stdout); @@ -445,6 +504,13 @@ nta_test_run_until_canceled(agent_t *ag) } } +static +int client_run_until_canceled(client_t *c, int expected) +{ + return client_run_with(c, expected, until_server_canceled); +} + + #include int test_init(agent_t *ag, char const *resolv_conf) @@ -507,16 +573,16 @@ int test_init(agent_t *ag, char const *resolv_conf) /* Create agent */ ag->ag_agent = nta_agent_create(ag->ag_root, - (url_string_t *)contact, - NULL, - NULL, - NTATAG_MCLASS(ag->ag_mclass), - NTATAG_USE_TIMESTAMP(1), - SRESTAG_RESOLV_CONF(resolv_conf), - NTATAG_USE_NAPTR(0), - NTATAG_USE_SRV(0), - NTATAG_PRELOAD(2048), - TAG_END()); + (url_string_t *)contact, + NULL, + NULL, + NTATAG_MCLASS(ag->ag_mclass), + NTATAG_USE_TIMESTAMP(1), + SRESTAG_RESOLV_CONF(resolv_conf), + NTATAG_USE_NAPTR(0), + NTATAG_USE_SRV(0), + NTATAG_PRELOAD(2048), + TAG_END()); TEST_1(ag->ag_agent); { @@ -582,30 +648,30 @@ int test_init(agent_t *ag, char const *resolv_conf) ag->ag_aliases = m; err = nta_agent_set_params(ag->ag_agent, - NTATAG_ALIASES(ag->ag_aliases), - NTATAG_REL100(1), - NTATAG_UA(1), - NTATAG_USE_NAPTR(1), - NTATAG_USE_SRV(1), - NTATAG_MAX_FORWARDS(20), - TAG_END()); + NTATAG_ALIASES(ag->ag_aliases), + NTATAG_REL100(1), + NTATAG_UA(1), + NTATAG_USE_NAPTR(1), + NTATAG_USE_SRV(1), + NTATAG_MAX_FORWARDS(20), + TAG_END()); TEST(err, 6); err = nta_agent_set_params(ag->ag_agent, - NTATAG_ALIASES(ag->ag_aliases), - NTATAG_DEFAULT_PROXY("sip:127.0.0.1"), - TAG_END()); + NTATAG_ALIASES(ag->ag_aliases), + NTATAG_DEFAULT_PROXY("sip:127.0.0.1"), + TAG_END()); TEST(err, 2); err = nta_agent_set_params(ag->ag_agent, - NTATAG_ALIASES(ag->ag_aliases), - NTATAG_DEFAULT_PROXY(NULL), - TAG_END()); + NTATAG_ALIASES(ag->ag_aliases), + NTATAG_DEFAULT_PROXY(NULL), + TAG_END()); TEST(err, 2); err = nta_agent_set_params(ag->ag_agent, - NTATAG_DEFAULT_PROXY("tel:+35878008000"), - TAG_END()); + NTATAG_DEFAULT_PROXY("tel:+35878008000"), + TAG_END()); TEST(err, -1); } @@ -617,11 +683,11 @@ int test_init(agent_t *ag, char const *resolv_conf) *url = *ag->ag_aliases->m_url; url->url_user = "%"; ag->ag_server_leg = nta_leg_tcreate(ag->ag_agent, - leg_callback_200, - ag, - NTATAG_NO_DIALOG(1), - URLTAG_URL(url), - TAG_END()); + leg_callback_200, + ag, + NTATAG_NO_DIALOG(1), + URLTAG_URL(url), + TAG_END()); TEST_1(ag->ag_server_leg); } @@ -634,10 +700,10 @@ int test_reinit(agent_t *ag) /* Create a new default leg */ nta_leg_destroy(ag->ag_default_leg), ag->ag_default_leg = NULL; TEST_1(ag->ag_default_leg = nta_leg_tcreate(ag->ag_agent, - leg_callback_200, - ag, - NTATAG_NO_DIALOG(1), - TAG_END())); + leg_callback_200, + ag, + NTATAG_NO_DIALOG(1), + TAG_END())); END(); } @@ -836,6 +902,92 @@ sip_payload_t *test_payload(su_home_t *home, size_t size) return pl; } +static +int client_check_to_tag(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) +{ + if (sip) + TEST_1(sip->sip_to && sip->sip_to->a_tag); + return 0; +} + +static +int check_magic_branch(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) +{ + if (sip) { + TEST_1(sip->sip_via); + TEST_S(sip->sip_via->v_branch, "MagicalBranch"); + } + return 0; +} + +static +int check_via_with_sigcomp(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) +{ + if (sip && sip->sip_via) { + TEST_S(sip->sip_via->v_comp, "sigcomp"); + } + return 0; +} + +static +int check_via_without_sigcomp(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) +{ + if (sip && sip->sip_via) { + TEST_1(sip->sip_via->v_comp == NULL); + } + return 0; +} + +static +int check_via_with_tcp(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) +{ + if (sip && sip->sip_via) { + TEST_S(sip->sip_via->v_protocol, "SIP/2.0/TCP"); + } + return 0; +} + +static +int check_via_with_sctp(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) +{ + if (sip && sip->sip_via) { + TEST_S(sip->sip_via->v_protocol, "SIP/2.0/SCTP"); + } + return 0; +} + +static +int check_via_with_udp(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) +{ + if (sip && sip->sip_via) { + TEST_S(sip->sip_via->v_protocol, "SIP/2.0/UDP"); + } + return 0; +} + +static +int save_and_check_tcp(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) +{ + if (ctx->c_status >= 200 && ctx->c_extra) { + tport_t *tport = nta_outgoing_transport(orq); + TEST_1(tport); + *(tport_t **)ctx->c_extra = tport; + } + + return check_via_with_tcp(ctx, orq, sip); +} + + +static client_check_f * const default_checks[] = { + client_check_to_tag, + NULL +}; + +static client_check_f * const no_default_checks[] = { + NULL +}; + + /* Test transports */ int test_tports(agent_t *ag) @@ -844,6 +996,7 @@ int test_tports(agent_t *ag) sip_via_t const *v, *v_udp_only = NULL; char const *udp_comp = NULL; char const *tcp_comp = NULL; + tport_t *tcp_tport = NULL; url_t url[1]; @@ -893,36 +1046,32 @@ int test_tports(agent_t *ag) */ char const p_acid[] = "P-Access-Network-Info: IEEE-802.11g\n"; url_t url[1]; + client_t ctx[1] = {{ ag, "Test 0.1", check_via_without_sigcomp }}; *url = *ag->ag_contact->m_url; url->url_params = NULL; ag->ag_expect_leg = ag->ag_default_leg; - su_free(ag->ag_home, (void *)ag->ag_out_via), ag->ag_out_via = NULL; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, - outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.1"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - SIPTAG_HEADER_STR(p_acid), - TAG_END()); - TEST_1(ag->ag_orq); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, + outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + SIPTAG_HEADER_STR(p_acid), + TAG_END()); + + TEST_1(!client_run(ctx, 200)); - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); + TEST_1(ag->ag_request); - msg_destroy(ag->ag_request), ag->ag_request = NULL; - TEST_1(ag->ag_out_via->v_comp == NULL); - nta_leg_bind(ag->ag_default_leg, leg_callback_200, ag); } @@ -933,30 +1082,27 @@ int test_tports(agent_t *ag) */ url_t url[1]; sip_t *sip; + client_t ctx[1] = {{ ag, "Test 0.1.2", check_via_without_sigcomp }}; *url = *ag->ag_contact->m_url; /* Test that method parameter is stripped and headers in query are used */ url->url_params = "method=MESSAGE;user=IP"; url->url_headers = "organization=United%20Testers"; ag->ag_expect_leg = ag->ag_default_leg; - su_free(ag->ag_home, (void *)ag->ag_out_via), ag->ag_out_via = NULL; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, - outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.1.2"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - TAG_END()); - TEST_1(ag->ag_orq); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, + outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + TAG_END()); + TEST_1(!client_run(ctx, 200)); - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); TEST_1(ag->ag_request); TEST_1(sip = sip_object(ag->ag_request)); @@ -965,8 +1111,6 @@ int test_tports(agent_t *ag) TEST_S(sip->sip_organization->g_string, "United Testers"); TEST_S(sip->sip_request->rq_url->url_params, "user=IP"); - TEST_1(ag->ag_out_via->v_comp == NULL); - nta_leg_bind(ag->ag_default_leg, leg_callback_200, ag); } @@ -977,6 +1121,7 @@ int test_tports(agent_t *ag) url_t url[1]; sip_payload_t *pl; size_t size = 1024; + client_t ctx[1] = {{ ag, "Test 0.1.3", check_via_with_sigcomp }}; *url = *ag->ag_aliases->m_url; url->url_user = "alice"; @@ -988,30 +1133,26 @@ int test_tports(agent_t *ag) TEST_1(pl = test_payload(ag->ag_home, size)); ag->ag_expect_leg = ag->ag_server_leg; - su_free(ag->ag_home, (void *)ag->ag_out_via), ag->ag_out_via = NULL; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - NTATAG_COMP("sigcomp"), - SIPTAG_SUBJECT_STR("Test 0.1.3"), - SIPTAG_FROM(ag->ag_bob), - SIPTAG_TO(ag->ag_alice), - SIPTAG_CONTACT(ag->ag_m_bob), - SIPTAG_PAYLOAD(pl), - TAG_END()); - TEST_1(ag->ag_orq); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + NTATAG_COMP("sigcomp"), + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_bob), + SIPTAG_TO(ag->ag_alice), + SIPTAG_CONTACT(ag->ag_m_bob), + SIPTAG_PAYLOAD(pl), + TAG_END()); su_free(ag->ag_home, pl); - nta_test_run(ag); - TEST(ag->ag_status, 200); + TEST_1(!client_run(ctx, 200)); + TEST_1(ag->ag_client_compartment); nta_compartment_decref(&ag->ag_client_compartment); - TEST_P(ag->ag_orq, NULL); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); - TEST_S(ag->ag_out_via->v_comp, "sigcomp"); } /* Test 0.2 @@ -1020,10 +1161,13 @@ int test_tports(agent_t *ag) * of 512 kB */ if (tcp) { + client_t ctx[1] = {{ ag, "Test 0.2", save_and_check_tcp, }}; url_t url[1]; sip_payload_t *pl; usize_t size = 512 * 1024; + ctx->c_extra = &tcp_tport; + *url = *ag->ag_aliases->m_url; url->url_user = "alice"; url->url_params = "transport=tcp"; @@ -1031,32 +1175,120 @@ int test_tports(agent_t *ag) TEST_1(pl = test_payload(ag->ag_home, size)); ag->ag_expect_leg = ag->ag_server_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - NULL, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.2"), - SIPTAG_FROM(ag->ag_bob), - SIPTAG_TO(ag->ag_alice), - SIPTAG_CONTACT(ag->ag_m_bob), - SIPTAG_PAYLOAD(pl), - NTATAG_DEFAULT_PROXY(ag->ag_obp), - TAG_END()); - TEST_1(ag->ag_orq); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + NULL, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_bob), + SIPTAG_TO(ag->ag_alice), + SIPTAG_CONTACT(ag->ag_m_bob), + SIPTAG_PAYLOAD(pl), + NTATAG_DEFAULT_PROXY(ag->ag_obp), + TAG_END()); su_free(ag->ag_home, pl); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + TEST_1(!client_run(ctx, 200)); + TEST_1(tcp_tport); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); } + if (tcp_tport) { + /* Test 0.2.1 - always use transport connection from NTATAG_TPORT() + * + * Test bug reported by geaaru + * - NTATAG_TPORT() is not used if NTATAG_DEFAULT_PROXY() is given + */ + client_t ctx[1] = {{ ag, "Test 0.2.1", save_and_check_tcp }}; + url_t url[1]; + sip_payload_t *pl; + tport_t *used_tport = NULL; + + ctx->c_extra = &used_tport; + + TEST(tport_shutdown(tcp_tport, 1), 0); /* Not going to send anymore */ + + TEST_1(pl = test_payload(ag->ag_home, 512)); + + ag->ag_expect_leg = ag->ag_server_leg; + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + NULL, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_bob), + SIPTAG_TO(ag->ag_alice), + SIPTAG_CONTACT(ag->ag_m_bob), + SIPTAG_PAYLOAD(pl), + NTATAG_DEFAULT_PROXY(ag->ag_obp), + NTATAG_TPORT(tcp_tport), + TAG_END()); + su_free(ag->ag_home, pl); + TEST_1(!client_run(ctx, 503)); + + TEST_P(ag->ag_latest_leg, ag->ag_server_leg); + + TEST_1(used_tport == tcp_tport); + + tport_unref(tcp_tport), tcp_tport = NULL; + + if (v_udp_only) /* Prepare for next test */ + TEST_1(tcp_tport = tport_ref(tport_parent(used_tport))); + tport_unref(used_tport); + } + + if (tcp_tport) { + /* test 0.2.2 - select transport protocol using NTATAG_TPORT() + * + * Use primary NTATAG_TPORT() to select transport + */ + client_t ctx[1] = {{ ag, "Test 0.2.2", save_and_check_tcp }}; + url_t url[1]; + sip_payload_t *pl; + tport_t *used_tport = NULL; + + ctx->c_extra = &used_tport; + TEST_1(tport_is_primary(tcp_tport)); + + TEST_1(pl = test_payload(ag->ag_home, 512)); + + *url = *ag->ag_aliases->m_url; + url->url_user = "alice"; + url->url_host = v_udp_only->v_host; + url->url_port = v_udp_only->v_port; + url->url_params = NULL; /* No sigcomp */ + + ag->ag_expect_leg = ag->ag_server_leg; + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + (url_string_t *)url, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_bob), + SIPTAG_TO(ag->ag_alice), + SIPTAG_CONTACT(ag->ag_m_bob), + SIPTAG_PAYLOAD(pl), + NTATAG_TPORT(tcp_tport), + TAG_END()); + su_free(ag->ag_home, pl); + TEST_1(!client_run(ctx, 503)); + + TEST_P(ag->ag_latest_leg, ag->ag_server_leg); + + TEST_1(used_tport); + TEST_1(tport_is_tcp(used_tport)); + tport_unref(used_tport); + tport_unref(tcp_tport), tcp_tport = NULL; + } + /* Test 0.3 * Send a message from Bob to Alice * This time include a large payload of 512 kB, let NTA choose transport. */ if (tcp) { + client_t ctx[1] = {{ ag, "Test 0.3" }}; url_t url[1]; sip_payload_t *pl; usize_t size = 512 * 1024; @@ -1067,23 +1299,19 @@ int test_tports(agent_t *ag) TEST_1(pl = test_payload(ag->ag_home, size)); ag->ag_expect_leg = ag->ag_server_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.3"), - SIPTAG_FROM(ag->ag_bob), - SIPTAG_TO(ag->ag_alice), - SIPTAG_CONTACT(ag->ag_m_bob), - SIPTAG_PAYLOAD(pl), - TAG_END()); - TEST_1(ag->ag_orq); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_bob), + SIPTAG_TO(ag->ag_alice), + SIPTAG_CONTACT(ag->ag_m_bob), + SIPTAG_PAYLOAD(pl), + TAG_END()); su_free(ag->ag_home, pl); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); } @@ -1092,6 +1320,7 @@ int test_tports(agent_t *ag) * This time include a payload of 2 kB, let NTA choose transport. */ { + client_t ctx[1] = {{ ag, "Test 0.4.1", check_via_with_tcp }}; url_t url[1]; sip_payload_t *pl; usize_t size = 2 * 1024; @@ -1100,30 +1329,24 @@ int test_tports(agent_t *ag) url->url_user = "alice"; TEST_1(pl = test_payload(ag->ag_home, size)); - su_free(ag->ag_home, (void *)ag->ag_out_via), ag->ag_out_via = NULL; ag->ag_expect_leg = ag->ag_server_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.4.1"), - SIPTAG_FROM(ag->ag_bob), - SIPTAG_TO(ag->ag_alice), - SIPTAG_CONTACT(ag->ag_m_bob), - SIPTAG_PAYLOAD(pl), - TAG_END()); - TEST_1(ag->ag_orq); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_bob), + SIPTAG_TO(ag->ag_alice), + SIPTAG_CONTACT(ag->ag_m_bob), + SIPTAG_PAYLOAD(pl), + TAG_END()); su_free(ag->ag_home, pl); - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + TEST_1(!client_run(ctx, 200)); + TEST_P(ag->ag_latest_leg, ag->ag_server_leg); - TEST_1(ag->ag_out_via); - TEST_1(strcasecmp(ag->ag_out_via->v_protocol, "SIP/2.0/TCP") == 0 || - strcasecmp(ag->ag_out_via->v_protocol, "SIP/2.0/SCTP") == 0); su_free(ag->ag_home, ag->ag_in_via), ag->ag_in_via = NULL; } @@ -1132,6 +1355,7 @@ int test_tports(agent_t *ag) * This time include a payload of 2 kB, let NTA choose transport. */ if (v_udp_only) { + client_t ctx[1] = {{ ag, "Test 0.4.2", check_via_with_udp }}; url_t url[1]; sip_payload_t *pl; usize_t size = 2 * 1024; @@ -1148,24 +1372,23 @@ int test_tports(agent_t *ag) su_free(ag->ag_home, ag->ag_in_via), ag->ag_in_via = NULL; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.4.2"), - SIPTAG_FROM(ag->ag_bob), - SIPTAG_TO(ag->ag_alice), - SIPTAG_CONTACT(ag->ag_m_bob), - SIPTAG_PAYLOAD(pl), - TAG_END()); - TEST_1(ag->ag_orq); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_bob), + SIPTAG_TO(ag->ag_alice), + SIPTAG_CONTACT(ag->ag_m_bob), + SIPTAG_PAYLOAD(pl), + TAG_END()); su_free(ag->ag_home, pl); - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + TEST_1(!client_run(ctx, 200)); + TEST_P(ag->ag_latest_leg, ag->ag_default_leg); + TEST_1(ag->ag_in_via); TEST_1(strcasecmp(ag->ag_in_via->v_protocol, "SIP/2.0/UDP") == 0); su_free(ag->ag_home, ag->ag_in_via), ag->ag_in_via = NULL; @@ -1176,6 +1399,7 @@ int test_tports(agent_t *ag) * This time include a payload of 2 kB, try to use UDP. */ if (udp) { + client_t ctx[1] = {{ ag, "Test 0.5", check_via_with_udp }}; url_t url[1]; sip_payload_t *pl; usize_t size = 2 * 1024; @@ -1185,36 +1409,33 @@ int test_tports(agent_t *ag) TEST_1(pl = test_payload(ag->ag_home, size)); - su_free(ag->ag_home, (void *)ag->ag_out_via), ag->ag_out_via = NULL; - ag->ag_expect_leg = ag->ag_server_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.5"), - SIPTAG_FROM(ag->ag_bob), - SIPTAG_TO(ag->ag_alice), - SIPTAG_CONTACT(ag->ag_m_bob), - SIPTAG_PAYLOAD(pl), - TPTAG_MTU(0xffffffff), - TAG_END()); - TEST_1(ag->ag_orq); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_bob), + SIPTAG_TO(ag->ag_alice), + SIPTAG_CONTACT(ag->ag_m_bob), + SIPTAG_PAYLOAD(pl), + TPTAG_MTU(0xffffffff), + TAG_END()); su_free(ag->ag_home, pl); - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + TEST_1(!client_run(ctx, 200)); + TEST_P(ag->ag_latest_leg, ag->ag_server_leg); - TEST_1(ag->ag_out_via); - TEST_S(ag->ag_out_via->v_protocol, "SIP/2.0/UDP"); } if (udp) { - /* Send a message from default leg to server leg + /* Test 0.6 + * Send a message from default leg to server leg * using a prefilled Via header */ + client_t ctx[1] = {{ ag, "Test 0.6", check_magic_branch }}; + sip_via_t via[1]; sip_via_init(via); @@ -1232,22 +1453,18 @@ int test_tports(agent_t *ag) TAG_END()); ag->ag_expect_leg = ag->ag_server_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, - magic_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.6"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - SIPTAG_VIA(via), - TAG_END()); - TEST_1(ag->ag_orq); - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + SIPTAG_VIA(via), + TAG_END()); + TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); nta_agent_set_params(ag->ag_agent, @@ -1262,6 +1479,7 @@ int test_tports(agent_t *ag) url_t url[1]; sip_payload_t *pl; usize_t size = 16 * 1024; + client_t ctx[1] = {{ ag, "Test 0.7", check_via_with_sctp }}; *url = *ag->ag_aliases->m_url; url->url_user = "alice"; @@ -1275,23 +1493,19 @@ int test_tports(agent_t *ag) TEST_1(pl = test_payload(ag->ag_home, size)); ag->ag_expect_leg = ag->ag_server_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.7"), - SIPTAG_FROM(ag->ag_bob), - SIPTAG_TO(ag->ag_alice), - SIPTAG_CONTACT(ag->ag_m_bob), - SIPTAG_PAYLOAD(pl), - TAG_END()); - TEST_1(ag->ag_orq); - su_free(ag->ag_home, pl); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_bob), + SIPTAG_TO(ag->ag_alice), + SIPTAG_CONTACT(ag->ag_m_bob), + SIPTAG_PAYLOAD(pl), + TAG_END()); + su_free(ag->ag_home, pl); + TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_server_leg); } @@ -1300,6 +1514,7 @@ int test_tports(agent_t *ag) url_t url[1]; sip_payload_t *pl; usize_t size = 128 * 1024; + client_t ctx[1] = {{ ag, "Test 0.8" }}; nta_agent_set_params(ag->ag_agent, NTATAG_MAXSIZE(65536), @@ -1312,23 +1527,19 @@ int test_tports(agent_t *ag) ag->ag_expect_leg = ag->ag_server_leg; ag->ag_latest_leg = NULL; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.8"), - SIPTAG_FROM(ag->ag_bob), - SIPTAG_TO(ag->ag_alice), - SIPTAG_CONTACT(ag->ag_m_bob), - SIPTAG_PAYLOAD(pl), - TAG_END()); - TEST_1(ag->ag_orq); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_bob), + SIPTAG_TO(ag->ag_alice), + SIPTAG_CONTACT(ag->ag_m_bob), + SIPTAG_PAYLOAD(pl), + TAG_END()); su_free(ag->ag_home, pl); - - nta_test_run(ag); - TEST(ag->ag_status, 413); - TEST_P(ag->ag_orq, NULL); + TEST_1(!client_run(ctx, 413)); TEST_P(ag->ag_latest_leg, NULL); nta_agent_set_params(ag->ag_agent, @@ -1339,6 +1550,7 @@ int test_tports(agent_t *ag) /* Test 0.9: Timeout */ { url_t url[1]; + client_t ctx[1] = {{ ag, "Test 0.9" }}; printf("%s: starting MESSAGE timeout test, completing in 4 seconds\n", name); @@ -1357,21 +1569,18 @@ int test_tports(agent_t *ag) ag->ag_expect_leg = ag->ag_server_leg; ag->ag_latest_leg = NULL; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.9"), - SIPTAG_FROM(ag->ag_bob), - SIPTAG_TO(ag->ag_alice), - SIPTAG_CONTACT(ag->ag_m_bob), - TAG_END()); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_bob), + SIPTAG_TO(ag->ag_alice), + SIPTAG_CONTACT(ag->ag_m_bob), + TAG_END()); - TEST_1(ag->ag_orq); - nta_test_run(ag); - TEST(ag->ag_status, 408); - TEST_P(ag->ag_orq, NULL); + TEST_1(!client_run(ctx, 408)); TEST_P(ag->ag_latest_leg, NULL); nta_agent_set_params(ag->ag_agent, @@ -1419,7 +1628,8 @@ int leg_callback_save(agent_t *ag, ag->ag_latest_leg = leg; ag->ag_irq = irq; - ag->ag_status = 1000; + + ag->ag_running = 0; return 0; } @@ -1433,56 +1643,59 @@ int test_destroy_incoming(agent_t *ag) *url = *ag->ag_contact->m_url; - /* Test 3.1 - * Check that when a incoming request is destroyed in callback, - * a 500 response is sent - */ - ag->ag_expect_leg = ag->ag_default_leg; - nta_leg_bind(ag->ag_default_leg, leg_callback_destroy, ag); + { + client_t ctx[1] = {{ ag, "Test 3.1" }}; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, - outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 3.1"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 500); - TEST_P(ag->ag_orq, NULL); - TEST_P(ag->ag_latest_leg, ag->ag_default_leg); + /* Test 3.1 + * Check that when a incoming request is destroyed in callback, + * a 500 response is sent + */ + ag->ag_expect_leg = ag->ag_default_leg; + nta_leg_bind(ag->ag_default_leg, leg_callback_destroy, ag); + + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, + outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + TAG_END()); + TEST_1(!client_run(ctx, 500)); + TEST_P(ag->ag_latest_leg, ag->ag_default_leg); + } - /* Test 3.1 - * Check that when a incoming request is destroyed, a 500 response is sent - */ - nta_leg_bind(ag->ag_default_leg, leg_callback_save, ag); + { + /* Test 3.2 + * Check that when an incoming request is destroyed, a 500 response is sent + */ + client_t ctx[1] = {{ ag, "Test 3.2" }}; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, - outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 3.1"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - TAG_END()); - TEST_1(ag->ag_orq); + nta_leg_bind(ag->ag_default_leg, leg_callback_save, ag); + + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, + outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + TAG_END()); + TEST_1(ctx->c_orq); + nta_test_run(ag); + TEST(ctx->c_status, 0); + TEST_1(ag->ag_irq); + TEST_1(ctx->c_orq); + TEST_P(ag->ag_latest_leg, ag->ag_default_leg); - nta_test_run(ag); - TEST(ag->ag_status, 1000); - TEST_1(ag->ag_irq); - TEST_1(ag->ag_orq); - TEST_P(ag->ag_latest_leg, ag->ag_default_leg); - nta_incoming_destroy(ag->ag_irq), ag->ag_irq = NULL; - nta_test_run(ag); - TEST(ag->ag_status, 500); - TEST_P(ag->ag_orq, NULL); + nta_incoming_destroy(ag->ag_irq), ag->ag_irq = NULL; + + TEST_1(!client_run(ctx, 500)); + } END(); } @@ -1526,22 +1739,19 @@ int test_resolv(agent_t *ag, char const *resolv_conf) /* Test 1.1 * Send a message to sip:example.org */ + client_t ctx[1] = {{ ag, "Test 1.1" }}; ag->ag_expect_leg = ag->ag_default_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 1.1"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + TAG_END()); + TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } @@ -1549,22 +1759,20 @@ int test_resolv(agent_t *ag, char const *resolv_conf) /* Test 1.2 * Send a message to sip:srv.example.org */ + client_t ctx[1] = {{ ag, "Test 1.2" }}; url->url_host = "srv.example.org"; ag->ag_expect_leg = ag->ag_default_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 1.2"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - TAG_END()); - TEST_1(ag->ag_orq); - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + TAG_END()); + TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } @@ -1572,23 +1780,20 @@ int test_resolv(agent_t *ag, char const *resolv_conf) /* Test 1.3 * Send a message to sip:ipv.example.org */ + client_t ctx[1] = {{ ag, "Test 1.3" }}; url->url_host = "ipv.example.org"; ag->ag_expect_leg = ag->ag_default_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 1.3"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + TAG_END()); + TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } @@ -1596,23 +1801,20 @@ int test_resolv(agent_t *ag, char const *resolv_conf) /* Test 1.4.1 * Send a message to sip:down.example.org */ + client_t ctx[1] = {{ ag, "Test 1.4.1" }}; url->url_host = "down.example.org"; ag->ag_expect_leg = ag->ag_default_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 1.4.1"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + TAG_END()); + TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } @@ -1621,23 +1823,20 @@ int test_resolv(agent_t *ag, char const *resolv_conf) /* Test 1.4.2 * Send a message to sip:na503.example.org */ + client_t ctx[1] = {{ ag, "Test 1.4.2" }}; url->url_host = "na503.example.org"; ag->ag_expect_leg = ag->ag_default_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 1.4.2"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 503); - TEST_P(ag->ag_orq, NULL); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + TAG_END()); + TEST_1(!client_run(ctx, 503)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } @@ -1645,23 +1844,20 @@ int test_resolv(agent_t *ag, char const *resolv_conf) /* Test 1.4.3 * Send a message to sip:nona.example.org */ + client_t ctx[1] = {{ ag, "Test 1.4.3" }}; url->url_host = "nona.example.org"; ag->ag_expect_leg = ag->ag_default_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 1.4.3"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + TAG_END()); + TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } @@ -1671,23 +1867,20 @@ int test_resolv(agent_t *ag, char const *resolv_conf) * After failing to find _sip._udp.nosrv.example.org, * second SRV with _sip._udp.srv.example.org succeeds */ + client_t ctx[1] = {{ ag, "Test 1.4.4" }}; url->url_host = "nosrv.example.org"; ag->ag_expect_leg = ag->ag_default_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 1.4.4"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + TAG_END()); + TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } @@ -1696,24 +1889,21 @@ int test_resolv(agent_t *ag, char const *resolv_conf) * Send a message to sip:srv.example.org;transport=tcp * Test outgoing_make_srv_query() */ + client_t ctx[1] = {{ ag, "Test 1.5.1: outgoing_make_srv_query()" }}; url->url_host = "srv.example.org"; url->url_params = "transport=tcp"; ag->ag_expect_leg = ag->ag_default_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 1.5.1: outgoing_make_srv_query()"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + TAG_END()); + TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); url->url_params = NULL; } @@ -1723,24 +1913,22 @@ int test_resolv(agent_t *ag, char const *resolv_conf) * Send a message to sip:srv.example.org;transport=udp * Test outgoing_make_srv_query() */ + client_t ctx[1] = {{ ag, "Test 1.5.2: outgoing_make_srv_query()" }}; + url->url_host = "srv.example.org"; url->url_params = "transport=udp"; ag->ag_expect_leg = ag->ag_default_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 1.5.2: outgoing_make_srv_query()"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + TAG_END()); + TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); url->url_params = NULL; } @@ -1750,24 +1938,22 @@ int test_resolv(agent_t *ag, char const *resolv_conf) * Send a message to sip:srv2.example.org;transport=udp * Test outgoing_query_srv_a() */ + client_t ctx[1] = {{ ag, "Test 1.5: outgoing_query_srv_a()" }}; + url->url_host = "srv2.example.org"; url->url_params = "transport=udp"; ag->ag_expect_leg = ag->ag_default_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 1.5: outgoing_query_srv_a()"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + TAG_END()); + TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); url->url_params = NULL; } @@ -1777,24 +1963,22 @@ int test_resolv(agent_t *ag, char const *resolv_conf) * Send a message to sip:srv.example.org:$port * Test outgoing_make_a_aaaa_query() */ + client_t ctx[1] = {{ ag, "Test 1.6.1: outgoing_make_a_aaaa_query()" }}; + url->url_host = "srv.example.org"; url->url_port = ag->ag_contact->m_url->url_port; ag->ag_expect_leg = ag->ag_default_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 1.6.1: outgoing_make_a_aaaa_query()"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 503); - TEST_P(ag->ag_orq, NULL); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + TAG_END()); + TEST_1(!client_run(ctx, 503)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } @@ -1803,24 +1987,22 @@ int test_resolv(agent_t *ag, char const *resolv_conf) * Send a message to sip:a.example.org:$port * Test outgoing_make_a_aaaa_query() */ + client_t ctx[1] = {{ ag, "Test 1.6.2: outgoing_make_a_aaaa_query()" }}; + url->url_host = "a.example.org"; url->url_port = ag->ag_contact->m_url->url_port; ag->ag_expect_leg = ag->ag_default_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 1.6.2: outgoing_make_a_aaaa_query()"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + TAG_END()); + TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); url->url_port = NULL; } @@ -1831,21 +2013,21 @@ int test_resolv(agent_t *ag, char const *resolv_conf) * Send a message to sip:na.example.org * Test outgoing_query_all() with NAPTR "A" flag */ + client_t ctx[1] = {{ ag, "Test 1.6c" }}; + url->url_host = "na.example.org"; ag->ag_expect_leg = ag->ag_default_leg; - TEST_1(ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 1.6c"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - TAG_END())); - nta_test_run(ag); - TEST(ag->ag_status, 503); - TEST(ag->ag_orq, NULL); + TEST_1(ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + TAG_END())); + TEST_1(!client_run(ctx, 503)); TEST(ag->ag_latest_leg, ag->ag_default_leg); } #endif @@ -1855,382 +2037,26 @@ int test_resolv(agent_t *ag, char const *resolv_conf) * Send a message to sip:down2.example.org:$port * Test A record failover. */ + client_t ctx[1] = {{ ag, "Test 1.7: outgoing_make_a_aaaa_query()" }}; + url->url_host = "down2.example.org"; url->url_port = ag->ag_contact->m_url->url_port; ag->ag_expect_leg = ag->ag_default_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 1.7: outgoing_make_a_aaaa_query()"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + TAG_END()); + TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); url->url_params = NULL; } -#if 0 - /* Test 0.1.1 - * Send a message from Bob to Alice using SIGCOMP and TCP - */ - if (tcp_comp) { - url_t url[1]; - sip_payload_t *pl; - usize_t size = 1024; - - *url = *ag->ag_aliases->m_url; - url->url_user = "alice"; - if (url->url_params) - url->url_params = su_sprintf(NULL, "%s;transport=tcp", url->url_params); - else - url->url_params = "transport=tcp"; - - TEST_1(pl = test_payload(ag->ag_home, size)); - ag->ag_expect_leg = ag->ag_server_leg; - TEST_1(ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.1.1"), - SIPTAG_FROM(ag->ag_bob), - SIPTAG_TO(ag->ag_alice), - SIPTAG_CONTACT(ag->ag_m_bob), - SIPTAG_PAYLOAD(pl), - TAG_END())); - su_free(ag->ag_home, pl); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST(ag->ag_orq, NULL); - TEST(ag->ag_latest_leg, ag->ag_server_leg); - } - - /* Test 0.2 - * Send a message from Bob to Alice - * This time specify a TCP URI, and include a large payload - * of 512 kB - */ - if (tcp) { - url_t url[1]; - sip_payload_t *pl; - usize_t size = 512 * 1024; - - *url = *ag->ag_aliases->m_url; - url->url_user = "alice"; -#if 0 - if (url->url_params) - url->url_params = su_sprintf(NULL, "%s;transport=tcp", url->url_params); - else -#endif - url->url_params = "transport=tcp"; - - - TEST_1(pl = test_payload(ag->ag_home, size)); - - ag->ag_expect_leg = ag->ag_server_leg; - TEST_1(ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.2"), - SIPTAG_FROM(ag->ag_bob), - SIPTAG_TO(ag->ag_alice), - SIPTAG_CONTACT(ag->ag_m_bob), - SIPTAG_PAYLOAD(pl), - TAG_END())); - su_free(ag->ag_home, pl); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST(ag->ag_orq, NULL); - TEST(ag->ag_latest_leg, ag->ag_server_leg); - } - - /* Test 0.3 - * Send a message from Bob to Alice - * This time include a large payload of 512 kB, let NTA choose transport. - */ - if (tcp) { - url_t url[1]; - sip_payload_t *pl; - usize_t size = 512 * 1024; - - *url = *ag->ag_aliases->m_url; - url->url_user = "alice"; - - TEST_1(pl = test_payload(ag->ag_home, size)); - - ag->ag_expect_leg = ag->ag_server_leg; - TEST_1(ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.3"), - SIPTAG_FROM(ag->ag_bob), - SIPTAG_TO(ag->ag_alice), - SIPTAG_CONTACT(ag->ag_m_bob), - SIPTAG_PAYLOAD(pl), - TAG_END())); - su_free(ag->ag_home, pl); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST(ag->ag_orq, NULL); - TEST(ag->ag_latest_leg, ag->ag_server_leg); - } - - /* Test 0.4: - * Send a message from Bob to Alice - * This time include a payload of 2 kB, let NTA choose transport. - */ - { - url_t url[1]; - sip_payload_t *pl; - usize_t size = 2 * 1024; - - *url = *ag->ag_aliases->m_url; - url->url_user = "alice"; - - TEST_1(pl = test_payload(ag->ag_home, size)); - - su_free(ag->ag_home, (void *)ag->ag_out_via), ag->ag_out_via = NULL; - - ag->ag_expect_leg = ag->ag_server_leg; - TEST_1(ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.4"), - SIPTAG_FROM(ag->ag_bob), - SIPTAG_TO(ag->ag_alice), - SIPTAG_CONTACT(ag->ag_m_bob), - SIPTAG_PAYLOAD(pl), - TAG_END())); - su_free(ag->ag_home, pl); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST(ag->ag_orq, NULL); - TEST(ag->ag_latest_leg, ag->ag_server_leg); - TEST_1(ag->ag_out_via); - TEST_1(strcasecmp(ag->ag_out_via->v_protocol, "SIP/2.0/TCP") == 0 || - strcasecmp(ag->ag_out_via->v_protocol, "SIP/2.0/SCTP") == 0); - } - - /* Test 0.5: - * Send a message from Bob to Alice - * This time include a payload of 2 kB, try to use UDP. - */ - if (udp) { - url_t url[1]; - sip_payload_t *pl; - usize_t size = 2 * 1024; - - *url = *ag->ag_aliases->m_url; - url->url_user = "alice"; - - TEST_1(pl = test_payload(ag->ag_home, size)); - - su_free(ag->ag_home, (void *)ag->ag_out_via), ag->ag_out_via = NULL; - - ag->ag_expect_leg = ag->ag_server_leg; - TEST_1(ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.5"), - SIPTAG_FROM(ag->ag_bob), - SIPTAG_TO(ag->ag_alice), - SIPTAG_CONTACT(ag->ag_m_bob), - SIPTAG_PAYLOAD(pl), - TPTAG_MTU(0xffffffff), - TAG_END())); - su_free(ag->ag_home, pl); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST(ag->ag_orq, NULL); - TEST(ag->ag_latest_leg, ag->ag_server_leg); - TEST_1(ag->ag_out_via); - TEST_S(ag->ag_out_via->v_protocol, "SIP/2.0/UDP"); - } - - if (udp) { - /* Send a message from default leg to server leg - * using a prefilled Via header - */ - sip_via_t via[1]; - - sip_via_init(via); - - via->v_protocol = sip_transport_udp; - - via->v_host = ag->ag_contact->m_url->url_host; - via->v_port = ag->ag_contact->m_url->url_port; - - sip_via_add_param(ag->ag_home, via, "branch=MagicalBranch"); - - nta_agent_set_params(ag->ag_agent, - NTATAG_USER_VIA(1), - TAG_END()); - - ag->ag_expect_leg = ag->ag_server_leg; - TEST_1(ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, - magic_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.6"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - SIPTAG_VIA(via), - TAG_END())); - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST(ag->ag_orq, NULL); - TEST(ag->ag_latest_leg, ag->ag_server_leg); - - nta_agent_set_params(ag->ag_agent, - NTATAG_USER_VIA(0), - TAG_END()); - } - - /* Test 0.7 - * Send a message from Bob to Alice using SCTP - */ - if (sctp) { - url_t url[1]; - sip_payload_t *pl; - usize_t size = 16 * 1024; - - *url = *ag->ag_aliases->m_url; - url->url_user = "alice"; -#if 0 - if (url->url_params) - url->url_params = su_sprintf(NULL, "%s;transport=sctp", url->url_params); - else -#endif - url->url_params = "transport=sctp"; - - TEST_1(pl = test_payload(ag->ag_home, size)); - - ag->ag_expect_leg = ag->ag_server_leg; - TEST_1(ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.7"), - SIPTAG_FROM(ag->ag_bob), - SIPTAG_TO(ag->ag_alice), - SIPTAG_CONTACT(ag->ag_m_bob), - SIPTAG_PAYLOAD(pl), - TAG_END())); - su_free(ag->ag_home, pl); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST(ag->ag_orq, NULL); - TEST(ag->ag_latest_leg, ag->ag_server_leg); - } - - /* Test 0.8: Send a too large message */ - if (tcp) { - url_t url[1]; - sip_payload_t *pl; - usize_t size = 128 * 1024; - - nta_agent_set_params(ag->ag_agent, - NTATAG_MAXSIZE(65536), - TAG_END()); - - *url = *ag->ag_aliases->m_url; - url->url_user = "alice"; - - TEST_1(pl = test_payload(ag->ag_home, size)); - - ag->ag_expect_leg = ag->ag_server_leg; - ag->ag_latest_leg = NULL; - TEST_1(ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.8"), - SIPTAG_FROM(ag->ag_bob), - SIPTAG_TO(ag->ag_alice), - SIPTAG_CONTACT(ag->ag_m_bob), - SIPTAG_PAYLOAD(pl), - TAG_END())); - su_free(ag->ag_home, pl); - - nta_test_run(ag); - TEST(ag->ag_status, 413); - TEST(ag->ag_orq, NULL); - TEST(ag->ag_latest_leg, NULL); - - nta_agent_set_params(ag->ag_agent, - NTATAG_MAXSIZE(2 * 1024 * 1024), - TAG_END()); - } - - /* Test 0.9: Timeout */ - { - url_t url[1]; - - printf("%s: starting MESSAGE timeout test, test will complete in 4 seconds\n", - name); - - nta_agent_set_params(ag->ag_agent, - NTATAG_TIMEOUT_408(1), - NTATAG_SIP_T1(25), - NTATAG_SIP_T1X64(64 * 25), - TAG_END()); - - *url = *ag->ag_aliases->m_url; - url->url_user = "timeout"; - url->url_port = ag->ag_sink_port; - - ag->ag_expect_leg = ag->ag_server_leg; - ag->ag_latest_leg = NULL; - TEST_1(ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 0.9"), - SIPTAG_FROM(ag->ag_bob), - SIPTAG_TO(ag->ag_alice), - SIPTAG_CONTACT(ag->ag_m_bob), - TAG_END())); - - nta_test_run(ag); - TEST(ag->ag_status, 408); - TEST(ag->ag_orq, NULL); - TEST(ag->ag_latest_leg, NULL); - - nta_agent_set_params(ag->ag_agent, - NTATAG_SIP_T1(500), - NTATAG_SIP_T1X64(64 * 500), - TAG_END()); - } -#endif - nta_agent_set_params(ag->ag_agent, NTATAG_SIP_T1(500), NTATAG_SIP_T1X64(64 * 500), @@ -2266,26 +2092,23 @@ int test_routing(agent_t *ag) * our own port number. */ url_t url2[1]; + client_t ctx[1] = {{ ag, "Test 1.2" }}; *url2 = *url; url2->url_port = "9"; /* discard service */ ag->ag_expect_leg = ag->ag_default_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - (url_string_t *)url, - SIP_METHOD_MESSAGE, - (url_string_t *)url2, - SIPTAG_SUBJECT_STR("Test 1.2"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + (url_string_t *)url, + SIP_METHOD_MESSAGE, + (url_string_t *)url2, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + TAG_END()); + TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_default_leg); } @@ -2304,88 +2127,87 @@ int test_dialog(agent_t *ag) * Alice sends a message to Bob, then Bob back to the Alice, and again * Alice to Bob. */ + ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, - leg_callback_200, - ag, - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - TAG_END()); + leg_callback_200, + ag, + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + TAG_END()); TEST_1(ag->ag_alice_leg); TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL)); - nta_leg_bind(ag->ag_server_leg, new_leg_callback_200, ag); - /* Send message from Alice to Bob establishing the dialog */ - ag->ag_expect_leg = ag->ag_server_leg; - ag->ag_tag_remote = ag->ag_alice_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_alice_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_MESSAGE, - (url_string_t *)ag->ag_m_bob->m_url, - SIPTAG_SUBJECT_STR("Test 2.1"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); - TEST_P(ag->ag_latest_leg, ag->ag_server_leg); - TEST_1(ag->ag_bob_leg != NULL); - - nta_leg_bind(ag->ag_server_leg, leg_callback_200, ag); - - /* Send message from Bob to Alice */ - ag->ag_expect_leg = ag->ag_alice_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ag, - NULL, - SIP_METHOD_MESSAGE, - (url_string_t *)ag->ag_m_alice->m_url, - SIPTAG_SUBJECT_STR("Test 2.2"), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); - TEST_P(ag->ag_latest_leg, ag->ag_alice_leg); - - /* Send again message from Alice to Bob */ - ag->ag_expect_leg = ag->ag_bob_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_alice_leg, outgoing_callback, ag, - NULL, - SIP_METHOD_MESSAGE, - (url_string_t *)ag->ag_m_bob->m_url, - SIPTAG_SUBJECT_STR("Test 2.3"), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); - TEST_P(ag->ag_latest_leg, ag->ag_bob_leg); - - /* Send message from Bob to Alice - * This time, however, specify request URI - */ { - ag->ag_expect_leg = ag->ag_alice_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ag, - NULL, - SIP_METHOD_MESSAGE, - (url_string_t *)ag->ag_m_alice->m_url, - SIPTAG_SUBJECT_STR("Test 2.4"), - TAG_END()); - TEST_1(ag->ag_orq); + client_t ctx[1] = {{ ag, "Test 2.1" }}; - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); + nta_leg_bind(ag->ag_server_leg, new_leg_callback_200, ag); + + /* Send message from Alice to Bob establishing the dialog */ + ag->ag_expect_leg = ag->ag_server_leg; + ag->ag_tag_remote = ag->ag_alice_leg; + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_alice_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_MESSAGE, + (url_string_t *)ag->ag_m_bob->m_url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + TAG_END()); + TEST_1(!client_run(ctx, 200)); + TEST_P(ag->ag_latest_leg, ag->ag_server_leg); + TEST_1(ag->ag_bob_leg != NULL); + } + + { + /* Send message from Bob to Alice */ + client_t ctx[1] = {{ ag, "Test 2.2" }}; + + nta_leg_bind(ag->ag_server_leg, leg_callback_200, ag); + + + ag->ag_expect_leg = ag->ag_alice_leg; + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ctx, + NULL, + SIP_METHOD_MESSAGE, + (url_string_t *)ag->ag_m_alice->m_url, + SIPTAG_SUBJECT_STR(ctx->c_name), + TAG_END()); + TEST_1(!client_run(ctx, 200)); + TEST_P(ag->ag_latest_leg, ag->ag_alice_leg); + } + + { + /* Send again message from Alice to Bob */ + client_t ctx[1] = {{ ag, "Test 2.3" }}; + ag->ag_expect_leg = ag->ag_bob_leg; + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_alice_leg, outgoing_callback, ctx, + NULL, + SIP_METHOD_MESSAGE, + (url_string_t *)ag->ag_m_bob->m_url, + SIPTAG_SUBJECT_STR(ctx->c_name), + TAG_END()); + TEST_1(!client_run(ctx, 200)); + TEST_P(ag->ag_latest_leg, ag->ag_bob_leg); + } + + { + /* Send message from Bob to Alice + * This time, however, specify request URI + */ + client_t ctx[1] = {{ ag, "Test 2.4" }}; + ag->ag_expect_leg = ag->ag_alice_leg; + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ctx, + NULL, + SIP_METHOD_MESSAGE, + (url_string_t *)ag->ag_m_alice->m_url, + SIPTAG_SUBJECT_STR(ctx->c_name), + TAG_END()); + TEST_1(!client_run(ctx, 200)); TEST_P(ag->ag_latest_leg, ag->ag_alice_leg); } @@ -2415,7 +2237,7 @@ int test_for_ack(agent_t *ag, TEST(method, sip_method_ack); - ag->ag_status = 200; + ag->ag_running = 0; END(); } @@ -2506,7 +2328,7 @@ int alice_leg_callback(agent_t *ag, leg_zap(ag, leg); } if (sip) - return 200; + return 200; END(); } @@ -2561,7 +2383,7 @@ int bob_leg_callback(agent_t *ag, if (sip->sip_request->rq_method != sip_method_invite) { return 200; } else { - nta_incoming_bind(irq, test_for_ack, ag); + nta_incoming_bind(irq, test_for_ack, ag); #if 1 nta_incoming_treply(irq, SIP_180_RINGING, @@ -2584,129 +2406,191 @@ int bob_leg_callback(agent_t *ag, END(); } -int outgoing_invite_callback(agent_t *ag, - nta_outgoing_t *orq, - sip_t const *sip) +struct invite_client_t { + client_t ic_client[1]; + nta_outgoing_t *ic_orq; /* Original INVITE transaction */ + int ic_tag_status; /* Status for current branch */ + char *ic_tag; +}; + +static +int invite_client_deinit(client_t *c) { - BEGIN(); + agent_t *ag = c->c_ag; + invite_client_t *ic = (invite_client_t *)c; - int status = sip->sip_status->st_status; + if (ic->ic_orq) nta_outgoing_destroy(ic->ic_orq), ic->ic_orq = NULL; + if (ic->ic_tag) su_free(ag->ag_home, ic->ic_tag), ic->ic_tag = NULL; - if (tstflags & tst_verbatim) { - printf("%s: %s: %s %03d %s\n", name, __func__, - sip->sip_status->st_version, - sip->sip_status->st_status, - sip->sip_status->st_phrase); - } + return 0; +} - { - msg_t *msg; +static +int check_prack_sending(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) +{ + agent_t *ag = ctx->c_ag; + int status = ctx->c_status; - TEST_1(msg = nta_outgoing_getresponse(orq)); - TEST_1(msg->m_refs == 2); - TEST_1(sip_object(msg) == sip); - if (ag->ag_probe_msg == NULL) - ag->ag_probe_msg = msg; - msg_destroy(msg); - } - - if (status < 200) { + if (100 < status && status < 200) { if (sip->sip_require && sip_has_feature(sip->sip_require, "100rel")) { + nta_outgoing_t *prack = NULL; + TEST_1(sip->sip_rseq); - orq = nta_outgoing_prack(ag->ag_call_leg, orq, NULL, NULL, - NULL, - sip, - TAG_END()); - TEST_1(orq); - nta_outgoing_destroy(orq); + + prack = nta_outgoing_prack(ag->ag_call_leg, orq, NULL, NULL, + NULL, + sip, + TAG_END()); + nta_outgoing_destroy(prack); + TEST_1(prack != NULL); } - return 0; } + return 0; +} - if (status < 300) { - nta_outgoing_t *ack; +static +int check_leg_tagging(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) +{ + agent_t *ag = ctx->c_ag; + int status = ctx->c_status; + + if (200 <= status && status < 300) { TEST_1(nta_leg_rtag(ag->ag_call_leg, sip->sip_to->a_tag)); TEST(nta_leg_client_route(ag->ag_call_leg, sip->sip_record_route, sip->sip_contact), 0); + } + return 0; +} + + +static +int check_tu_ack(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) +{ + agent_t *ag = ctx->c_ag; + int status = ctx->c_status; + + if (200 <= status && status < 300) { + nta_outgoing_t *ack; ack = nta_outgoing_tcreate(ag->ag_call_leg, NULL, NULL, NULL, SIP_METHOD_ACK, NULL, SIPTAG_CSEQ(sip->sip_cseq), TAG_END()); - TEST_1(ack); nta_outgoing_destroy(ack); - } - else { - ag->ag_status = status; + TEST_1(ack); } - TEST_1(sip->sip_to && sip->sip_to->a_tag); - - nta_outgoing_destroy(orq); - ag->ag_orq = NULL; - ag->ag_call_leg = NULL; - END(); + return 0; } +static +int check_final_error(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) +{ + agent_t *ag = ctx->c_ag; + int status = ctx->c_status; + + if (status >= 300) + ag->ag_call_leg = NULL; + + return 0; +} + + +/** Cancel call after receiving 1XX response */ +static +int cancel_invite(client_t *ctx, nta_outgoing_t *orq, sip_t const *sip) +{ + int status = ctx->c_status; + + if (100 < status && status < 200) { + nta_outgoing_cancel(orq); + ctx->c_status = 0; + } + else if (status >= 200) { + TEST_1(status == 487 || status == 504); + } + + return 0; +} + +static client_check_f * const checks_for_invite[] = { + client_check_to_tag, + check_leg_tagging, + check_tu_ack, + check_final_error, + NULL, +}; + +static client_check_f * const checks_for_reinvite[] = { + client_check_to_tag, + check_prack_sending, + check_leg_tagging, + check_tu_ack, + NULL, +}; + int test_call(agent_t *ag) { - sip_content_type_t *c = ag->ag_content_type; + sip_content_type_t *ct = ag->ag_content_type; sip_payload_t *sdp = ag->ag_payload; nta_leg_t *old_leg; sip_replaces_t *r1, *r2; BEGIN(); - /* - * Test establishing a call - * - * Alice sends a INVITE to Bob, then Bob sends 200 Ok. - */ - ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, - alice_leg_callback, - ag, - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - TAG_END()); - TEST_1(ag->ag_alice_leg); - - TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL)); - nta_leg_bind(ag->ag_server_leg, bob_leg_callback, ag); - - /* Send INVITE */ - ag->ag_expect_leg = ag->ag_server_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, - outgoing_invite_callback, ag, - ag->ag_obp, - SIP_METHOD_INVITE, - (url_string_t *)ag->ag_m_bob->m_url, - SIPTAG_SUBJECT_STR("Call 1"), - SIPTAG_CONTACT(ag->ag_m_alice), - SIPTAG_CONTENT_TYPE(c), - SIPTAG_ACCEPT_CONTACT_STR("*;audio"), - SIPTAG_PAYLOAD(sdp), - NTATAG_USE_TIMESTAMP(1), - NTATAG_PASS_100(1), - TAG_END()); - TEST_1(ag->ag_orq); - - /* Try to CANCEL it immediately */ - TEST_1(nta_outgoing_cancel(ag->ag_orq) == 0); - /* As Bob immediately answers INVITE with 200 Ok, - cancel should be answered with 487. */ + { + invite_client_t ic[1] = {{ + {{ ag, "Call 1", NULL, checks_for_invite, invite_client_deinit }} }}; + client_t *ctx = ic->ic_client; - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); - TEST_P(ag->ag_latest_leg, ag->ag_server_leg); - TEST_1(ag->ag_bob_leg != NULL); + /* + * Test establishing a call + * + * Alice sends a INVITE to Bob, then Bob sends 200 Ok. + */ + ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, + alice_leg_callback, + ag, + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + TAG_END()); + TEST_1(ag->ag_alice_leg); + + TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL)); + nta_leg_bind(ag->ag_server_leg, bob_leg_callback, ag); + + /* Send INVITE */ + ag->ag_expect_leg = ag->ag_server_leg; + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, + outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_INVITE, + (url_string_t *)ag->ag_m_bob->m_url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_CONTACT(ag->ag_m_alice), + SIPTAG_CONTENT_TYPE(ct), + SIPTAG_ACCEPT_CONTACT_STR("*;audio"), + SIPTAG_PAYLOAD(sdp), + NTATAG_USE_TIMESTAMP(1), + NTATAG_PASS_100(1), + TAG_END()); + TEST_1(ctx->c_orq); + /* Try to CANCEL it immediately */ + TEST_1(nta_outgoing_cancel(ctx->c_orq) == 0); + /* As Bob immediately answers INVITE with 200 Ok, + cancel should be answered with 481 and 200 Ok is teruned to INVITE. */ + TEST_1(!client_run(ctx, 200)); + + TEST_P(ag->ag_latest_leg, ag->ag_server_leg); + TEST_1(ag->ag_bob_leg != NULL); + } TEST_1(r1 = nta_leg_make_replaces(ag->ag_alice_leg, ag->ag_home, 0)); TEST_1(r2 = sip_replaces_format(ag->ag_home, "%s;from-tag=%s;to-tag=%s", @@ -2715,55 +2599,59 @@ int test_call(agent_t *ag) TEST_P(ag->ag_alice_leg, nta_leg_by_replaces(ag->ag_agent, r2)); TEST_P(ag->ag_bob_leg, nta_leg_by_replaces(ag->ag_agent, r1)); - /* Re-INVITE from Bob to Alice. - * - * Alice first sends 183, waits for PRACK, then sends 184 and 185, - * waits for PRACKs, then sends 200, waits for ACK. - */ - ag->ag_expect_leg = ag->ag_alice_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_bob_leg, - outgoing_invite_callback, ag, - NULL, - SIP_METHOD_INVITE, - NULL, - SIPTAG_SUBJECT_STR("Re-INVITE"), - SIPTAG_CONTACT(ag->ag_m_bob), - SIPTAG_SUPPORTED_STR("foo"), - SIPTAG_CONTENT_TYPE(c), - SIPTAG_PAYLOAD(sdp), - TAG_END()); - TEST_1(ag->ag_orq); - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); - TEST_P(ag->ag_latest_leg, ag->ag_alice_leg); + { + invite_client_t ic[1] = {{ + {{ ag, "Re-INVITE in Call 1", NULL, checks_for_reinvite, invite_client_deinit }} + }}; + client_t *ctx = ic->ic_client; - nta_agent_set_params(ag->ag_agent, - NTATAG_DEBUG_DROP_PROB(0), - TAG_END()); + /* Re-INVITE from Bob to Alice. + * + * Alice first sends 183, waits for PRACK, then sends 184 and 185, + * waits for PRACKs, then sends 200, waits for ACK. + */ + ag->ag_expect_leg = ag->ag_alice_leg; + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_bob_leg, + outgoing_callback, ctx, + NULL, + SIP_METHOD_INVITE, + NULL, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_CONTACT(ag->ag_m_bob), + SIPTAG_SUPPORTED_STR("foo"), + SIPTAG_CONTENT_TYPE(ct), + SIPTAG_PAYLOAD(sdp), + TAG_END()); + TEST_1(!client_run(ctx, 200)); + TEST_P(ag->ag_latest_leg, ag->ag_alice_leg); + } - /* Send BYE from Bob to Alice */ - old_leg = ag->ag_expect_leg = ag->ag_alice_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ag, - NULL, - SIP_METHOD_BYE, - NULL, - SIPTAG_SUBJECT_STR("Hangup"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - SIPTAG_CONTENT_TYPE(c), - SIPTAG_PAYLOAD(sdp), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); - TEST_P(ag->ag_latest_leg, old_leg); - TEST_P(ag->ag_alice_leg, NULL); + { + client_t ctx[1] = {{ ag, "Hangup" }}; + + nta_agent_set_params(ag->ag_agent, + NTATAG_DEBUG_DROP_PROB(0), + TAG_END()); + + /* Send BYE from Bob to Alice */ + old_leg = ag->ag_expect_leg = ag->ag_alice_leg; + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ctx, + NULL, + SIP_METHOD_BYE, + NULL, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + SIPTAG_CONTENT_TYPE(ct), + SIPTAG_PAYLOAD(sdp), + TAG_END()); + TEST_1(!client_run(ctx, 200)); + TEST_P(ag->ag_latest_leg, old_leg); + TEST_P(ag->ag_alice_leg, NULL); + } nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL; ag->ag_latest_leg = NULL; @@ -2850,121 +2738,88 @@ int bob_leg_callback2(agent_t *ag, if (sip->sip_request->rq_method != sip_method_invite) { return 200; - } else { - nta_incoming_bind(irq, test_for_ack_or_timeout, ag); - nta_incoming_treply(irq, - SIP_183_SESSION_PROGRESS, - SIPTAG_CONTENT_TYPE(ag->ag_content_type), - SIPTAG_PAYLOAD(ag->ag_payload), - SIPTAG_CONTACT(ag->ag_m_bob), - TAG_END()); - if (0) + } + + nta_incoming_bind(irq, test_for_ack_or_timeout, ag); + nta_incoming_treply(irq, + SIP_183_SESSION_PROGRESS, + SIPTAG_CONTENT_TYPE(ag->ag_content_type), + SIPTAG_PAYLOAD(ag->ag_payload), + SIPTAG_CONTACT(ag->ag_m_bob), + TAG_END()); + if (0) nta_incoming_treply(irq, SIP_180_RINGING, SIPTAG_CONTENT_TYPE(ag->ag_content_type), SIPTAG_PAYLOAD(ag->ag_payload), SIPTAG_CONTACT(ag->ag_m_bob), TAG_END()); - nta_incoming_treply(irq, - SIP_200_OK, - SIPTAG_CONTACT(ag->ag_m_bob), - TAG_END()); - ag->ag_irq = irq; - } + nta_incoming_treply(irq, + SIP_200_OK, + SIPTAG_CONTACT(ag->ag_m_bob), + TAG_END()); + ag->ag_irq = irq; END(); } +/** Fork the original INVITE. */ +static +int check_orq_tagging(client_t *ctx, + nta_outgoing_t *orq, + sip_t const *sip) +{ + agent_t *ag = ctx->c_ag; + int status = ctx->c_status; + invite_client_t *ic = (invite_client_t *)ctx; -int invite_prack_callback(agent_t *ag, - nta_outgoing_t *orq, - sip_t const *sip) -{ - BEGIN(); - - int status = sip->sip_status->st_status; - - if (tstflags & tst_verbatim) { - printf("%s: %s: %s %03d %s\n", name, __func__, - sip->sip_status->st_version, - sip->sip_status->st_status, - sip->sip_status->st_phrase); - } - - if (!ag->ag_call_tag && (status >= 200 || (status > 100 && sip->sip_rseq))) { - nta_outgoing_t *tagged; + if (100 < status && status < 200) { + TEST_1(sip->sip_rseq); TEST_1(sip->sip_to->a_tag); - ag->ag_tag_status = status; - ag->ag_call_tag = su_strdup(ag->ag_home, sip->sip_to->a_tag); - TEST_S(ag->ag_call_tag, sip->sip_to->a_tag); - TEST_S(nta_leg_rtag(ag->ag_call_leg, ag->ag_call_tag), ag->ag_call_tag); - TEST(nta_leg_client_route(ag->ag_call_leg, - sip->sip_record_route, - sip->sip_contact), 0); - tagged = nta_outgoing_tagged(orq, - invite_prack_callback, - ag, - ag->ag_call_tag, - sip->sip_rseq); - TEST_1(tagged); - nta_outgoing_destroy(orq); - if (ag->ag_orq == orq) - ag->ag_orq = tagged; - orq = tagged; - } - if (status > ag->ag_status) - ag->ag_status = status; - - if (status > 100 && status < 200 && sip->sip_rseq) { - nta_outgoing_t *prack; - prack = nta_outgoing_prack(ag->ag_call_leg, orq, NULL, NULL, - NULL, - sip, - TAG_END()); - TEST_1(prack); - nta_outgoing_destroy(prack); - return 0; - } - - if (status < 200) - return 0; - - if (status < 300) { - nta_outgoing_t *ack; - msg_t *msg; - sip_t *osip; - - TEST_1(msg = nta_outgoing_getrequest(orq)); - TEST_1(osip = sip_object(msg)); - - TEST_1(nta_leg_rtag(ag->ag_call_leg, sip->sip_to->a_tag)); + TEST_1(orq == ctx->c_orq); + + TEST_1(ic); TEST_1(ic->ic_orq == NULL); + TEST_1(ic->ic_tag == NULL); + + ic->ic_orq = orq; + ic->ic_tag = su_strdup(ag->ag_home, sip->sip_to->a_tag); TEST_1(ic->ic_tag); + ic->ic_tag_status = status; + TEST_S(nta_leg_rtag(ag->ag_call_leg, ic->ic_tag), ic->ic_tag); + TEST(nta_leg_client_route(ag->ag_call_leg, sip->sip_record_route, sip->sip_contact), 0); + + orq = nta_outgoing_tagged(orq, + outgoing_callback, + ctx, + ic->ic_tag, + sip->sip_rseq); + TEST_1(orq); + nta_outgoing_destroy(ctx->c_orq); + ctx->c_orq = orq; - ack = nta_outgoing_tcreate(ag->ag_call_leg, NULL, NULL, - NULL, - SIP_METHOD_ACK, - NULL, - SIPTAG_CSEQ(sip->sip_cseq), - NTATAG_ACK_BRANCH(osip->sip_via->v_branch), - TAG_END()); - TEST_1(ack); - nta_outgoing_destroy(ack); - msg_destroy(msg); + TEST_1(ctx->c_checks && ctx->c_checks[0] == check_orq_tagging); + + ctx->c_checks++; } - TEST_1(sip->sip_to && sip->sip_to->a_tag); - - nta_outgoing_destroy(orq); - ag->ag_orq = NULL; - ag->ag_call_leg = NULL; - - END(); + return 0; } +static client_check_f * const checks_for_100rel[] = { + check_orq_tagging, + client_check_to_tag, + check_prack_sending, + check_leg_tagging, + check_tu_ack, + NULL, +}; + + + static int process_prack(nta_reliable_magic_t *arg, nta_reliable_t *rel, nta_incoming_t *irq, @@ -3049,67 +2904,6 @@ int bob_leg_callback3(agent_t *ag, } -int invite_183_cancel_callback(agent_t *ag, - nta_outgoing_t *orq, - sip_t const *sip) -{ - BEGIN(); - - int status = sip->sip_status->st_status; - - if (tstflags & tst_verbatim) { - printf("%s: %s: %s %03d %s\n", name, __func__, - sip->sip_status->st_version, - sip->sip_status->st_status, - sip->sip_status->st_phrase); - } - - if (status > 100 && status < 200) { - nta_outgoing_cancel(orq); - return 0; - } - - if (status < 200) - return 0; - - if (status < 300) { - nta_outgoing_t *ack; - msg_t *msg; - sip_t *osip; - - TEST_1(msg = nta_outgoing_getrequest(orq)); - TEST_1(osip = sip_object(msg)); - - TEST_1(nta_leg_rtag(ag->ag_call_leg, sip->sip_to->a_tag)); - - TEST(nta_leg_client_route(ag->ag_call_leg, - sip->sip_record_route, - sip->sip_contact), 0); - - ack = nta_outgoing_tcreate(ag->ag_call_leg, NULL, NULL, - NULL, - SIP_METHOD_ACK, - NULL, - SIPTAG_CSEQ(sip->sip_cseq), - NTATAG_ACK_BRANCH(osip->sip_via->v_branch), - TAG_END()); - TEST_1(ack); - nta_outgoing_destroy(ack); - msg_destroy(msg); - } - else { - ag->ag_status = status; - } - - TEST_1(sip->sip_to && sip->sip_to->a_tag); - - nta_outgoing_destroy(orq); - ag->ag_orq = NULL; - ag->ag_call_leg = NULL; - - END(); -} - /* * Test establishing a call with an early dialog / 100 rel / timeout * @@ -3120,133 +2914,134 @@ int invite_183_cancel_callback(agent_t *ag, int test_prack(agent_t *ag) { - sip_content_type_t *c = ag->ag_content_type; + BEGIN(); + + sip_content_type_t *ct = ag->ag_content_type; sip_payload_t *sdp = ag->ag_payload; nta_leg_t *old_leg; - BEGIN(); - { /* Send a PRACK from default leg, NTA responds to it with error */ url_t url[1]; + client_t ctx[1] = {{ ag, "Test 1.1" }}; *url = *ag->ag_aliases->m_url; url->url_user = "bob"; ag->ag_expect_leg = ag->ag_server_leg; ag->ag_latest_leg = NULL; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_PRACK, - (url_string_t *)url, - SIPTAG_SUBJECT_STR("Test 1.1"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - SIPTAG_RACK_STR("1432432 42332432 INVITE"), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 481); - TEST_P(ag->ag_orq, NULL); + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_PRACK, + (url_string_t *)url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + SIPTAG_RACK_STR("1432432 42332432 INVITE"), + TAG_END()); + TEST_1(!client_run(ctx, 481)); TEST_P(ag->ag_latest_leg, NULL); } ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, - alice_leg_callback, - ag, - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - TAG_END()); + alice_leg_callback, + ag, + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + TAG_END()); TEST_1(ag->ag_alice_leg); TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL)); /* Send INVITE */ - nta_leg_bind(ag->ag_server_leg, bob_leg_callback2, ag); - ag->ag_expect_leg = ag->ag_server_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, - invite_prack_callback, ag, - ag->ag_obp, - SIP_METHOD_INVITE, - (url_string_t *)ag->ag_m_bob->m_url, - SIPTAG_SUBJECT_STR("Call 2"), - SIPTAG_CONTACT(ag->ag_m_alice), - SIPTAG_REQUIRE_STR("100rel"), - SIPTAG_CONTENT_TYPE(c), - SIPTAG_PAYLOAD(sdp), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run_until_acked(ag); - TEST(ag->ag_status, 200); - /*TEST(ag->ag_tag_status, 183);*/ - TEST_P(ag->ag_orq, NULL); - TEST_P(ag->ag_latest_leg, ag->ag_server_leg); - TEST_1(ag->ag_bob_leg != NULL); + { + invite_client_t ic[1] = {{ {{ ag, "Call 2", NULL, checks_for_100rel, invite_client_deinit }} }}; + client_t *ctx = ic->ic_client; - /* Send BYE from Bob to Alice */ - old_leg = ag->ag_expect_leg = ag->ag_alice_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ag, - NULL, - SIP_METHOD_BYE, - NULL, - SIPTAG_SUBJECT_STR("Hangup"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - SIPTAG_CONTENT_TYPE(c), - SIPTAG_PAYLOAD(sdp), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); - TEST_P(ag->ag_latest_leg, old_leg); - TEST_P(ag->ag_alice_leg, NULL); + nta_leg_bind(ag->ag_server_leg, bob_leg_callback2, ag); + ag->ag_expect_leg = ag->ag_server_leg; + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, + outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_INVITE, + (url_string_t *)ag->ag_m_bob->m_url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_CONTACT(ag->ag_m_alice), + SIPTAG_REQUIRE_STR("100rel"), + SIPTAG_CONTENT_TYPE(ct), + SIPTAG_PAYLOAD(sdp), + TAG_END()); + + TEST_1(!client_run_until_acked(ctx, 200)); + + /*TEST(ic->ic_tag_status, 183); */ + + TEST_P(ag->ag_latest_leg, ag->ag_server_leg); + TEST_1(ag->ag_bob_leg != NULL); + } + + { + client_t ctx[1] = {{ ag, "Hangup" }}; + + /* Send BYE from Bob to Alice */ + old_leg = ag->ag_expect_leg = ag->ag_alice_leg; + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ctx, + NULL, + SIP_METHOD_BYE, + NULL, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + SIPTAG_CONTENT_TYPE(ct), + SIPTAG_PAYLOAD(sdp), + TAG_END()); + TEST_1(!client_run(ctx, 200)); + TEST_P(ag->ag_latest_leg, old_leg); + TEST_P(ag->ag_alice_leg, NULL); + } nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL; ag->ag_latest_leg = NULL; ag->ag_call_leg = NULL; - if (ag->ag_call_tag) - su_free(ag->ag_home, (void *)ag->ag_call_tag), ag->ag_call_tag = NULL; - /* Test CANCELing a call after received PRACK */ + /* Test CANCELing a call after receiving 100rel response */ ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, - alice_leg_callback, - ag, - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - TAG_END()); + alice_leg_callback, + ag, + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + TAG_END()); TEST_1(ag->ag_alice_leg); TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL)); - /* Send INVITE */ - nta_leg_bind(ag->ag_server_leg, bob_leg_callback3, ag); - ag->ag_expect_leg = ag->ag_server_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, - invite_183_cancel_callback, ag, - ag->ag_obp, - SIP_METHOD_INVITE, - (url_string_t *)ag->ag_m_bob->m_url, - SIPTAG_SUBJECT_STR("Call 2b"), - SIPTAG_CONTACT(ag->ag_m_alice), - SIPTAG_REQUIRE_STR("100rel"), - SIPTAG_CONTENT_TYPE(c), - SIPTAG_PAYLOAD(sdp), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST_1(ag->ag_status == 487 || ag->ag_status == 504); - TEST_P(ag->ag_orq, NULL); + { + invite_client_t ic[1] = {{ {{ ag, "Call 2b", cancel_invite, checks_for_invite, invite_client_deinit }} }}; + client_t *ctx = ic->ic_client; + + /* Send INVITE */ + nta_leg_bind(ag->ag_server_leg, bob_leg_callback3, ag); + ag->ag_expect_leg = ag->ag_server_leg; + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, + outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_INVITE, + (url_string_t *)ag->ag_m_bob->m_url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_CONTACT(ag->ag_m_alice), + SIPTAG_REQUIRE_STR("100rel"), + SIPTAG_CONTENT_TYPE(ct), + SIPTAG_PAYLOAD(sdp), + TAG_END()); + TEST_1(!client_run(ctx, 0)); + } + TEST_P(ag->ag_latest_leg, ag->ag_server_leg); TEST_1(ag->ag_bob_leg != NULL); @@ -3255,109 +3050,122 @@ int test_prack(agent_t *ag) ag->ag_call_leg = NULL; if (EXPENSIVE_CHECKS) { - printf("%s: starting 100rel timeout test, test will complete in 4 seconds\n", - name); + printf("%s: starting 100rel timeout test, test will complete in 4 seconds\n", + name); - TEST(nta_agent_set_params(ag->ag_agent, - NTATAG_SIP_T1(25), - NTATAG_SIP_T1X64(64 * 25), - TAG_END()), 2); + TEST(nta_agent_set_params(ag->ag_agent, + NTATAG_SIP_T1(25), + NTATAG_SIP_T1X64(64 * 25), + TAG_END()), 2); - ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, - alice_leg_callback, - ag, - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - TAG_END()); - TEST_1(ag->ag_alice_leg); + ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, + alice_leg_callback, + ag, + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + TAG_END()); + TEST_1(ag->ag_alice_leg); - TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL)); + TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL)); - /* Send INVITE, - * send precious provisional response - * do not send PRACK, - * timeout (after 64 * t1 ~ 3.2 seconds), - */ - nta_leg_bind(ag->ag_server_leg, bob_leg_callback2, ag); - ag->ag_expect_leg = ag->ag_server_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, - outgoing_callback, ag, - ag->ag_obp, - SIP_METHOD_INVITE, - (url_string_t *)ag->ag_m_bob->m_url, - SIPTAG_SUBJECT_STR("Call 3"), - SIPTAG_CONTACT(ag->ag_m_alice), - SIPTAG_REQUIRE_STR("100rel"), - SIPTAG_CONTENT_TYPE(c), - SIPTAG_PAYLOAD(sdp), - TAG_END()); - TEST_1(ag->ag_orq); + { + invite_client_t ic[1] = {{ {{ ag, "Call 3", NULL, checks_for_invite, invite_client_deinit }} }}; + client_t *ctx = ic->ic_client; + + /* Send INVITE, + * send precious provisional response + * do not send PRACK, + * timeout (after 64 * t1 ~ 3.2 seconds), + */ + nta_leg_bind(ag->ag_server_leg, bob_leg_callback2, ag); + ag->ag_expect_leg = ag->ag_server_leg; + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, + outgoing_callback, ctx, + ag->ag_obp, + SIP_METHOD_INVITE, + (url_string_t *)ag->ag_m_bob->m_url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_CONTACT(ag->ag_m_alice), + SIPTAG_REQUIRE_STR("100rel"), + SIPTAG_CONTENT_TYPE(ct), + SIPTAG_PAYLOAD(sdp), + TAG_END()); + TEST_1(ctx->c_orq); - nta_test_run(ag); - TEST(ag->ag_status, 503); - TEST_P(ag->ag_orq, NULL); - TEST_P(ag->ag_latest_leg, ag->ag_server_leg); - TEST_1(ag->ag_bob_leg == NULL); + nta_test_run(ag); + TEST(ctx->c_status, 503); + TEST_P(ctx->c_orq, NULL); + TEST_P(ag->ag_latest_leg, ag->ag_server_leg); + TEST_1(ag->ag_bob_leg == NULL); + } - TEST(nta_agent_set_params(ag->ag_agent, - NTATAG_SIP_T1(500), - NTATAG_SIP_T1X64(64 * 500), - TAG_END()), 2); + TEST(nta_agent_set_params(ag->ag_agent, + NTATAG_SIP_T1(500), + NTATAG_SIP_T1X64(64 * 500), + TAG_END()), 2); } if (EXPENSIVE_CHECKS || 1) { - printf("%s: starting timer C, test will complete in 1 seconds\n", - name); + /* + * client sends INVITE, + * server sends provisional response, + * client PRACKs it, + * client timeouts after timer C + */ + + invite_client_t ic[1] = {{ + {{ ag, "Call 4", NULL, checks_for_100rel, invite_client_deinit }} + }}; + client_t *ctx = ic->ic_client; + + printf("%s: starting timer C, test will complete in 1 seconds\n", + name); - TEST(nta_agent_set_params(ag->ag_agent, - NTATAG_TIMER_C(1000), - TAG_END()), 1); + TEST(nta_agent_set_params(ag->ag_agent, + NTATAG_TIMER_C(1000), + TAG_END()), 1); - TEST_1(ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, - alice_leg_callback, - ag, - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - TAG_END())); - TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL)); + TEST_1(ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, + alice_leg_callback, + ag, + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + TAG_END())); + TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL)); - /* Send INVITE, - * send precious provisional response - * timeout after timer C - */ - nta_leg_bind(ag->ag_server_leg, bob_leg_callback3, ag); - ag->ag_expect_leg = ag->ag_server_leg; - TEST_1(ag->ag_orq = - nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, - invite_prack_callback, ag, - ag->ag_obp, - SIP_METHOD_INVITE, - (url_string_t *)ag->ag_m_bob->m_url, - SIPTAG_SUBJECT_STR("Call 4"), - SIPTAG_CONTACT(ag->ag_m_alice), - SIPTAG_REQUIRE_STR("100rel"), - SIPTAG_CONTENT_TYPE(c), - SIPTAG_PAYLOAD(sdp), - TAG_END())); - nta_test_run_until_canceled(ag); - TEST(ag->ag_status, 408); - TEST_1(ag->ag_canceled != 0); - TEST_P(ag->ag_orq, NULL); - TEST_P(ag->ag_latest_leg, ag->ag_server_leg); - TEST_1(ag->ag_bob_leg); - nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL; + nta_leg_bind(ag->ag_server_leg, bob_leg_callback3, ag); + ag->ag_expect_leg = ag->ag_server_leg; + TEST_1(ctx->c_orq = + nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, + outgoing_callback, ic->ic_client, + ag->ag_obp, + SIP_METHOD_INVITE, + (url_string_t *)ag->ag_m_bob->m_url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_CONTACT(ag->ag_m_alice), + SIPTAG_REQUIRE_STR("100rel"), + SIPTAG_CONTENT_TYPE(ct), + SIPTAG_PAYLOAD(sdp), + TAG_END())); - TEST(nta_agent_set_params(ag->ag_agent, - NTATAG_TIMER_C(185 * 1000), - TAG_END()), 1); + /* Run until 1) server gets CANCEL and 2) client gets 408 */ + TEST_1(!client_run_until_canceled(ctx, 408)); - nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL; - ag->ag_latest_leg = NULL; - ag->ag_call_leg = NULL; - if (ag->ag_call_tag) - su_free(ag->ag_home, (void *)ag->ag_call_tag), ag->ag_call_tag = NULL; + TEST_1(ag->ag_canceled != 0); + TEST_P(ag->ag_latest_leg, ag->ag_server_leg); + TEST_1(ag->ag_bob_leg); + nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL; + + TEST(nta_agent_set_params(ag->ag_agent, + NTATAG_TIMER_C(185 * 1000), + TAG_END()), 1); + + nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL; + ag->ag_latest_leg = NULL; + ag->ag_call_leg = NULL; } + END(); } @@ -3430,7 +3238,7 @@ int alice_leg_callback2(agent_t *ag, } if(sip) - return 200; + return 200; END(); } @@ -3444,76 +3252,81 @@ int alice_leg_callback2(agent_t *ag, */ int test_fix_467(agent_t *ag) { - sip_content_type_t *c = ag->ag_content_type; + sip_content_type_t *ct = ag->ag_content_type; sip_payload_t *sdp = ag->ag_payload; nta_leg_t *old_leg; BEGIN(); ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, - alice_leg_callback2, - ag, - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - TAG_END()); + alice_leg_callback2, + ag, + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + TAG_END()); TEST_1(ag->ag_alice_leg); TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL)); ag->ag_bob_leg = NULL; - ag->ag_call_tag = NULL; - /* Send INVITE */ - nta_leg_bind(ag->ag_server_leg, bob_leg_callback2, ag); - ag->ag_expect_leg = ag->ag_server_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, - invite_prack_callback, ag, - ag->ag_obp, - SIP_METHOD_INVITE, - (url_string_t *)ag->ag_m_bob->m_url, - SIPTAG_SUBJECT_STR("Call 5"), - SIPTAG_CONTACT(ag->ag_m_alice), - SIPTAG_REQUIRE_STR("100rel"), - SIPTAG_CONTENT_TYPE(c), - SIPTAG_PAYLOAD(sdp), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - /*TEST(ag->ag_tag_status, 183);*/ - TEST_P(ag->ag_orq, NULL); - TEST_P(ag->ag_latest_leg, ag->ag_server_leg); - TEST_1(ag->ag_bob_leg != NULL); + { + invite_client_t ic[1] = {{ + {{ ag, "Call 5", NULL, checks_for_100rel, invite_client_deinit }} + }}; + client_t *ctx = ic->ic_client; + + /* Send INVITE */ + nta_leg_bind(ag->ag_server_leg, bob_leg_callback2, ag); + ag->ag_expect_leg = ag->ag_server_leg; + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, + outgoing_callback, ic->ic_client, + ag->ag_obp, + SIP_METHOD_INVITE, + (url_string_t *)ag->ag_m_bob->m_url, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_CONTACT(ag->ag_m_alice), + SIPTAG_REQUIRE_STR("100rel"), + SIPTAG_CONTENT_TYPE(ct), + SIPTAG_PAYLOAD(sdp), + TAG_END()); + + TEST_1(!client_run(ctx, 200)); + + /*TEST(ag->ag_tag_status, 183);*/ + TEST_P(ag->ag_latest_leg, ag->ag_server_leg); + TEST_1(ag->ag_bob_leg != NULL); + } - /* Send BYE from Bob to Alice */ old_leg = ag->ag_expect_leg = ag->ag_alice_leg; - ag->ag_orq = - nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ag, - NULL, - SIP_METHOD_BYE, - NULL, - SIPTAG_SUBJECT_STR("Hangup"), - SIPTAG_FROM(ag->ag_alice), - SIPTAG_TO(ag->ag_bob), - SIPTAG_CONTACT(ag->ag_m_alice), - SIPTAG_CONTENT_TYPE(c), - SIPTAG_PAYLOAD(sdp), - TAG_END()); - TEST_1(ag->ag_orq); - - nta_test_run(ag); - TEST(ag->ag_status, 200); - TEST_P(ag->ag_orq, NULL); - TEST_P(ag->ag_latest_leg, old_leg); - TEST_P(ag->ag_alice_leg, NULL); + + { + client_t ctx[1] = {{ ag, "Hangup" }}; + + /* Send BYE from Bob to Alice */ + ctx->c_orq = + nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ctx, + NULL, + SIP_METHOD_BYE, + NULL, + SIPTAG_SUBJECT_STR(ctx->c_name), + SIPTAG_FROM(ag->ag_alice), + SIPTAG_TO(ag->ag_bob), + SIPTAG_CONTACT(ag->ag_m_alice), + SIPTAG_CONTENT_TYPE(ct), + SIPTAG_PAYLOAD(sdp), + TAG_END()); + TEST_1(!client_run(ctx, 200)); + TEST_P(ag->ag_latest_leg, old_leg); + TEST_P(ag->ag_alice_leg, NULL); + } END(); -/* - nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL; - ag->ag_latest_leg = NULL; - ag->ag_call_leg = NULL; -*/ + /* + nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL; + ag->ag_latest_leg = NULL; + ag->ag_call_leg = NULL; + */ } #if HAVE_ALARM @@ -3551,6 +3364,29 @@ void usage(int exitcode) exit(exitcode); } +#if HAVE_OPEN_C +int posix_main(int argc, char *argv[]); + +int main(int argc, char *argv[]) +{ + int retval; + + tstflags |= tst_verbatim; + + su_log_set_level(su_log_default, 9); + su_log_set_level(nta_log, 9); + su_log_set_level(tport_log, 9); + + retval = posix_main(argc, argv); + + sleep(7); + + return retval; +} + +#define main posix_main +#endif + int main(int argc, char *argv[]) { int retval = 0, quit_on_single_failure = 0; @@ -3633,16 +3469,6 @@ int main(int argc, char *argv[]) } #endif -#if HAVE_OPEN_C - tstflags |= tst_verbatim; - su_log_soft_set_level(su_log_default, 9); - su_log_soft_set_level(nta_log, 9); - su_log_soft_set_level(tport_log, 9); - setenv("SU_DEBUG", "9", 1); - setenv("NUA_DEBUG", "9", 1); - setenv("NTA_DEBUG", "9", 1); - setenv("TPORT_DEBUG", "9", 1); -#endif su_init(); if (!(TSTFLAGS & tst_verbatim)) { @@ -3650,17 +3476,10 @@ int main(int argc, char *argv[]) su_log_soft_set_level(tport_log, 0); } -#if HAVE_OPEN_C #define SINGLE_FAILURE_CHECK() \ - do { fflush(stdout); \ - if (retval && quit_on_single_failure) { su_deinit(); sleep(7); return retval; } \ - } while(0) -#else - #define SINGLE_FAILURE_CHECK() \ - do { fflush(stdout); \ - if (retval && quit_on_single_failure) { su_deinit(); return retval; } \ - } while(0) -#endif + do { fflush(stdout); \ + if (retval && quit_on_single_failure) { su_deinit(); return retval; } \ + } while(0) retval |= test_init(ag, argv[i]); SINGLE_FAILURE_CHECK(); if (retval == 0) { @@ -3681,9 +3500,5 @@ int main(int argc, char *argv[]) su_deinit(); -#if HAVE_OPEN_C - sleep(7); -#endif - return retval; } diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.am index aa0352cf80..aec84dc18b 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.am @@ -8,26 +8,10 @@ # ---------------------------------------------------------------------- # Header paths -INCLUDES = -I$(srcdir)/../bnf -I../bnf \ - -I$(srcdir)/../ipt -I../ipt \ - -I$(srcdir)/../iptsec -I../iptsec \ - -I$(srcdir)/../http -I../http \ - -I$(srcdir)/../msg -I../msg \ - -I$(srcdir)/../nea -I../nea \ - -I$(srcdir)/../nta -I../nta \ - -I$(srcdir)/../nth -I../nth \ - -I$(srcdir)/../sdp -I../sdp \ - -I$(srcdir)/../sip -I../sip \ - -I$(srcdir)/../soa -I../soa \ - -I$(srcdir)/../tport -I../tport \ - -I$(srcdir)/../stun -I../stun \ - -I$(srcdir)/../url -I../url \ - -I$(srcdir)/../su -I../su - # ---------------------------------------------------------------------- # Build targets -noinst_LTLIBRARIES = libnua.la +noinst_LTLIBRARIES = libnua.la libtestnua.la libtestproxy.la libtestnat.la check_PROGRAMS = test_nua @@ -57,7 +41,26 @@ libnua_la_SOURCES = nua.c nua_stack.h nua_common.c nua_stack.c \ COVERAGE_INPUT = $(libnua_la_SOURCES) $(include_sofia_HEADERS) -LDADD = libnua.la \ +test_nua_LDFLAGS = -static + +libtestnua_la_SOURCES = test_nua.h test_ops.c \ + test_init.c \ + test_nua_api.c test_nua_params.c \ + test_register.c test_basic_call.c \ + test_offer_answer.c \ + test_call_reject.c test_cancel_bye.c \ + test_call_hold.c test_session_timer.c \ + test_refer.c test_100rel.c \ + test_simple.c test_sip_events.c \ + test_extension.c + +libtestproxy_la_SOURCES = test_proxy.h test_proxy.c + +libtestnat_la_SOURCES = test_nat.h test_nat.c test_nat_tags.c + +test_nua_SOURCES = test_nua.c + +test_nua_LDADD = libnua.la libtestnua.la libtestproxy.la libtestnat.la \ ../iptsec/libiptsec.la \ ../ipt/libipt.la \ ../nea/libnea.la \ @@ -74,21 +77,6 @@ LDADD = libnua.la \ ../bnf/libbnf.la \ ../su/libsu.la -test_nua_LDFLAGS = -static - -test_nua_SOURCES = test_nua.c test_nua.h test_ops.c \ - test_init.c \ - test_nua_api.c test_nua_params.c \ - test_register.c test_basic_call.c \ - test_offer_answer.c \ - test_call_reject.c test_cancel_bye.c \ - test_call_hold.c test_session_timer.c \ - test_refer.c test_100rel.c \ - test_simple.c test_sip_events.c \ - test_extension.c \ - test_proxy.h test_proxy.c \ - test_nat.h test_nat.c test_nat_tags.c - # ---------------------------------------------------------------------- # Install and distribution rules @@ -99,4 +87,6 @@ EXTRA_DIST = nua.docs $(BUILT_SOURCES) include $(top_srcdir)/rules/sofia.am +INCLUDES = ${INTERNAL_INCLUDES} + TAG_DLL_FLAGS = LIST=nua_tag_list diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua.c index b625e258ef..7e3787b134 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua.c @@ -43,8 +43,6 @@ #include #define SU_ROOT_MAGIC_T struct nua_s -#define SU_MSG_ARG_T struct event_s -#define NUA_SAVED_EVENT_T su_msg_t * #include #include @@ -192,7 +190,7 @@ void nua_shutdown(nua_t *nua) if (nua) nua->nua_shutdown_started = 1; - nua_signal(nua, NULL, NULL, 1, nua_r_shutdown, 0, NULL, TAG_END()); + nua_signal(nua, NULL, NULL, nua_r_shutdown, 0, NULL, TAG_END()); } /** Destroy the @nua stack. @@ -227,6 +225,8 @@ void nua_destroy(nua_t *nua) return; } + nua->nua_callback = NULL; + su_task_deinit(nua->nua_server); su_task_deinit(nua->nua_client); @@ -574,7 +574,7 @@ void nua_set_params(nua_t *nua, tag_type_t tag, tag_value_t value, ...) enter; - nua_signal(nua, NULL, NULL, 0, nua_r_set_params, 0, NULL, ta_tags(ta)); + nua_signal(nua, NULL, NULL, nua_r_set_params, 0, NULL, ta_tags(ta)); ta_end(ta); } @@ -587,7 +587,7 @@ void nua_get_params(nua_t *nua, tag_type_t tag, tag_value_t value, ...) enter; - nua_signal(nua, NULL, NULL, 0, nua_r_get_params, 0, NULL, ta_tags(ta)); + nua_signal(nua, NULL, NULL, nua_r_get_params, 0, NULL, ta_tags(ta)); ta_end(ta); } @@ -597,7 +597,7 @@ void nua_get_params(nua_t *nua, tag_type_t tag, tag_value_t value, ...) if (NH_IS_VALID((nh))) { \ ta_list ta; \ ta_start(ta, tag, value); \ - nua_signal((nh)->nh_nua, nh, NULL, 0, event, 0, NULL, ta_tags(ta)); \ + nua_signal((nh)->nh_nua, nh, NULL, event, 0, NULL, ta_tags(ta)); \ ta_end(ta); \ } \ else { \ @@ -881,7 +881,7 @@ void nua_respond(nua_handle_t *nh, if (NH_IS_VALID(nh)) { ta_list ta; ta_start(ta, tag, value); - nua_signal(nh->nh_nua, nh, NULL, 0, nua_r_respond, + nua_signal(nh->nh_nua, nh, NULL, nua_r_respond, status, phrase, ta_tags(ta)); ta_end(ta); } @@ -922,197 +922,7 @@ void nua_handle_destroy(nua_handle_t *nh) if (NH_IS_VALID(nh) && !NH_IS_DEFAULT(nh)) { nh->nh_valid = NULL; /* Events are no more delivered to appl. */ - nua_signal(nh->nh_nua, nh, NULL, 1, nua_r_destroy, 0, NULL, TAG_END()); - } -} - -/*# Send a request to the protocol thread */ -void nua_signal(nua_t *nua, nua_handle_t *nh, msg_t *msg, int always, - nua_event_t event, - int status, char const *phrase, - tag_type_t tag, tag_value_t value, ...) -{ - su_msg_r sumsg = SU_MSG_R_INIT; - size_t len, xtra, e_len, l_len = 0, l_xtra = 0; - ta_list ta; - - if (nua == NULL) - return; - - ta_start(ta, tag, value); - - e_len = offsetof(event_t, e_tags); - len = tl_len(ta_args(ta)); - xtra = tl_xtra(ta_args(ta), len); - - if (su_msg_create(sumsg, nua->nua_server, su_task_null, - nua_stack_signal, - e_len + len + l_len + xtra + l_xtra) == 0) { - event_t *e = su_msg_data(sumsg); - tagi_t *t = e->e_tags; - void *b = (char *)t + len + l_len; - - tagi_t *tend = (tagi_t *)b; - char *bend = (char *)b + xtra + l_xtra; - - t = tl_dup(t, ta_args(ta), &b); - - assert(tend == t); (void)tend; assert(b == bend); (void)bend; - - e->e_always = always; - e->e_event = event; - e->e_nh = event == nua_r_destroy ? nh : nua_handle_ref(nh); - e->e_status = status; - e->e_phrase = phrase; - - SU_DEBUG_7(("nua(%p): signal %s\n", (void *)nh, - nua_event_name(event) + 4)); - - if (su_msg_send(sumsg) != 0 && event != nua_r_destroy) - nua_handle_unref(nh); - } - else { - /* XXX - we should return error code to application but we just abort() */ - assert(ENOMEM == 0); - } - - ta_end(ta); -} - -/*# Receive event from protocol machine and hand it over to application */ -void nua_event(nua_t *root_magic, su_msg_r sumsg, event_t *e) -{ - nua_t *nua; - nua_handle_t *nh = e->e_nh; - - enter; - - if (nh) { - if (!nh->nh_ref_by_user && nh->nh_valid) { - nh->nh_ref_by_user = 1; - nua_handle_ref(nh); - } - } - - if (!nh || !nh->nh_valid) { /* Handle has been destroyed */ - if (nua_log->log_level >= 7) { - char const *name = nua_event_name(e->e_event) + 4; - SU_DEBUG_7(("nua(%p): event %s dropped\n", (void *)nh, name)); - } - if (nh && !NH_IS_DEFAULT(nh) && nua_handle_unref(nh)) { -#if HAVE_NUA_HANDLE_DEBUG - SU_DEBUG_0(("nua(%p): freed by application\n", (void *)nh)); -#else - SU_DEBUG_9(("nua(%p): freed by application\n", (void *)nh)); -#endif - } - if (e->e_msg) - msg_destroy(e->e_msg), e->e_msg = NULL; - return; - } - - nua = nh->nh_nua; assert(nua); - - if (e->e_event == nua_r_shutdown && e->e_status >= 200) - nua->nua_shutdown_final = 1; - - if (!nua->nua_callback) - return; - - if (NH_IS_DEFAULT(nh)) - nh = NULL; - - su_msg_save(nua->nua_current, sumsg); - - e->e_nh = NULL; - - nua->nua_callback(e->e_event, e->e_status, e->e_phrase, - nua, nua->nua_magic, - nh, nh ? nh->nh_magic : NULL, - e->e_msg ? sip_object(e->e_msg) : NULL, - e->e_tags); - - if (nh && !NH_IS_DEFAULT(nh) && nua_handle_unref(nh)) { -#if HAVE_NUA_HANDLE_DEBUG - SU_DEBUG_0(("nua(%p): freed by application\n", (void *)nh)); -#else - SU_DEBUG_9(("nua(%p): freed by application\n", (void *)nh)); -#endif - } - - if (!su_msg_is_non_null(nua->nua_current)) - return; - - if (e->e_msg) - msg_destroy(e->e_msg), e->e_msg = NULL; - - su_msg_destroy(nua->nua_current); -} - -/** Get current request message. @NEW_1_12_4. - * - * @note A response message is returned when processing response message. - * - * @sa #nua_event_e, nua_respond(), NUTAG_WITH_CURRENT() - */ -msg_t *nua_current_request(nua_t const *nua) -{ - return nua && nua->nua_current ? su_msg_data(nua->nua_current)->e_msg : NULL; -} - -/** Get request message from saved nua event. @NEW_1_12_4. - * - * @sa nua_save_event(), nua_respond(), NUTAG_WITH_SAVED(), - */ -msg_t *nua_saved_event_request(nua_saved_event_t const *saved) -{ - return saved && saved[0] ? su_msg_data(saved)->e_msg : NULL; -} - -/** Save nua event and its arguments. - * - * @sa #nua_event_e, nua_event_data() nua_saved_event_request(), nua_destroy_event() - */ -int nua_save_event(nua_t *nua, nua_saved_event_t return_saved[1]) -{ - if (nua && return_saved) { - su_msg_save(return_saved, nua->nua_current); - if (su_msg_is_non_null(return_saved)) { - /* Remove references to tasks */ - su_msg_remove_refs(return_saved); - return 1; - } - } - return 0; -} - -/** Get event data. - * - * @sa #nua_event_e, nua_event_save(), nua_saved_event_request(), nua_destroy_event(). - */ -nua_event_data_t const *nua_event_data(nua_saved_event_t const saved[1]) -{ - return saved ? su_msg_data(saved) : NULL; -} - -/** Destroy saved event. - * - * @sa #nua_event_e, nua_event_save(), nua_event_data(), nua_saved_event_request(). - */ -void nua_destroy_event(nua_saved_event_t saved[1]) -{ - if (su_msg_is_non_null(saved)) { - event_t *e = su_msg_data(saved); - nua_handle_t *nh = e->e_nh; - - if (e->e_msg) - msg_destroy(e->e_msg), e->e_msg = NULL; - - if (nh && !NH_IS_DEFAULT(nh) && nua_handle_unref(nh)) { - SU_DEBUG_9(("nua(%p): freed by application\n", (void *)nh)); - } - - su_msg_destroy(saved); + nua_signal(nh->nh_nua, nh, NULL, nua_r_destroy, 0, NULL, TAG_END()); } } diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_common.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_common.c index 1c02537999..df9643871f 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_common.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_common.c @@ -52,7 +52,6 @@ #include #define SU_ROOT_MAGIC_T struct nua_s -#define SU_MSG_ARG_T struct event_s #include diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h b/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h index 9750c0684c..88f3ffd608 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h @@ -50,7 +50,11 @@ typedef struct nua_server_request nua_server_request_t; typedef struct nua_client_request nua_client_request_t; typedef struct nua_dialog_peer_info nua_dialog_peer_info_t; -typedef su_msg_r nua_saved_signal_t; +#ifndef NUA_SAVED_SIGNAL_T +#define NUA_SAVED_SIGNAL_T struct nua_saved_signal * +#endif + +typedef NUA_SAVED_SIGNAL_T nua_saved_signal_t; typedef struct { sip_method_t sm_method; @@ -80,6 +84,7 @@ typedef struct { } nua_server_methods_t; + /* Server side transaction */ struct nua_server_request { struct nua_server_request *sr_next, **sr_prev; @@ -132,7 +137,7 @@ struct nua_server_request { size_t sr_sdp_len; /**< SDP length */ /**< Save 200 OK nua_respond() signal until PRACK has been received */ - nua_saved_signal_t sr_signal; + nua_saved_signal_t sr_signal[1]; }; #define SR_STATUS(sr, status, phrase) \ @@ -141,6 +146,8 @@ struct nua_server_request { #define SR_STATUS1(sr, statusphrase) \ sr_status(sr, statusphrase) +#define SR_HAS_SAVED_SIGNAL(sr) ((sr)->sr_signal[0] != NULL) + su_inline int sr_status(nua_server_request_t *sr, int status, char const *phrase) { @@ -261,7 +268,7 @@ struct nua_client_request nua_owner_t *cr_owner; nua_dialog_usage_t *cr_usage; - nua_saved_signal_t cr_signal; + nua_saved_signal_t cr_signal[1]; tagi_t const *cr_tags; nua_client_methods_t const *cr_methods; diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c index 023d2237c7..723c1a2f02 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c @@ -890,7 +890,18 @@ int nua_refer_server_respond(nua_server_request_t *sr, tagi_t const *tags) /** @NUA_EVENT nua_i_refer * - * Incoming @b REFER request used to transfer calls. + * Incoming @b REFER request used to transfer calls. The tag list will + * contain tag NUTAG_REFER_EVENT() with the @Event header constructed from + * the REFER request. It will also contain the SIPTAG_REFERRED_BY() tag with + * the @ReferredBy header containing the identity of the party sending the + * REFER. The @ReferredBy structure contained in the tag is constructed from + * the @From header if the @ReferredBy header was not present in the REFER + * request. + * + * The application can let the nua to send NOTIFYs from the call it + * initiates with nua_invite() if it includes in the nua_invite() arguments + * both the NUTAG_NOTIFY_REFER() with the handle with which nua_i_refer was + * received and the NUTAG_REFER_EVENT() from #nua_i_refer event tags. * * @param status status code of response sent automatically by stack * @param phrase a short textual description of @a status code diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_register.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_register.c index fda891f5d3..17ec33ae54 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_register.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_register.c @@ -1941,7 +1941,9 @@ sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh, char _transport[16]; va_list va; sip_contact_t *m; - url_t url = URL_INIT_AS(sip); + url_t url; + + url_init(&url, url_sip); if (!v) return NULL; diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c index 95ddb8b311..93feb9c510 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c @@ -2611,20 +2611,16 @@ int nua_prack_server_report(nua_server_request_t *sr, tagi_t const *tags) if (sri == NULL) { } - else if (su_msg_is_non_null(sri->sr_signal)) { - su_msg_r signal; - event_t *e; + else if (SR_HAS_SAVED_SIGNAL(sri)) { + nua_signal_data_t const *e; - su_msg_save(signal, sri->sr_signal); - - e = su_msg_data(signal); + e = nua_signal_data(sri->sr_signal); + sri->sr_application = SR_STATUS(sri, e->e_status, e->e_phrase); nua_server_params(sri, e->e_tags); nua_server_respond(sri, e->e_tags); nua_server_report(sri); - - su_msg_destroy(signal); } else if (ss->ss_state < nua_callstate_ready && !ss->ss_alerting @@ -3106,7 +3102,6 @@ static int nua_update_client_report(nua_client_request_t *cr, nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; nua_session_usage_t *ss = nua_dialog_usage_private(du); - unsigned next_state = ss->ss_state; nua_stack_event(nh->nh_nua, nh, nta_outgoing_getresponse(orq), @@ -3122,6 +3117,8 @@ static int nua_update_client_report(nua_client_request_t *cr, return 1; if (cr->cr_offer_sent) { + unsigned next_state = ss->ss_state; + if (status < 200) ; else if (du->du_cr && du->du_cr->cr_orq && du->du_cr->cr_status >= 200) { diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c index ad46787cea..5e8bb149d0 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c @@ -45,10 +45,11 @@ #include #define SU_ROOT_MAGIC_T struct nua_s -#define SU_MSG_ARG_T struct event_s +#define SU_MSG_ARG_T struct nua_ee_data #define SU_TIMER_ARG_T struct nua_client_request #define NUA_SAVED_EVENT_T su_msg_t * +#define NUA_SAVED_SIGNAL_T su_msg_t * #define NTA_AGENT_MAGIC_T struct nua_s #define NTA_LEG_MAGIC_T struct nua_handle_s @@ -84,6 +85,26 @@ * * ======================================================================== */ +/* ---------------------------------------------------------------------- */ +/* Internal types */ + +/** Extended event data. */ +typedef struct nua_ee_data { + nua_t *ee_nua; + nua_event_data_t ee_data[1]; +} nua_ee_data_t; + +/** @internal Linked stack frames from nua event callback */ +struct nua_event_frame_s { + nua_event_frame_t *nf_next; + nua_saved_event_t nf_saved[1]; +}; + + +static void nua_event_deinit(nua_ee_data_t *ee); +static void nua_application_event(nua_t *, su_msg_r, nua_ee_data_t *ee); +static void nua_stack_signal(nua_t *nua, su_msg_r, nua_ee_data_t *ee); + nua_handle_t *nh_create(nua_t *nua, tag_type_t t, tag_value_t v, ...); static void nh_append(nua_t *nua, nua_handle_t *nh); static void nh_remove(nua_t *nua, nua_handle_t *nh); @@ -279,18 +300,18 @@ int nua_stack_event(nua_t *nua, nua_handle_t *nh, msg_t *msg, } if (tags) { - e_len = offsetof(event_t, e_tags); + e_len = offsetof(nua_ee_data_t, ee_data[0].e_tags); len = tl_len(tags); xtra = tl_xtra(tags, len); } else { - e_len = sizeof(event_t), len = 0, xtra = 0; + e_len = sizeof(nua_ee_data_t), len = 0, xtra = 0; } p_len = phrase ? strlen(phrase) + 1 : 1; - if (su_msg_create(sumsg, nua->nua_client, su_task_null, - nua_event, e_len + len + xtra + p_len) == 0) { - event_t *e = su_msg_data(sumsg); + if (su_msg_new(sumsg, e_len + len + xtra + p_len) == 0) { + nua_ee_data_t *ee = su_msg_data(sumsg); + nua_event_data_t *e = ee->ee_data; void *p; if (tags) { @@ -303,21 +324,138 @@ int nua_stack_event(nua_t *nua, nua_handle_t *nh, msg_t *msg, else p = e + 1; + ee->ee_nua = nua_stack_ref(nua); e->e_event = event; - e->e_nh = nh ? nua_handle_ref(nh) : nua->nua_dhandle; + e->e_nh = nh ? nua_handle_ref(nh) : NULL; e->e_status = status; e->e_phrase = strcpy(p, phrase ? phrase : ""); if (msg) e->e_msg = msg, su_home_threadsafe(msg_home(msg)); - if (su_msg_send(sumsg) != 0 && nh) - nua_handle_unref(nh); + su_msg_deinitializer(sumsg, nua_event_deinit); + + su_msg_send_to(sumsg, nua->nua_client, nua_application_event); } return event; } -/* ---------------------------------------------------------------------- +static +void nua_event_deinit(nua_ee_data_t *ee) +{ + nua_t *nua = ee->ee_nua; + nua_event_data_t *e = ee->ee_data; + nua_handle_t *nh = e->e_nh; + + if (e->e_msg) + msg_destroy(e->e_msg), e->e_msg = NULL; + + if (nh) + nua_handle_unref(nh), e->e_nh = NULL; + + if (nua) + nua_stack_unref(nua), ee->ee_nua = NULL; +} + +/*# Receive event from protocol machine and hand it over to application */ +static +void nua_application_event(nua_t *dummy, su_msg_r sumsg, nua_ee_data_t *ee) +{ + nua_t *nua = ee->ee_nua; + nua_event_data_t *e = ee->ee_data; + nua_handle_t *nh = e->e_nh; + + enter; + + ee->ee_nua = NULL; + e->e_nh = NULL; + + if (nh == NULL) { + /* Xyzzy */ + } + else if (nh->nh_valid) { + if (!nh->nh_ref_by_user) { + /* Application must now call nua_handle_destroy() */ + nh->nh_ref_by_user = 1; + nua_handle_ref(nh); + } + } + else if (!nh->nh_valid) { /* Handle has been destroyed */ + if (nua_log->log_level >= 7) { + char const *name = nua_event_name(e->e_event) + 4; + SU_DEBUG_7(("nua(%p): event %s dropped\n", (void *)nh, name)); + } + nua_handle_unref(nh); + nua_stack_unref(nua); + return; + } + + if (e->e_event == nua_r_shutdown && e->e_status >= 200) + nua->nua_shutdown_final = 1; + + if (nua->nua_callback) { + nua_event_frame_t frame[1]; + + su_msg_save(frame->nf_saved, sumsg); + frame->nf_next = nua->nua_current, nua->nua_current = frame; + + nua->nua_callback(e->e_event, e->e_status, e->e_phrase, + nua, nua->nua_magic, + nh, nh ? nh->nh_magic : NULL, + e->e_msg ? sip_object(e->e_msg) : NULL, + e->e_tags); + + su_msg_destroy(frame->nf_saved); + nua->nua_current = frame->nf_next; + } + + nua_handle_unref(nh); + nua_stack_unref(nua); +} + +/** Get current request message. @NEW_1_12_4. + * + * @note A response message is returned when processing response message. + * + * @sa #nua_event_e, nua_respond(), NUTAG_WITH_CURRENT() + */ +msg_t *nua_current_request(nua_t const *nua) +{ + if (nua && nua->nua_current && su_msg_is_non_null(nua->nua_current->nf_saved)) + return su_msg_data(nua->nua_current->nf_saved)->ee_data->e_msg; + return NULL; +} + +/** Get request message from saved nua event. @NEW_1_12_4. + * + * @sa nua_save_event(), nua_respond(), NUTAG_WITH_SAVED(), + */ +msg_t *nua_saved_event_request(nua_saved_event_t const *saved) +{ + return saved && saved[0] ? su_msg_data(saved)->ee_data->e_msg : NULL; +} + +/** Save nua event and its arguments. + * + * @sa #nua_event_e, nua_event_data() nua_saved_event_request(), nua_destroy_event() + */ +int nua_save_event(nua_t *nua, nua_saved_event_t return_saved[1]) +{ + if (return_saved) { + if (nua && nua->nua_current) { + su_msg_save(return_saved, nua->nua_current->nf_saved); + return su_msg_is_non_null(return_saved); + } + else + *return_saved = NULL; + } + + return 0; +} + +/* ---------------------------------------------------------------------- */ + +/** @internal * Post signal to stack itself */ void nua_stack_post_signal(nua_handle_t *nh, nua_event_t event, @@ -325,16 +463,73 @@ void nua_stack_post_signal(nua_handle_t *nh, nua_event_t event, { ta_list ta; ta_start(ta, tag, value); - nua_signal((nh)->nh_nua, nh, NULL, 1, event, 0, NULL, ta_tags(ta)); + nua_signal((nh)->nh_nua, nh, NULL, event, 0, NULL, ta_tags(ta)); ta_end(ta); } +/*# Send a request to the protocol thread */ +int nua_signal(nua_t *nua, nua_handle_t *nh, msg_t *msg, + nua_event_t event, + int status, char const *phrase, + tag_type_t tag, tag_value_t value, ...) +{ + su_msg_r sumsg = SU_MSG_R_INIT; + size_t len, xtra, ee_len, l_len = 0, l_xtra = 0; + ta_list ta; + int retval = -1; + + if (nua == NULL) + return -1; + + if (nua->nua_shutdown_started && event != nua_r_shutdown) + return -1; + + ta_start(ta, tag, value); + + ee_len = offsetof(nua_ee_data_t, ee_data[0].e_tags); + len = tl_len(ta_args(ta)); + xtra = tl_xtra(ta_args(ta), len); + + if (su_msg_new(sumsg, ee_len + len + l_len + xtra + l_xtra) == 0) { + nua_ee_data_t *ee = su_msg_data(sumsg); + nua_event_data_t *e = ee->ee_data; + tagi_t *t = e->e_tags; + void *b = (char *)t + len + l_len; + + tagi_t *tend = (tagi_t *)b; + char *bend = (char *)b + xtra + l_xtra; + + t = tl_dup(t, ta_args(ta), &b); + + assert(tend == t); (void)tend; assert(b == bend); (void)bend; + + e->e_always = event == nua_r_destroy || event == nua_r_shutdown; + e->e_event = event; + e->e_nh = nh ? nua_handle_ref(nh) : NULL; + e->e_status = status; + e->e_phrase = phrase; + + SU_DEBUG_7(("nua(%p): signal %s\n", (void *)nh, + nua_event_name(event) + 4)); + + su_msg_deinitializer(sumsg, nua_event_deinit); + + retval = su_msg_send_to(sumsg, nua->nua_server, nua_stack_signal); + } + + ta_end(ta); + + return retval; +} + /* ---------------------------------------------------------------------- * Receiving events from client */ -void nua_stack_signal(nua_t *nua, su_msg_r msg, nua_event_data_t *e) +static +void nua_stack_signal(nua_t *nua, su_msg_r msg, nua_ee_data_t *ee) { + nua_event_data_t *e = ee->ee_data; nua_handle_t *nh = e->e_nh; tagi_t *tags = e->e_tags; nua_event_t event; @@ -342,11 +537,6 @@ void nua_stack_signal(nua_t *nua, su_msg_r msg, nua_event_data_t *e) assert(tags); - if (nua_log->log_level >= 7) { - char const *name = nua_event_name(e->e_event) + 4; - SU_DEBUG_7(("nua(%p): recv %s\n", (void *)nh, name)); - } - if (nh) { if (!nh->nh_prev) nh_append(nua, nh); @@ -359,6 +549,7 @@ void nua_stack_signal(nua_t *nua, su_msg_r msg, nua_event_data_t *e) if (nua_log->log_level >= 5) { char const *name = nua_event_name(e->e_event); + if (e->e_status == 0) SU_DEBUG_5(("nua(%p): signal %s\n", (void *)nh, name + 4)); else @@ -377,8 +568,7 @@ void nua_stack_signal(nua_t *nua, su_msg_r msg, nua_event_data_t *e) 901, "Stack is going down", NULL); } - - switch (event) { + else switch (event) { case nua_r_get_params: nua_stack_get_params(nua, nh ? nh : nua->nua_dhandle, event, tags); break; @@ -463,11 +653,44 @@ void nua_stack_signal(nua_t *nua, su_msg_r msg, nua_event_data_t *e) nua_stack_event(nh->nh_nua, nh, NULL, event, NUA_INTERNAL_ERROR, NULL); } - if (su_msg_is_non_null(nua->nua_signal)) - su_msg_destroy(nua->nua_signal); + su_msg_destroy(nua->nua_signal); +} - if (nh != nua->nua_dhandle) - nua_handle_unref(nh); +/* ====================================================================== */ +/* Signal and event handling */ + +/** Get event data. + * + * @sa #nua_event_e, nua_event_save(), nua_saved_event_request(), nua_destroy_event(). + */ +nua_event_data_t const *nua_event_data(nua_saved_event_t const saved[1]) +{ + return saved && saved[0] ? su_msg_data(saved)->ee_data : NULL; +} + +/** Destroy saved event. + * + * @sa #nua_event_e, nua_event_save(), nua_event_data(), nua_saved_event_request(). + */ +void nua_destroy_event(nua_saved_event_t saved[1]) +{ + if (saved) su_msg_destroy(saved); +} + +/** @internal Move signal. */ +void nua_move_signal(nua_saved_signal_t a[1], nua_saved_signal_t b[1]) +{ + su_msg_save(a, b); +} + +void nua_destroy_signal(nua_saved_signal_t saved[1]) +{ + if (saved) su_msg_destroy(saved); +} + +nua_signal_data_t const *nua_signal_data(nua_saved_signal_t const saved[1]) +{ + return nua_event_data(saved); } /* ====================================================================== */ @@ -1114,6 +1337,8 @@ int nua_stack_process_request(nua_handle_t *nh, (Call/Transaction Does Not Exist) status code and pass that to the server transaction. */ + if (method == sip_method_info) + /* accept out-of-dialog info */; else if (method != sip_method_message || !NH_PGET(nh, win_messenger_enable)) sm = NULL; } @@ -1242,11 +1467,12 @@ void nua_server_request_destroy(nua_server_request_t *sr) if (sr == NULL) return; + if (SR_HAS_SAVED_SIGNAL(sr)) + nua_destroy_signal(sr->sr_signal); + if (sr->sr_irq) nta_incoming_destroy(sr->sr_irq), sr->sr_irq = NULL; - su_msg_destroy(sr->sr_signal); - if (sr->sr_request.msg) msg_destroy(sr->sr_request.msg), sr->sr_request.msg = NULL; @@ -1379,8 +1605,9 @@ nua_stack_respond(nua_t *nua, nua_handle_t *nh, sr->sr_application = status; if (tags && nua_stack_set_params(nua, nh, nua_i_none, tags) < 0) SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); - else + else { sr->sr_status = status, sr->sr_phrase = phrase; + } } nua_server_params(sr, tags); @@ -1771,12 +1998,12 @@ int nua_client_create(nua_handle_t *nh, cr->cr_auto = 1; if (su_msg_is_non_null(nh->nh_nua->nua_signal)) { - nua_event_data_t const *e = su_msg_data(nh->nh_nua->nua_signal); + nua_event_data_t const *e = su_msg_data(nh->nh_nua->nua_signal)->ee_data; if (tags == e->e_tags && event == e->e_event) { cr->cr_auto = 0; if (tags) { - su_msg_save(cr->cr_signal, nh->nh_nua->nua_signal); + nua_move_signal(cr->cr_signal, nh->nh_nua->nua_signal); cr->cr_tags = tags; } } @@ -1860,7 +2087,7 @@ void nua_client_request_destroy(nua_client_request_t *cr) nh = cr->cr_owner; - su_msg_destroy(cr->cr_signal); + nua_destroy_signal(cr->cr_signal); nua_client_request_remove(cr); nua_client_bind(cr, NULL); @@ -2575,9 +2802,11 @@ int nua_base_client_check_restart(nua_client_request_t *cr, cr->cr_challenged = 1; - if (invalid) + if (invalid) { /* Bad username/password */ + SU_DEBUG_7(("nua(%p): bad credentials, clearing them\n", (void *)nh)); auc_clear_credentials(&nh->nh_auth, NULL, NULL); + } else if (auc_has_authorization(&nh->nh_auth)) return nua_client_restart(cr, 100, "Request Authorized by Cache"); @@ -2594,7 +2823,7 @@ int nua_base_client_check_restart(nua_client_request_t *cr, if (500 <= status && status < 600 && sip->sip_retry_after && sip->sip_retry_after->af_delta < 32) { - char phrase[18]; /* Retry-After: XXXX\0 */ + char phrase[18]; /* Retry After XXXX\0 */ if (cr->cr_timer == NULL) cr->cr_timer = su_timer_create(su_root_task(nh->nh_nua->nua_root), 0); diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h b/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h index fac582f5f5..e8a6226066 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h @@ -75,7 +75,7 @@ SOFIA_BEGIN_DECLS #include "nua_params.h" #endif -typedef struct event_s event_t; +typedef struct event_s event_t, nua_signal_data_t; #define NONE ((void *)-1) @@ -109,7 +109,7 @@ typedef struct register_usage nua_registration_t; #define nua_handle_unref(nh) nua_handle_unref_by((nh), __func__) su_inline nua_handle_t *nua_handle_ref_by(nua_handle_t *nh, - char const *by) + char const *by) { if (nh) SU_DEBUG_0(("nua_handle_ref(%p) => "MOD_ZU" by %s\n", nh, @@ -120,11 +120,16 @@ su_inline nua_handle_t *nua_handle_ref_by(nua_handle_t *nh, su_inline int nua_handle_unref_by(nua_handle_t *nh, char const *by) { - if (nh) - SU_DEBUG_0(("nua_handle_unref(%p) => "MOD_ZU" by %s\n", nh, - su_home_refcount((su_home_t *)nh) - 1, - by)); - return su_home_unref((su_home_t *)nh); + if (nh) { + size_t refcount = su_home_refcount((su_home_t *)nh) - 1; + int freed = su_home_unref((su_home_t *)nh); + if (freed) refcount = 0; + SU_DEBUG_0(("nua_handle_unref(%p) => "MOD_ZU" by %s\n", + nh, refcount, by)); + return freed; + } + + return 0; } #endif @@ -197,6 +202,8 @@ int nh_is_special(nua_handle_t *nh) return nh == NULL || nh->nh_special; } +typedef struct nua_event_frame_s nua_event_frame_t; + extern char const nua_internal_error[]; #define NUA_INTERNAL_ERROR 900, nua_internal_error @@ -214,7 +221,7 @@ struct nua_s { nua_callback_f nua_callback; nua_magic_t *nua_magic; - nua_saved_event_t nua_current[1]; + nua_event_frame_t *nua_current; nua_saved_event_t nua_signal[1]; /* Engine state flags */ @@ -277,10 +284,19 @@ struct nua_s { #define __func__ "nua" #endif +su_inline nua_t *nua_stack_ref(nua_t *nua) +{ + return (nua_t *)su_home_ref(nua->nua_home); +} + +su_inline void nua_stack_unref(nua_t *nua) +{ + su_home_unref(nua->nua_home); +} + /* Internal prototypes */ int nua_stack_init(su_root_t *root, nua_t *nua); void nua_stack_deinit(su_root_t *root, nua_t *nua); -void nua_stack_signal(nua_t *nua, su_msg_r msg, event_t *e); int nua_stack_init_transport(nua_t *nua, tagi_t const *tags); @@ -305,6 +321,10 @@ typedef int nua_stack_signal_handler(nua_t *, nua_event_t, tagi_t const *); +void nua_move_signal(nua_saved_signal_t a[1], nua_saved_signal_t b[1]); +nua_signal_data_t const *nua_signal_data(nua_saved_signal_t const saved[1]); +void nua_destroy_signal(nua_saved_signal_t saved[1]); + nua_stack_signal_handler nua_stack_set_params, nua_stack_get_params, nua_stack_register, @@ -332,6 +352,8 @@ int nua_stack_event(nua_t *nua, nua_handle_t *nh, msg_t *msg, nua_event_t event, int status, char const *phrase, tagi_t const *tags); +void nua_move_event(nua_saved_event_t a[1], nua_saved_event_t b[1]); + nua_handle_t *nh_create_handle(nua_t *nua, nua_hmagic_t *hmagic, tagi_t *tags); nua_handle_t *nua_stack_incoming_handle(nua_t *nua, @@ -431,11 +453,9 @@ typedef unsigned longlong ull; /* ---------------------------------------------------------------------- */ /* Application side prototypes */ -void nua_signal(nua_t *nua, nua_handle_t *nh, msg_t *msg, int always, - nua_event_t event, int status, char const *phrase, - tag_type_t tag, tag_value_t value, ...); - -void nua_event(nua_t *root_magic, su_msg_r sumsg, event_t *e); +int nua_signal(nua_t *nua, nua_handle_t *nh, msg_t *msg, + nua_event_t event, int status, char const *phrase, + tag_type_t tag, tag_value_t value, ...); SOFIA_END_DECLS diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_basic_call.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_basic_call.c index 689edbea05..d7c7feddb4 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_basic_call.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_basic_call.c @@ -463,7 +463,8 @@ int test_basic_call_2(struct context *ctx) #else /* sf.net bug #1816647: Outbound contact does not make it to dialogs */ /* Now we use first registered contact if aor does not match */ - TEST_S(sip->sip_contact->m_url->url_user, "b"); + if (ctx->proxy_tests) + TEST_S(sip->sip_contact->m_url->url_user, "b"); #endif TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); TEST(callstate(e->data->e_tags), nua_callstate_ready); /* READY */ @@ -1043,7 +1044,8 @@ int test_basic_call_5(struct context *ctx) TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_contact); - TEST_S(sip->sip_contact->m_url->url_user, "b"); + if (ctx->proxy_tests) /* Use Contact from registration? */ + TEST_S(sip->sip_contact->m_url->url_user, "b"); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); TEST(callstate(e->data->e_tags), nua_callstate_completing); /* COMPLETING */ TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_init.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_init.c index 92311cb609..b12b75f533 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_init.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_init.c @@ -408,6 +408,7 @@ int test_deinit(struct context *ctx) nua_shutdown(ctx->a.nua); run_a_until(ctx, nua_r_shutdown, until_final_response); + free_events_in_list(ctx, ctx->a.events); free_events_in_list(ctx, ctx->a.specials); nua_destroy(ctx->a.nua), ctx->a.nua = NULL; } @@ -418,6 +419,7 @@ int test_deinit(struct context *ctx) nua_shutdown(ctx->b.nua); run_b_until(ctx, nua_r_shutdown, until_final_response); + free_events_in_list(ctx, ctx->b.events); free_events_in_list(ctx, ctx->b.specials); nua_destroy(ctx->b.nua), ctx->b.nua = NULL; } @@ -428,6 +430,7 @@ int test_deinit(struct context *ctx) nua_shutdown(ctx->c.nua); run_c_until(ctx, nua_r_shutdown, until_final_response); + free_events_in_list(ctx, ctx->c.events); free_events_in_list(ctx, ctx->c.specials); nua_destroy(ctx->c.nua), ctx->c.nua = NULL; } @@ -436,7 +439,7 @@ int test_deinit(struct context *ctx) test_nat_destroy(ctx->nat), ctx->nat = NULL; - su_root_destroy(ctx->root); + su_root_destroy(ctx->root), ctx->root = NULL; END(); } diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_nua.h b/libs/sofia-sip/libsofia-sip-ua/nua/test_nua.h index 0e75b799c8..1d035fcae1 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_nua.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_nua.h @@ -22,7 +22,8 @@ * */ -/**@CFILE test_nua.h +/**@@internal + * @file test_nua.h * @brief High-level tester framework for Sofia SIP User Agent Engine * * @author Pekka Pessi diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_proxy.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_proxy.c index c6e59ac072..afc2819a45 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_proxy.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_proxy.c @@ -206,6 +206,7 @@ struct proxy_tr sip_t *sip; /* request headers */ sip_method_t method; /* request method */ + char const *method_name; int status; /* best status */ url_t *target; /* request-URI */ @@ -343,6 +344,9 @@ test_proxy_deinit(su_root_t *root, struct proxy *proxy) { struct proxy_tr *t; + while (proxy->transactions) + proxy_tr_destroy(proxy->transactions); + if ((t = proxy->stateless)) { proxy->stateless = NULL; proxy_tr_destroy(t); @@ -698,7 +702,7 @@ static int domain_request(union proxy_or_domain *pod, { int (*process)(struct proxy_tr *) = NULL; sip_method_t method = sip->sip_request->rq_method; - + assert(pod->domain->magic = domain_init); if (leg == pod->domain->uleg) @@ -732,6 +736,7 @@ static int proxy_tr_with(struct proxy *proxy, t->sip = sip_object(t->msg); t->method = sip->sip_request->rq_method; + t->method_name = sip->sip_request->rq_method_name; t->target = sip->sip_request->rq_url; t->now = nta_incoming_received(irq, NULL); @@ -767,7 +772,7 @@ static int proxy_transaction(struct proxy_tr *t) return target_transaction(t, t->target, NULL); } - + static int respond_transaction(struct proxy_tr *t, int status, char const *phrase, tag_type_t tag, tag_value_t value, @@ -925,6 +930,7 @@ static int target_transaction(struct proxy_tr *t, tport_t *tport) { struct client_tr *c = su_zalloc(t->proxy->home, sizeof *c); + int stateless = t->method == sip_method_ack; if (c == NULL) return 500; @@ -935,8 +941,7 @@ static int target_transaction(struct proxy_tr *t, if (c->msg) c->rq = sip_request_create(msg_home(c->msg), - c->sip->sip_request->rq_method, - c->sip->sip_request->rq_method_name, + t->method, t->method_name, (url_string_t *)target, NULL); @@ -957,15 +962,18 @@ static int target_transaction(struct proxy_tr *t, NULL, msg_ref_create(c->msg), NTATAG_TPORT(tport), + NTATAG_STATELESS(stateless), TAG_END()); - if (c->client) - return client_tr_insert(&t->clients, c), 0; + if (!c->client) { + msg_destroy(c->msg); + su_free(t->proxy->home, c); + return 500; + } - msg_destroy(c->msg); - su_free(t->proxy->home, c); + client_tr_insert(&t->clients, c); - return 500; + return stateless ? 200 : 0; } static int challenge_transaction(struct proxy_tr *t) @@ -1095,6 +1103,8 @@ void proxy_tr_destroy(struct proxy_tr *t) su_free(t->proxy->home, c); } + msg_destroy(t->msg); + nta_incoming_destroy(t->server); su_free(t->proxy->home, t); diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_register.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_register.c index 1ee17cf248..cb79b12d2b 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_register.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_register.c @@ -1018,6 +1018,15 @@ int test_unregister(struct context *ctx) TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_unregister); } + if (e->data->e_status == 401) { + TEST_1(!e->next); + free_events_in_list(ctx, c->events); + AUTHENTICATE(c, NULL, c->reg->nh, + NUTAG_AUTH("Digest:\"test-proxy\":charlie:secret"), TAG_END()); + run_c_until(ctx, -1, save_until_final_response); + TEST_1(e = c->events->head); + TEST_E(e->data->e_event, nua_r_unregister); + } TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_from->a_url->url_user); diff --git a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h index c0a1071e3f..e35a92a57d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h +++ b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h @@ -398,6 +398,9 @@ typedef void su_msg_function(su_root_magic_t *magic, su_msg_r msg, su_msg_arg_t *arg); +/** Message deinitialize. */ +typedef void su_msg_deinit_func(su_msg_arg_t *arg); + /** Message delivery function pointer type. */ typedef su_msg_function *su_msg_f; @@ -526,6 +529,7 @@ SOFIAPUBFUN int su_msg_create(su_msg_r msg, su_task_r const to, su_task_r const from, su_msg_f wakeup, isize_t size); SOFIAPUBFUN int su_msg_report(su_msg_r msg, su_msg_f report); +SOFIAPUBFUN int su_msg_deinitializer(su_msg_r msg, su_msg_deinit_func *); SOFIAPUBFUN int su_msg_reply(su_msg_r reply, su_msg_cr msg, su_msg_f wakeup, isize_t size); SOFIAPUBFUN void su_msg_destroy(su_msg_r msg); @@ -537,6 +541,11 @@ SOFIAPUBFUN _su_task_r su_msg_from(su_msg_cr msg); SOFIAPUBFUN _su_task_r su_msg_to(su_msg_cr msg); SOFIAPUBFUN int su_msg_send(su_msg_r msg); +SOFIAPUBFUN int su_msg_new(su_msg_r msg, size_t size); +SOFIAPUBFUN int su_msg_send_to(su_msg_r msg, + su_task_r const to, + su_msg_f wakeup); + /** Does reference contain a message? */ #if SU_HAVE_INLINE static SU_INLINE diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_base_port.c b/libs/sofia-sip/libsofia-sip-ua/su/su_base_port.c index 13b0b51e59..715888c021 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_base_port.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_base_port.c @@ -268,8 +268,14 @@ static int su_base_port_execute_msgs(su_msg_t *queue) queue = msg->sum_next, msg->sum_next = NULL; - if (f) - f(SU_ROOT_MAGIC(msg->sum_to->sut_root), &msg, msg->sum_data); + if (f) { + su_root_t *root = msg->sum_to->sut_root; + + if (msg->sum_to->sut_port == NULL) + msg->sum_to->sut_root = NULL; + f(SU_ROOT_MAGIC(root), &msg, msg->sum_data); + } + su_msg_delivery_report(&msg); n++; } diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_port.h b/libs/sofia-sip/libsofia-sip-ua/su/su_port.h index 475c10948e..adb7716031 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_port.h +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_port.h @@ -61,12 +61,13 @@ SOFIA_BEGIN_DECLS /** @internal Message */ struct su_msg_s { - isize_t sum_size; + size_t sum_size; su_msg_t *sum_next; su_task_r sum_to; su_task_r sum_from; su_msg_f sum_func; su_msg_f sum_report; + su_msg_deinit_func *sum_deinit; su_msg_arg_t sum_data[1]; /* minimum size, may be extended */ }; @@ -101,11 +102,11 @@ typedef struct su_port_vtable { struct _GSource *(*su_port_gsource)(su_port_t *port); int (*su_port_send)(su_port_t *self, su_msg_r rmsg); int (*su_port_register)(su_port_t *self, - su_root_t *root, - su_wait_t *wait, - su_wakeup_f callback, - su_wakeup_arg_t *arg, - int priority); + su_root_t *root, + su_wait_t *wait, + su_wakeup_f callback, + su_wakeup_arg_t *arg, + int priority); int (*su_port_unregister)(su_port_t *port, su_root_t *root, su_wait_t *wait, diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_root.c b/libs/sofia-sip/libsofia-sip-ua/su/su_root.c index 2a7ffb228c..daf176cefb 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_root.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_root.c @@ -875,6 +875,30 @@ int su_root_has_thread(su_root_t *root) * Messages */ +/** + * Allocate a su message of given size. + * + * Allocate a su message with given data size. + * + * @param rmsg handle to the new message (may be uninitialized prior calling) + * @param size size of the message data + * + * @retval 0 if successful, + * @retval -1 if message allocation fails. + */ +int su_msg_new(su_msg_r rmsg, size_t size) +{ + su_msg_t *msg; + size_t total = sizeof(*msg) + (size_t)size; + + *rmsg = msg = su_zalloc(NULL, (isize_t)total); + if (!*rmsg) + return -1; + + msg->sum_size = total; + return 0; +} + /** * Allocates a message of given size. * @@ -896,20 +920,13 @@ int su_msg_create(su_msg_r rmsg, su_msg_f wakeup, isize_t size) { - su_msg_t *msg; - - msg = su_zalloc(NULL, sizeof(*msg) + size); - - if (msg) { - msg->sum_size = sizeof(*msg) + size; - SU_TASK_COPY(msg->sum_to, to, su_msg_create); - SU_TASK_COPY(msg->sum_from, from, su_msg_create); - msg->sum_func = wakeup; - *rmsg = msg; + if (su_msg_new(rmsg, (size_t) size) == 0) { + SU_TASK_COPY(rmsg[0]->sum_to, to, su_msg_create); + SU_TASK_COPY(rmsg[0]->sum_from, from, su_msg_create); + rmsg[0]->sum_func = wakeup; return 0; } - *rmsg = NULL; return -1; } @@ -931,11 +948,31 @@ int su_msg_report(su_msg_r msg, return -1; } +/** Add a deinitializer function to a message. + * + * The deinitializer function is called when the message gets destroyed. It + * is called even if the message was never delivered. Note that the thread + * destroying the message and calling the deinit function is not necessarily + * the same that sent the message nor the original recipient. + * + * @param rmsg message reference + * @param deinit pointer to deinitializer function + */ +int su_msg_deinitializer(su_msg_r rmsg, + su_msg_deinit_func *deinit) +{ + if (rmsg && rmsg[0]) { + rmsg[0]->sum_deinit = deinit; + return 0; + } + return -1; +} + /** * Allocates a reply message of given size. * * @param reply handle to the new message (may be uninitialized prior calling) - * @param msg the incoming message + * @param rmsg the incoming message * @param wakeup function that is called when message is delivered * @param size size of the message data * @@ -943,17 +980,17 @@ int su_msg_report(su_msg_r msg, * @retval -1 otherwise. */ -int su_msg_reply(su_msg_r reply, su_msg_cr msg, +int su_msg_reply(su_msg_r reply, su_msg_cr rmsg, su_msg_f wakeup, isize_t size) { - su_msg_r msg0; + su_msg_r rmsg0; - assert(msg != reply); + assert(rmsg != reply); - *msg0 = *(su_msg_t **) msg; + *rmsg0 = *(su_msg_t **) rmsg; *reply = NULL; - return su_msg_create(reply, su_msg_from(msg0), su_msg_to(msg0), wakeup, size); + return su_msg_create(reply, su_msg_from(rmsg0), su_msg_to(rmsg0), wakeup, size); } @@ -964,38 +1001,38 @@ int su_msg_reply(su_msg_r reply, su_msg_cr msg, * sending task. The sending task calls the delivery report function when it * has received the message. */ -void su_msg_delivery_report(su_msg_r msg) +void su_msg_delivery_report(su_msg_r rmsg) { su_task_r swap; - if (!msg || !msg[0]) + if (!rmsg || !rmsg[0]) return; - if (!msg[0]->sum_report) { - su_msg_destroy(msg); + if (!rmsg[0]->sum_report) { + su_msg_destroy(rmsg); return; } - *swap = *msg[0]->sum_from; - *msg[0]->sum_from = *msg[0]->sum_to; - *msg[0]->sum_to = *swap; + *swap = *rmsg[0]->sum_from; + *rmsg[0]->sum_from = *rmsg[0]->sum_to; + *rmsg[0]->sum_to = *swap; - msg[0]->sum_func = msg[0]->sum_report; - msg[0]->sum_report = NULL; - su_msg_send(msg); + rmsg[0]->sum_func = rmsg[0]->sum_report; + rmsg[0]->sum_report = NULL; + su_msg_send(rmsg); } /** Save a message. */ -void su_msg_save(su_msg_r save, su_msg_r msg) +void su_msg_save(su_msg_r save, su_msg_r rmsg) { if (save) { - if (msg) - save[0] = msg[0]; + if (rmsg) + save[0] = rmsg[0]; else save[0] = NULL; } - if (msg) - msg[0] = NULL; + if (rmsg) + rmsg[0] = NULL; } /** @@ -1011,6 +1048,9 @@ void su_msg_destroy(su_msg_r rmsg) SU_TASK_ZAP(rmsg[0]->sum_to, su_msg_destroy); SU_TASK_ZAP(rmsg[0]->sum_from, su_msg_destroy); + if (rmsg[0]->sum_deinit) + rmsg[0]->sum_deinit(rmsg[0]->sum_data); + su_free(NULL, rmsg[0]); } @@ -1048,13 +1088,13 @@ isize_t su_msg_size(su_msg_cr rmsg) * If the message handle contains NULL the function @c su_msg_from * returns NULL. * - * @param msg message handle + * @param rmsg message handle * * @return The task handle of the sender is returned. */ -_su_task_r su_msg_from(su_msg_cr msg) +_su_task_r su_msg_from(su_msg_cr rmsg) { - return msg[0] ? msg[0]->sum_from : NULL; + return rmsg[0] ? rmsg[0]->sum_from : NULL; } /** Get destination task. @@ -1065,24 +1105,24 @@ _su_task_r su_msg_from(su_msg_cr msg) * If the message handle contains NULL the function @c su_msg_to * returns NULL. * - * @param msg message handle + * @param rmsg message handle * * @return The task handle of the recipient is returned. */ -_su_task_r su_msg_to(su_msg_cr msg) +_su_task_r su_msg_to(su_msg_cr rmsg) { - return msg[0] ? msg[0]->sum_to : NULL; + return rmsg[0] ? rmsg[0]->sum_to : NULL; } /** Remove references to 'from' and 'to' tasks from a message. * - * @param msg message handle + * @param rmsg message handle */ -void su_msg_remove_refs(su_msg_cr msg) +void su_msg_remove_refs(su_msg_cr rmsg) { - if (msg[0]) { - su_task_deinit(msg[0]->sum_to); - su_task_deinit(msg[0]->sum_from); + if (rmsg[0]) { + su_task_deinit(rmsg[0]->sum_to); + su_task_deinit(rmsg[0]->sum_from); } } @@ -1115,3 +1155,36 @@ int su_msg_send(su_msg_r rmsg) return 0; } + +/** Send message to the @a to_task and mark @a from_task as sender */ +SOFIAPUBFUN int su_msg_send_to(su_msg_r rmsg, + su_task_r const to_task, + su_msg_f wakeup) +{ + assert(rmsg); assert(to_task); + + if (rmsg[0]) { + su_msg_t *msg = rmsg[0]; + + if (wakeup) + msg->sum_func = wakeup; + + if (msg->sum_to->sut_port && + msg->sum_to->sut_port != to_task->sut_port) { + SU_TASK_ZAP(msg->sum_to, "su_msg_send_to"); + } + + if (to_task->sut_port != NULL) { + msg->sum_to->sut_port = NULL; + msg->sum_to->sut_root = to_task->sut_root; + + return su_port_send(to_task->sut_port, rmsg); + } + + su_msg_destroy(rmsg); + errno = EINVAL; + return -1; + } + + return 0; +} diff --git a/libs/sofia-sip/libsofia-sip-ua/su/test_htable2.c b/libs/sofia-sip/libsofia-sip-ua/su/test_htable2.c index d23f73372c..a11b2fd396 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/test_htable2.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/test_htable2.c @@ -96,7 +96,7 @@ struct hentry_s #define HENTRY_IS_USED(e) ((e).e_n != 0) #define HENTRY_REMOVE(e) ((e)->e_n = 0, (e)->e_hash = 0) #define HENTRY_IS_EQUAL(a, b) ((a).e_n == (b).e_n) -#define HALLOC(home, old, newsize) (su_realloc(home, old, newsize)) +#define HALLOC(home, old, newsize) (su_realloc(home, old, (isize_t)newsize)) HTABLE2_BODIES2(htable2_t, htable2, ht2_, entry_t, size_t, HENTRY_HASH, HENTRY_IS_USED, HENTRY_REMOVE, HENTRY_IS_EQUAL, diff --git a/libs/sofia-sip/libsofia-sip-ua/su/test_su.c b/libs/sofia-sip/libsofia-sip-ua/su/test_su.c index 987f75163a..a88c1e2557 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/test_su.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/test_su.c @@ -559,16 +559,10 @@ int main(int argc, char *argv[]) su_perror("su_timer_create"), exit(1); su_timer_set(t, (su_timer_f)do_exit, NULL); - su_clone_pause(ping); - su_clone_pause(pong); - su_msg_create(start_msg, su_clone_task(ping), su_clone_task(pong), init_ping, 0); su_msg_send(start_msg); - su_clone_resume(ping); - su_clone_resume(pong); - su_root_run(root); su_clone_wait(root, ping); diff --git a/libs/sofia-sip/libsofia-sip-ua/su/torture_su_root.c b/libs/sofia-sip/libsofia-sip-ua/su/torture_su_root.c index f99c86f758..d5673f9f7a 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/torture_su_root.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/torture_su_root.c @@ -41,6 +41,7 @@ char const *name = "torture_su_root"; #include #include #include +#include #define TSTFLAGS rt->rt_flags #include @@ -50,6 +51,7 @@ typedef struct test_ep_s test_ep_t; #define SU_ROOT_MAGIC_T root_test_t #define SU_WAKEUP_ARG_T test_ep_t +#define SU_MSG_ARG_T root_test_t * #include #include @@ -83,6 +85,9 @@ struct root_test_s { su_clone_r rt_clone; + unsigned rt_msg_received; + unsigned rt_msg_destroyed; + unsigned rt_fail_init:1; unsigned rt_fail_deinit:1; unsigned rt_success_init:1; @@ -591,6 +596,22 @@ static int set_execute_bit_and_return_3(void *void_rt) return 3; } +static void deinit_simple_msg(su_msg_arg_t *arg) +{ + root_test_t *rt = *arg; + rt->rt_msg_destroyed++; +} + +static void receive_simple_msg(root_test_t *rt, + su_msg_r msg, + su_msg_arg_t *arg) +{ + assert(rt == *arg); + rt->rt_msg_received = + su_task_cmp(su_msg_from(msg), su_task_null) == 0 && + su_task_cmp(su_msg_to(msg), su_task_null) == 0; +} + static int clone_test(root_test_t rt[1]) { BEGIN(); @@ -629,7 +650,21 @@ static int clone_test(root_test_t rt[1]) &retval), 0); TEST(retval, 3); TEST_1(rt->rt_executed); - + + /* Deliver message with su_msg_send() */ + TEST(su_msg_new(m, sizeof &rt), 0); + *su_msg_data(m) = rt; + + rt->rt_msg_received = 0; + rt->rt_msg_destroyed = 0; + + TEST(su_msg_deinitializer(m, deinit_simple_msg), 0); + TEST(su_msg_send_to(m, su_clone_task(rt->rt_clone), receive_simple_msg), 0); + + while (rt->rt_msg_destroyed == 0) + su_root_step(rt->rt_root, 1); + + TEST(rt->rt_msg_received, 1); /* Make sure 3-way handshake is done as expected */ TEST(su_msg_create(m, diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/sofia-sip/tport.h b/libs/sofia-sip/libsofia-sip-ua/tport/sofia-sip/tport.h index 9d8683bb58..f87191bc96 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/sofia-sip/tport.h +++ b/libs/sofia-sip/libsofia-sip-ua/tport/sofia-sip/tport.h @@ -166,7 +166,7 @@ typedef struct { (n)->tpn_comp ? ";comp=" : "", (n)->tpn_comp ? (n)->tpn_comp : "", \ (n)->tpn_ident ? "/" : "", (n)->tpn_ident ? (n)->tpn_ident : "" -/** Create first primary transport. */ +/**Create master transport. */ TPORT_DLL tport_t *tport_tcreate(tp_stack_t *stack, tport_stack_class_t const *tpac, su_root_t *root, diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/test_tport.c b/libs/sofia-sip/libsofia-sip-ua/tport/test_tport.c index 730104054c..d8bed43f99 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/test_tport.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/test_tport.c @@ -798,7 +798,7 @@ static int udp_test(tp_test_t *tt) int pending_server_close, pending_client_close; void server_closed_callback(tp_stack_t *tt, tp_client_t *client, - tport_t *tp, msg_t *msg, int error) + tport_t *tp, msg_t *msg, int error) { assert(msg == NULL); assert(client == NULL); @@ -809,7 +809,7 @@ void server_closed_callback(tp_stack_t *tt, tp_client_t *client, } void client_closed_callback(tp_stack_t *tt, tp_client_t *client, - tport_t *tp, msg_t *msg, int error) + tport_t *tp, msg_t *msg, int error) { assert(msg == NULL); assert(client == NULL); @@ -1232,6 +1232,26 @@ static int sctp_test(tp_test_t *tt) END(); } +struct called { + int n, error, pending, released; +}; + +static +void tls_error_callback(tp_stack_t *tt, tp_client_t *client, + tport_t *tp, msg_t *msg, int error) +{ + struct called *called = (struct called *)client; + + tt->tt_status = -1; + + called->n++, called->error = error; + + if (called->pending) { + called->released = tport_release(tp, called->pending, msg, NULL, client, 0); + called->pending = 0; + } +} + static int tls_test(tp_test_t *tt) { BEGIN(); @@ -1242,6 +1262,7 @@ static int tls_test(tp_test_t *tt) int i; char ident[16]; tport_t *tp, *tp0; + struct called called[1] = {{ 0, 0, 0, 0 }}; TEST_S(dst->tpn_proto, "tls"); @@ -1249,9 +1270,21 @@ static int tls_test(tp_test_t *tt) TEST_1(!new_test_msg(tt, &msg, "tls-first", 1, 1024)); TEST_1(tp = tport_tsend(tt->tt_tports, msg, dst, TAG_END())); TEST_1(tp0 = tport_ref(tp)); + TEST_1(called->pending = tport_pend(tp, msg, tls_error_callback, (tp_client_t *)called)); + + i = tport_test_run(tt, 5); msg_destroy(msg); - TEST(tport_test_run(tt, 5), 1); + if (i < 0) { + if (called->n) { + TEST(called->released, 0); + puts("test_tport: skipping TLS tests"); + tport_unref(tp0); + return 0; + } + } + + TEST(i, 1); TEST_1(!check_msg(tt, tt->tt_rmsg, "tls-first")); msg_destroy(tt->tt_rmsg), tt->tt_rmsg = NULL; diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport.c index bbad7a9b83..6ff369adf2 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport.c @@ -405,7 +405,8 @@ static int tport_base_wakeup(tport_t *self, int events), tport_connected(su_root_magic_t *m, su_wait_t *w, tport_t *self), tport_resolve(tport_t *self, msg_t *msg, tp_name_t const *tpn), - tport_send_error(tport_t *, msg_t *, tp_name_t const *), + tport_send_error(tport_t *, msg_t *, tp_name_t const *, char const *who), + tport_send_fatal(tport_t *, msg_t *, tp_name_t const *, char const *who), tport_queue(tport_t *self, msg_t *msg), tport_queue_rest(tport_t *self, msg_t *msg, msg_iovec_t iov[], size_t iovused), tport_pending_error(tport_t *self, su_sockaddr_t const *dst, int error), @@ -469,7 +470,12 @@ msg_t *tport_destroy_alloc(tp_stack_t *stack, int flags, /** Name for "any" transport. @internal */ static char const tpn_any[] = "*"; -/** Create the master transport. +/** Create the master transport. + * + * Master transport object is used to bind the protocol using transport with + * actual transport objects corresponding to TCP, UDP, etc. + * + * @sa tport_tbind() * * @TAGS * TPTAG_LOG(), TPTAG_DUMP(), tags used with tport_set_params(), especially @@ -2985,6 +2991,7 @@ void tport_deliver(tport_t *self, ref = tport_incref(self); + if (self->tp_pri->pri_vtable->vtp_deliver) { self->tp_pri->pri_vtable->vtp_deliver(self, msg, now); } @@ -3405,28 +3412,28 @@ int tport_send_msg(tport_t *self, msg_t *msg, if (tport_is_connection_oriented(self)) { iov[i].mv_len -= (su_ioveclen_t)(n - total); iov[i].mv_base = (char *)iov[i].mv_base + (n - total); - if (tport_queue_rest(self, msg, &iov[i], iovused - i) >= 0) + if (tport_queue_rest(self, msg, &iov[i], iovused - i) < 0) + return tport_send_fatal(self, msg, tpn, "tport_queue_rest"); + else return 0; } else { char const *comp = tpn->tpn_comp; - SU_DEBUG_1(("tport(%p): send truncated for %s/%s:%s%s%s\n", - (void *)self, tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, + SU_DEBUG_1(("%s(%p): send truncated for %s/%s:%s%s%s\n", + "tport_vsend", (void *)self, tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, comp ? ";comp=" : "", comp ? comp : "")); - su_seterrno(EIO); + msg_set_errno(msg, EIO); + return /* tport_send_fatal(self, msg, tpn, "tport_send") */ -1; } - - return -1; } + total += iov[i].mv_len; } /* We have sent a complete message */ - - self->tp_slogged = NULL; - self->tp_stats.sent_msgs ++; + tport_sent_message(self, msg, 0); if (!tport_is_secondary(self)) return 0; @@ -3465,9 +3472,9 @@ ssize_t tport_vsend(tport_t *self, return 0; if (n == -1) - return tport_send_error(self, msg, tpn); + return tport_send_error(self, msg, tpn, "tport_vsend"); - self->tp_stats.sent_bytes += n; + tport_sent_bytes(self, n, n); /* Sigcomp will decrease on_line accodingly */ if (n > 0 && self->tp_master->mr_dump_file) tport_dump_iovec(self, msg, n, iov, iovused, "sent", "to"); @@ -3481,8 +3488,8 @@ ssize_t tport_vsend(tport_t *self, if (tpn == NULL || tport_is_connection_oriented(self)) tpn = self->tp_name; - SU_DEBUG_7(("tport_vsend(%p): "MOD_ZU" bytes of "MOD_ZU" to %s/%s:%s%s\n", - (void *)self, n, m, tpn->tpn_proto, tpn->tpn_host, + SU_DEBUG_7(("%s(%p): "MOD_ZU" bytes of "MOD_ZU" to %s/%s:%s%s\n", + "tport_vsend", (void *)self, n, m, tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, (ai->ai_flags & TP_AI_COMPRESSED) ? ";comp=sigcomp" : "")); } @@ -3491,45 +3498,56 @@ ssize_t tport_vsend(tport_t *self, } static -int tport_send_error(tport_t *self, msg_t *msg, - tp_name_t const *tpn) +int tport_send_error(tport_t *self, msg_t *msg, tp_name_t const *tpn, + char const *who) { int error = su_errno(); - su_addrinfo_t *ai = msg_addrinfo(msg); - char const *comp = (ai->ai_flags & TP_AI_COMPRESSED) ? ";comp=sigcomp" : ""; if (error == EPIPE) { /*Xyzzy*/ } if (su_is_blocking(error)) { - SU_DEBUG_5(("tport_vsend(%p): %s with (s=%d %s/%s:%s%s)\n", - (void *)self, "EAGAIN", (int)self->tp_socket, + su_addrinfo_t *ai = msg_addrinfo(msg); + char const *comp = (ai->ai_flags & TP_AI_COMPRESSED) ? ";comp=sigcomp" : ""; + SU_DEBUG_5(("%s(%p): %s with (s=%d %s/%s:%s%s)\n", + who, (void *)self, "EAGAIN", (int)self->tp_socket, tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, comp)); return 0; } msg_set_errno(msg, error); + return tport_send_fatal(self, msg, tpn, who); +} + +static +int tport_send_fatal(tport_t *self, msg_t *msg, tp_name_t const *tpn, + char const *who) +{ + su_addrinfo_t *ai = msg_addrinfo(msg); + char const *comp = (ai->ai_flags & TP_AI_COMPRESSED) ? ";comp=sigcomp" : ""; + + int error = msg_errno(msg); + if (self->tp_addrinfo->ai_family == AF_INET) { - SU_DEBUG_3(("tport_vsend(%p): %s with (s=%d %s/%s:%s%s)\n", - (void *)self, su_strerror(error), (int)self->tp_socket, + SU_DEBUG_3(("%s(%p): %s with (s=%d %s/%s:%s%s)\n", + who, (void *)self, su_strerror(error), (int)self->tp_socket, tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, comp)); } #if SU_HAVE_IN6 else if (self->tp_addrinfo->ai_family == AF_INET6) { su_sockaddr_t const *su = (su_sockaddr_t const *)ai->ai_addr; - SU_DEBUG_3(("tport_vsend(%p): %s with " - "(s=%d, IP6=%s/%s:%s%s (scope=%i) addrlen=%u)\n", - (void *)self, su_strerror(error), (int)self->tp_socket, + SU_DEBUG_3(("%s(%p): %s with (s=%d, IP6=%s/%s:%s%s" + " (scope=%i) addrlen=%u)\n", + who, (void *)self, su_strerror(error), (int)self->tp_socket, tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, comp, su->su_scope_id, (unsigned)ai->ai_addrlen)); } #endif else { - SU_DEBUG_3(("\ttport_vsend(%p): %s with " - "(s=%d, AF=%u addrlen=%u)%s\n", - (void *)self, su_strerror(error), + SU_DEBUG_3(("%s(%p): %s with (s=%d, AF=%u addrlen=%u)%s\n", + who, (void *)self, su_strerror(error), (int)self->tp_socket, ai->ai_family, (unsigned)ai->ai_addrlen, comp)); } @@ -3856,9 +3874,8 @@ void tport_send_queue(tport_t *self) /* We have sent a complete message */ self->tp_queue[qhead] = NULL; + tport_sent_message(self, msg, 0); msg_destroy(msg); - self->tp_stats.sent_msgs++; - self->tp_slogged = NULL; qhead = (qhead + 1) % N; } @@ -4403,7 +4420,7 @@ tport_t *tport_by_name(tport_t const *self, tp_name_t const *tpn) su->su_len = sulen = (socklen_t) sizeof (struct sockaddr_in6); su->su_family = AF_INET6; } - else if (host_is_ip_address(host)) { + else if (host_is_ip6_address(host)) { su->su_len = sulen = (socklen_t) sizeof (struct sockaddr_in6); su->su_family = AF_INET6; } @@ -4613,27 +4630,10 @@ int tport_name_by_url(su_home_t *home, /** Check if transport named is already resolved */ int tport_name_is_resolved(tp_name_t const *tpn) { - size_t n; - if (!tpn->tpn_host) return 0; - - if (tpn->tpn_host[0] == '[') - return 1; - n = strspn(tpn->tpn_host, ".0123456789"); - - if (tpn->tpn_host[n] == '\0') - return 1; - - if (strchr(tpn->tpn_host, ':')) { - n = strspn(tpn->tpn_host, ":0123456789abcdefABCDEF"); - - if (tpn->tpn_host[n] == '\0') - return 1; - } - - return 0; + return host_is_ip_address(tpn->tpn_host); } /** Duplicate name. @@ -4742,3 +4742,79 @@ char *tport_hostport(char buf[], isize_t bufsize, return buf; } + +/** @internal Update receive statistics. */ +void tport_recv_bytes(tport_t *self, ssize_t bytes, ssize_t on_line) +{ + self->tp_stats.recv_bytes += bytes; + self->tp_stats.recv_on_line += on_line; + + if (self != self->tp_pri->pri_primary) { + self = self->tp_pri->pri_primary; + self->tp_stats.recv_bytes += bytes; + self->tp_stats.recv_on_line += on_line; + } + self = self->tp_master->mr_master; + self->tp_stats.recv_bytes += bytes; + self->tp_stats.recv_on_line += on_line; +} + +/** @internal Update message-based receive statistics. */ +void tport_recv_message(tport_t *self, msg_t *msg, int error) +{ + error = error != 0; + + self->tp_stats.recv_msgs++; + self->tp_stats.recv_errors += error; + + if (self != self->tp_pri->pri_primary) { + self = self->tp_pri->pri_primary; + self->tp_stats.recv_msgs++; + self->tp_stats.recv_errors += error; + } + + self = self->tp_master->mr_master; + + self->tp_stats.recv_msgs++; + self->tp_stats.recv_errors += error; +} + +/** @internal Update send statistics. */ +void tport_sent_bytes(tport_t *self, ssize_t bytes, ssize_t on_line) +{ + self->tp_stats.sent_bytes += bytes; + self->tp_stats.sent_on_line += on_line; + + if (self != self->tp_pri->pri_primary) { + self = self->tp_pri->pri_primary; + self->tp_stats.sent_bytes += bytes; + self->tp_stats.sent_on_line += on_line; + } + + self = self->tp_master->mr_master; + self->tp_stats.sent_bytes += bytes; + self->tp_stats.sent_on_line += on_line; +} + +/** @internal Update message-based send statistics. */ +void tport_sent_message(tport_t *self, msg_t *msg, int error) +{ + self->tp_slogged = NULL; + + error = error != 0; + + self->tp_stats.sent_msgs++; + self->tp_stats.sent_errors += error; + + if (self != self->tp_pri->pri_primary) { + self = self->tp_pri->pri_primary; + self->tp_stats.sent_msgs++; + self->tp_stats.sent_errors += error; + } + + self = self->tp_master->mr_master; + + self->tp_stats.sent_msgs++; + self->tp_stats.sent_errors += error; + +} diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_internal.h b/libs/sofia-sip/libsofia-sip-ua/tport/tport_internal.h index a17e485464..cf3b2205d0 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_internal.h +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_internal.h @@ -221,8 +221,8 @@ struct tport_s { /* ==== Statistics ===================================================== */ struct { - uint64_t sent_bytes, sent_on_line, recv_bytes, recv_on_line; - uint64_t sent_msgs, recv_msgs; + uint64_t sent_msgs, sent_errors, sent_bytes, sent_on_line; + uint64_t recv_msgs, recv_errors, recv_bytes, recv_on_line; } tp_stats; }; @@ -528,6 +528,12 @@ int tport_recv_stun_dgram(tport_t const *self, msg_t **in_out_msg, int tport_stun_server_add_socket(tport_t *tp); int tport_stun_server_remove_socket(tport_t *tp); +void tport_recv_bytes(tport_t *self, ssize_t bytes, ssize_t on_line); +void tport_recv_message(tport_t *self, msg_t *msg, int error); + +void tport_sent_bytes(tport_t *self, ssize_t bytes, ssize_t on_line); +void tport_sent_message(tport_t *self, msg_t *msg, int error); + /* ---------------------------------------------------------------------- */ /* Compressor plugin */ extern tport_comp_vtable_t const *tport_comp_vtable; diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_stub_sigcomp.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_stub_sigcomp.c index befab5d3ce..791cd39ca7 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_stub_sigcomp.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_stub_sigcomp.c @@ -34,6 +34,7 @@ #include "tport_internal.h" #include +#include tport_comp_vtable_t const *tport_comp_vtable = NULL; diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_sctp.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_sctp.c index 8c06dee251..5c8f6bdeaa 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_sctp.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_sctp.c @@ -242,6 +242,8 @@ int tport_recv_sctp(tport_t *self) return 0; /* End of stream */ } + tport_recv_bytes(self, n, n); + veclen = tport_recv_iovec(self, &self->tp_msg, iovec, N, 0); if (veclen < 0) return -1; diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tcp.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tcp.c index 52ce971675..26ccf4661a 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tcp.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tcp.c @@ -281,6 +281,8 @@ int tport_recv_stream(tport_t *self) N -= n, self->tp_ping += n; + tport_recv_bytes(self, n, n); + if (N == 0) { /* outbound-10 section 3.5.1 - send pong */ if (self->tp_ping >= 4) @@ -305,6 +307,8 @@ int tport_recv_stream(tport_t *self) assert(n <= N); + tport_recv_bytes(self, n, n); + /* Check if message contains only whitespace */ /* This can happen if multiple PINGs are received at once */ if (initial) { diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c index 2f9860dac6..d4abd7c8c8 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c @@ -46,6 +46,7 @@ #include #include #include +#include /* ---------------------------------------------------------------------- */ /* TLS */ diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_udp.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_udp.c index db5288369f..74e15b38a3 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_udp.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_udp.c @@ -293,6 +293,8 @@ int tport_recv_dgram(tport_t *self) return 0; } + tport_recv_bytes(self, n, n); + SU_CANONIZE_SOCKADDR(from); if (self->tp_master->mr_dump_file) diff --git a/libs/sofia-sip/libsofia-sip-ua/url/sofia-sip/url.h b/libs/sofia-sip/libsofia-sip-ua/url/sofia-sip/url.h index 35fcd32168..ef4a339853 100644 --- a/libs/sofia-sip/libsofia-sip-ua/url/sofia-sip/url.h +++ b/libs/sofia-sip/libsofia-sip-ua/url/sofia-sip/url.h @@ -204,7 +204,7 @@ SOFIAPUBFUN char *url_unescape(char *d, char const *s); * @endcode */ #define URL_INIT_AS(type) \ -{ { 0 }, url_##type, 0, url_##type != url_any ? #type : "*" } + { "\0", url_##type, 0, url_##type != url_any ? #type : "*" } /** Init a url structure as given type */ SOFIAPUBFUN void url_init(url_t *url, enum url_type_e type); diff --git a/libs/sofia-sip/libsofia-sip-ua/url/url.c b/libs/sofia-sip/libsofia-sip-ua/url/url.c index a1e3f54693..76b371b999 100644 --- a/libs/sofia-sip/libsofia-sip-ua/url/url.c +++ b/libs/sofia-sip/libsofia-sip-ua/url/url.c @@ -802,8 +802,8 @@ int url_d(url_t *url, char *s) if (s && !url_canonize(s, s, SIZE_MAX, /* Allow all URI characters but ? */ /* Allow unescaped /;?@, - but do not convert */ - (unsigned)(SYN33('/') | SYN33(';') | SYN33('=') | SYN33('@') | - SYN33(',')), + SYN33('/') | SYN33(';') | SYN33('=') | SYN33('@') | + SYN33(','), /* Convert escaped :&+$ to unescaped */ ":&+$")) return -1; @@ -812,7 +812,7 @@ int url_d(url_t *url, char *s) if (s && !url_canonize(s, s, SIZE_MAX, /* Allow all URI characters but ? */ /* Allow unescaped ;=@, - but do not convert */ - (unsigned)(SYN33(';') | SYN33('=') | SYN33('@') | SYN33(',')), + SYN33(';') | SYN33('=') | SYN33('@') | SYN33(','), /* Convert escaped /:&+$ to unescaped */ "/:&+$")) return -1; diff --git a/libs/sofia-sip/rules/sofia.am b/libs/sofia-sip/rules/sofia.am index 771052c799..b9061ba93c 100644 --- a/libs/sofia-sip/rules/sofia.am +++ b/libs/sofia-sip/rules/sofia.am @@ -1,6 +1,9 @@ # common Makefile targets for libsofia-sip-ua(-glib) modules # ---------------------------------------------------------- +sofiasrcdir = ${top_srcdir}/libsofia-sip-ua +sofiabuilddir = ${top_builddir}/libsofia-sip-ua + AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(SOFIA_CFLAGS) $(openssl_CFLAGS) SOFIA_COVERAGE = $(COVERAGE_FLAGS) @@ -19,7 +22,7 @@ clean-built-sources: # rules for building tag files -TAG_AWK=$(top_srcdir)/libsofia-sip-ua/su/tag_dll.awk +TAG_AWK=${sofiasrcdir}/su/tag_dll.awk *_tag_ref.c: $(TAG_AWK) @@ -36,25 +39,25 @@ _tag.c_tag_ref.c: cd $(@D) && $(MAKE) $(@F) INTERNAL_INCLUDES = \ - -I$(srcdir)/../features -I../features \ - -I$(srcdir)/../ipt -I../ipt \ - -I$(srcdir)/../iptsec -I../iptsec \ - -I$(srcdir)/../bnf -I../bnf \ - -I$(srcdir)/../http -I../http \ - -I$(srcdir)/../msg -I../msg \ - -I$(srcdir)/../nth -I../nth \ - -I$(srcdir)/../nta -I../nta \ - -I$(srcdir)/../nea -I../nea \ - -I$(srcdir)/../nua -I../nua \ - -I$(srcdir)/../soa -I../soa \ - -I$(srcdir)/../sdp -I../sdp \ - -I$(srcdir)/../sip -I../sip \ - -I$(srcdir)/../soa -I../soa \ - -I$(srcdir)/../sresolv -I../sresolv \ - -I$(srcdir)/../tport -I../tport \ - -I$(srcdir)/../stun -I../stun \ - -I$(srcdir)/../url -I../url \ - -I$(srcdir)/../su -I../su + -I${sofiasrcdir}/features -I${sofiabuilddir}/features \ + -I${sofiasrcdir}/ipt -I${sofiabuilddir}/ipt \ + -I${sofiasrcdir}/iptsec -I${sofiabuilddir}/iptsec \ + -I${sofiasrcdir}/bnf -I${sofiabuilddir}/bnf \ + -I${sofiasrcdir}/http -I${sofiabuilddir}/http \ + -I${sofiasrcdir}/msg -I${sofiabuilddir}/msg \ + -I${sofiasrcdir}/nth -I${sofiabuilddir}/nth \ + -I${sofiasrcdir}/nta -I${sofiabuilddir}/nta \ + -I${sofiasrcdir}/nea -I${sofiabuilddir}/nea \ + -I${sofiasrcdir}/nua -I${sofiabuilddir}/nua \ + -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ + -I${sofiasrcdir}/sdp -I${sofiabuilddir}/sdp \ + -I${sofiasrcdir}/sip -I${sofiabuilddir}/sip \ + -I${sofiasrcdir}/soa -I${sofiabuilddir}/soa \ + -I${sofiasrcdir}/sresolv -I${sofiabuilddir}/sresolv \ + -I${sofiasrcdir}/tport -I${sofiabuilddir}/tport \ + -I${sofiasrcdir}/stun -I${sofiabuilddir}/stun \ + -I${sofiasrcdir}/url -I${sofiabuilddir}/url \ + -I${sofiasrcdir}/su -I${sofiabuilddir}/su PHONY = built-sources clean-built-sources @@ -63,4 +66,3 @@ include $(top_srcdir)/rules/valcheck.am if HAVE_LCOV include $(top_srcdir)/rules/lcov.am endif - diff --git a/libs/sofia-sip/tests/Makefile.am b/libs/sofia-sip/tests/Makefile.am new file mode 100644 index 0000000000..fedc6333d5 --- /dev/null +++ b/libs/sofia-sip/tests/Makefile.am @@ -0,0 +1,28 @@ +# +# Tests using check +# + +EXTRA_DIST = check_nua.c + +TESTS = +check_PROGRAMS = + +include $(top_srcdir)/rules/sofia.am + +INCLUDES = ${INTERNAL_INCLUDES} + +AM_CFLAGS += @CHECK_CFLAGS@ + +if HAVE_CHECK +TESTS += check_sofia +check_PROGRAMS += check_sofia + +check_sofia_SOURCES = check_sofia.c check_sofia.h \ + suite_for_nua.c + +check_sofia_LDADD = \ + ${sofiabuilddir}/nua/libtestnua.la \ + ${sofiabuilddir}/nua/libtestproxy.la \ + ${sofiabuilddir}/nua/libtestnat.la \ + ${sofiabuilddir}/libsofia-sip-ua.la @CHECK_LIBS@ +endif diff --git a/libs/sofia-sip/tests/check_sofia.c b/libs/sofia-sip/tests/check_sofia.c new file mode 100644 index 0000000000..f8fd707216 --- /dev/null +++ b/libs/sofia-sip/tests/check_sofia.c @@ -0,0 +1,62 @@ +/* + * This file is part of the Sofia-SIP package + * + * Copyright (C) 2007 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_sofia.c + * + * @brief Check-driven tester for Sofia SIP User Agent library + * + * @author Pekka Pessi + * + * @copyright (C) 2007 Nokia Corporation. + */ + +#include "config.h" + +#include "check_sofia.h" + +#include + +/* Globals used by */ +int tstflags; +char const name[] = "check_sofia"; + +int main(int argc, char *argv[]) +{ + int failed = 0; + + Suite *suite; + SRunner *runner; + + suite = suite_for_nua(); + runner = srunner_create(suite); + + srunner_set_xml(runner, "/tmp/result.xml"); + srunner_run_all(runner, CK_NORMAL); + + failed = srunner_ntests_failed(runner); + srunner_free(runner); + + exit(failed ? EXIT_FAILURE : EXIT_SUCCESS); +} + diff --git a/libs/sofia-sip/tests/check_sofia.h b/libs/sofia-sip/tests/check_sofia.h new file mode 100644 index 0000000000..d641347f79 --- /dev/null +++ b/libs/sofia-sip/tests/check_sofia.h @@ -0,0 +1,7 @@ +#ifndef CHECK_SOFIA_H + +#include +Suite *suite_for_nua(void); + +#endif + diff --git a/libs/sofia-sip/tests/suite_for_nua.c b/libs/sofia-sip/tests/suite_for_nua.c new file mode 100644 index 0000000000..d0655a2a92 --- /dev/null +++ b/libs/sofia-sip/tests/suite_for_nua.c @@ -0,0 +1,188 @@ +/* + * This file is part of the Sofia-SIP package + * + * Copyright (C) 2007 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_sofia.c + * + * @brief Check-driven tester for Sofia SIP User Agent library + * + * @author Pekka Pessi + * + * @copyright (C) 2007 Nokia Corporation. + */ + +#include "config.h" + +#include "test_nua.h" +#include "check_sofia.h" + +int print_headings = 0; +struct context ctx[1] = {{{ SU_HOME_INIT(ctx) }}}; + +SOFIAPUBVAR su_log_t nua_log[]; +SOFIAPUBVAR su_log_t soa_log[]; +SOFIAPUBVAR su_log_t nea_log[]; +SOFIAPUBVAR su_log_t nta_log[]; +SOFIAPUBVAR su_log_t tport_log[]; +SOFIAPUBVAR su_log_t su_log_default[]; + +static void init_context(void) +{ + int level = 1; + + su_init(); + memset(ctx, 0, sizeof ctx); + su_home_init(ctx->home); + endpoint_init(ctx, &ctx->a, 'a'); + endpoint_init(ctx, &ctx->b, 'b'); + endpoint_init(ctx, &ctx->c, 'c'); + + su_log_soft_set_level(nua_log, level); + su_log_soft_set_level(soa_log, level); + su_log_soft_set_level(su_log_default, level); + su_log_soft_set_level(nea_log, level); + su_log_soft_set_level(nta_log, level); + su_log_soft_set_level(tport_log, level); +} + +static void clean_context(void) +{ + test_deinit(ctx); + su_home_deinit(ctx->home); + memset(ctx, 0, sizeof ctx); + su_deinit(); +} + +/* Each testcase is run in different process */ + +START_TEST(check_api) { fail_if(test_nua_api_errors(ctx)); } END_TEST +START_TEST(check_tag_filter) { fail_if(test_tag_filter()); } END_TEST +START_TEST(check_params) { fail_if(test_nua_params(ctx)); } END_TEST +START_TEST(check_destroy) { fail_if(test_nua_destroy(ctx)); } END_TEST +START_TEST(check_stack_errors) { fail_if(test_stack_errors(ctx)); } END_TEST + +START_TEST(without_proxy) +{ + fail_if(test_nua_init(ctx, 0, NULL, 0, TAG_END())); + fail_if(test_register(ctx)); + fail_if(test_connectivity(ctx)); + fail_if(test_basic_call(ctx)); + fail_if(test_rejects(ctx)); + fail_if(test_call_cancel(ctx)); + fail_if(test_call_destroy(ctx)); + fail_if(test_early_bye(ctx)); + fail_if(test_offer_answer(ctx)); + fail_if(test_reinvites(ctx)); + fail_if(test_session_timer(ctx)); + fail_if(test_refer(ctx)); + fail_if(test_100rel(ctx)); + fail_if(test_simple(ctx)); + fail_if(test_events(ctx)); + fail_if(test_extension(ctx)); + fail_if(test_unregister(ctx)); + fail_if(test_deinit(ctx)); +} +END_TEST + +START_TEST(with_proxy) +{ + fail_if(test_nua_init(ctx, 1, NULL, 0, TAG_END())); + fail_if(test_register(ctx)); + fail_if(test_connectivity(ctx)); + fail_if(test_basic_call(ctx)); + fail_if(test_rejects(ctx)); + fail_if(test_call_cancel(ctx)); + fail_if(test_call_destroy(ctx)); + fail_if(test_early_bye(ctx)); + fail_if(test_offer_answer(ctx)); + fail_if(test_reinvites(ctx)); + fail_if(test_session_timer(ctx)); + fail_if(test_refer(ctx)); + fail_if(test_100rel(ctx)); + fail_if(test_simple(ctx)); + fail_if(test_events(ctx)); + fail_if(test_extension(ctx)); + fail_if(test_unregister(ctx)); + fail_if(test_deinit(ctx)); +} +END_TEST + +START_TEST(with_proxy_and_nat) +{ + fail_if(test_nua_init(ctx, 1, NULL, 1, TAG_END())); + fail_if(test_register(ctx)); + fail_if(test_connectivity(ctx)); + fail_if(test_nat_timeout(ctx)); + fail_if(test_basic_call(ctx)); + fail_if(test_rejects(ctx)); + fail_if(test_call_cancel(ctx)); + fail_if(test_call_destroy(ctx)); + fail_if(test_early_bye(ctx)); + fail_if(test_offer_answer(ctx)); + fail_if(test_reinvites(ctx)); + fail_if(test_session_timer(ctx)); + fail_if(test_refer(ctx)); + fail_if(test_100rel(ctx)); + fail_if(test_simple(ctx)); + fail_if(test_events(ctx)); + fail_if(test_extension(ctx)); + fail_if(test_unregister(ctx)); + fail_if(test_deinit(ctx)); +} +END_TEST + +Suite *suite_for_nua(void) +{ + Suite *suite = suite_create("nua"); + TCase *tc; + + tc = tcase_create("api"); + tcase_add_unchecked_fixture(tc, init_context, clean_context); + tcase_add_test(tc, check_api); + tcase_add_test(tc, check_tag_filter); + tcase_add_test(tc, check_params); + tcase_add_test(tc, check_destroy); + tcase_add_test(tc, check_stack_errors); + tcase_set_timeout(tc, 5); + suite_add_tcase(suite, tc); + + tc = tcase_create("without-proxy"); + tcase_add_unchecked_fixture(tc, init_context, clean_context); + tcase_add_test(tc, without_proxy); + tcase_set_timeout(tc, 60); + suite_add_tcase(suite, tc); + + tc = tcase_create("with-proxy"); + tcase_add_unchecked_fixture(tc, init_context, clean_context); + tcase_add_test(tc, with_proxy); + tcase_set_timeout(tc, 120); + suite_add_tcase(suite, tc); + + tc = tcase_create("with-proxy-and-nat"); + tcase_add_unchecked_fixture(tc, init_context, clean_context); + tcase_add_test(tc, with_proxy_and_nat); + tcase_set_timeout(tc, 120); + suite_add_tcase(suite, tc); + + return suite; +} diff --git a/libs/sofia-sip/utils/Makefile.am b/libs/sofia-sip/utils/Makefile.am index c421299a2a..124a17e34a 100644 --- a/libs/sofia-sip/utils/Makefile.am +++ b/libs/sofia-sip/utils/Makefile.am @@ -10,31 +10,9 @@ # ---------------------------------------------------------------------- # Header paths -sofiasrc=$(top_srcdir)/libsofia-sip-ua -sofiabld=$(top_builddir)/libsofia-sip-ua +include $(top_srcdir)/rules/sofia.am -INCLUDES = -I$(sofiasrc)/features -I$(sofiabld)/features \ - -I$(sofiasrc)/ipt -I$(sofiabld)/ipt \ - -I$(sofiasrc)/iptsec -I$(sofiabld)/iptsec \ - -I$(sofiasrc)/bnf -I$(sofiabld)/bnf \ - -I$(sofiasrc)/http -I$(sofiabld)/http \ - -I$(sofiasrc)/msg -I$(sofiabld)/msg \ - -I$(sofiasrc)/nth -I$(sofiabld)/nth \ - -I$(sofiasrc)/nta -I$(sofiabld)/nta \ - -I$(sofiasrc)/nea -I$(sofiabld)/nea \ - -I$(sofiasrc)/nua -I$(sofiabld)/nua \ - -I$(sofiasrc)/soa -I$(sofiabld)/soa \ - -I$(sofiasrc)/sdp -I$(sofiabld)/sdp \ - -I$(sofiasrc)/sip -I$(sofiabld)/sip \ - -I$(sofiasrc)/soa -I$(sofiabld)/soa \ - -I$(sofiasrc)/sresolv -I$(sofiabld)/sresolv \ - -I$(sofiasrc)/tport -I$(sofiabld)/tport \ - -I$(sofiasrc)/stun -I$(sofiabld)/stun \ - -I$(sofiasrc)/url -I$(sofiabld)/url \ - -I$(sofiasrc)/su -I$(sofiabld)/su - - -AM_CFLAGS = $(SOFIA_CFLAGS) +INCLUDES = ${INTERNAL_INCLUDES} # ---------------------------------------------------------------------- # Build targets