From 587408b8ce66580e3edc6e7896699f53d406628a Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Wed, 11 Feb 2009 17:08:41 +0000 Subject: [PATCH] Fri Jan 16 13:37:43 CST 2009 Pekka Pessi * nua: fixed problem handling re-SUBSCRIBE when it creates new dialog git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@11836 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- libs/sofia-sip/.update | 2 +- .../sofia-sip/libsofia-sip-ua/nua/check_nua.c | 6 + .../sofia-sip/libsofia-sip-ua/nua/check_nua.h | 1 + .../libsofia-sip-ua/nua/check_register.c | 6 +- .../libsofia-sip-ua/nua/check_session.c | 8 +- .../sofia-sip/libsofia-sip-ua/nua/nua_stack.c | 135 ++++++++---------- libs/sofia-sip/libsofia-sip-ua/nua/test_s2.c | 78 ++++++++-- libs/sofia-sip/libsofia-sip-ua/nua/test_s2.h | 13 +- 8 files changed, 152 insertions(+), 97 deletions(-) diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index 4f2f64fd5d..dcb1fe5f5d 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Wed Feb 11 11:07:52 CST 2009 +Wed Feb 11 11:08:29 CST 2009 diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/check_nua.c b/libs/sofia-sip/libsofia-sip-ua/nua/check_nua.c index 9ea08629a5..b46f8a34d1 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/check_nua.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/check_nua.c @@ -43,6 +43,8 @@ #include #endif +#include "test_s2.h" + static char const * const default_patterns[] = { "*", NULL }; static char const * const *test_patterns = default_patterns; @@ -80,6 +82,10 @@ int main(int argc, char *argv[]) Suite *suite = suite_create("Unit tests for Sofia-SIP UA Engine"); SRunner *runner; + s2_tester = "check_nua"; + if (getenv("CHECK_NUA_VERBOSE")) + s2_start_stop = strtoul(getenv("CHECK_NUA_VERBOSE"), NULL, 10); + if (getenv("CHECK_NUA_CASES")) { size_t i; char *s, **patterns; diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/check_nua.h b/libs/sofia-sip/libsofia-sip-ua/nua/check_nua.h index d58680f724..0537aebaaa 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/check_nua.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/check_nua.h @@ -10,6 +10,7 @@ void check_nua_tcase_add_test(TCase *, TFun, char const *name); void check_session_cases(Suite *suite); void check_register_cases(Suite *suite); +void check_simple_cases(Suite *suite); #endif diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/check_register.c b/libs/sofia-sip/libsofia-sip-ua/nua/check_register.c index 8ca0bb2aff..e6f6b6de27 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/check_register.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/check_register.c @@ -54,12 +54,13 @@ static nua_t *nua; static void register_setup(void) { - nua = s2_nua_setup(TAG_END()); + nua = s2_nua_setup("register", TAG_END()); } static void register_pingpong_setup(void) { - nua = s2_nua_setup(TPTAG_PINGPONG(20000), + nua = s2_nua_setup("register with pingpong", + TPTAG_PINGPONG(20000), TPTAG_KEEPALIVE(10000), TAG_END()); tport_set_params(s2->tcp.tport, TPTAG_PONG2PING(1), TAG_END()); @@ -68,6 +69,7 @@ static void register_pingpong_setup(void) static void register_teardown(void) { + s2_teardown_started("register"); nua_shutdown(nua); fail_unless(s2_check_event(nua_r_shutdown, 200)); s2_nua_teardown(); diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/check_session.c b/libs/sofia-sip/libsofia-sip-ua/nua/check_session.c index 06e1bdba77..a0e9af1b52 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/check_session.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/check_session.c @@ -63,9 +63,8 @@ static struct dialog *dialog = NULL; static void call_setup(void) { - s2_case("0.1.1", "Setup for Call Tests", ""); - - nua = s2_nua_setup(SIPTAG_ORGANIZATION_STR("Pussy Galore's Flying Circus"), + nua = s2_nua_setup("call", + SIPTAG_ORGANIZATION_STR("Pussy Galore's Flying Circus"), NUTAG_OUTBOUND("no-options-keepalive, no-validate"), TAG_END()); @@ -85,7 +84,7 @@ static void call_setup(void) static void call_teardown(void) { - s2_case("0.1.2", "Teardown Call Test Setup", ""); + s2_teardown_started("call"); mark_point(); @@ -3078,6 +3077,7 @@ static void options_setup(void) static void options_teardown(void) { + s2_teardown_started("options"); call_teardown(); } 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 53ee3726f5..f7ed0cf86a 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c @@ -1973,8 +1973,7 @@ int nua_base_server_report(nua_server_request_t *sr, tagi_t const *tags) static void nua_client_request_destroy(nua_client_request_t *cr); static int nua_client_init_request0(nua_client_request_t *cr); static int nua_client_request_try(nua_client_request_t *cr); -static int nua_client_request_sendmsg(nua_client_request_t *cr, - msg_t *msg, sip_t *sip); +static int nua_client_request_sendmsg(nua_client_request_t *cr); static void nua_client_restart_after(su_root_magic_t *magic, su_timer_t *timer, nua_client_request_t *cr); @@ -2416,23 +2415,6 @@ int nua_client_init_request0(nua_client_request_t *cr) (sip_header_t *)sip->sip_from) < 0) { return nua_client_return(cr, NUA_ERROR_AT(__FILE__, __LINE__), msg); } - - if (cr->cr_dialog) { - ds->ds_leg = nta_leg_tcreate(nua->nua_nta, - nua_stack_process_request, nh, - SIPTAG_CALL_ID(sip->sip_call_id), - SIPTAG_FROM(sip->sip_from), - SIPTAG_TO(sip->sip_to), - SIPTAG_CSEQ(sip->sip_cseq), - TAG_END()); - if (!ds->ds_leg) - return nua_client_return(cr, NUA_ERROR_AT(__FILE__, __LINE__), msg); - - if (!sip->sip_from->a_tag && - sip_from_tag(msg_home(msg), sip->sip_from, - nta_leg_tag(ds->ds_leg, NULL)) < 0) - return nua_client_return(cr, NUA_ERROR_AT(__FILE__, __LINE__), msg); - } } else { if (ds->ds_route) @@ -2540,15 +2522,17 @@ int nua_client_resend_request(nua_client_request_t *cr, if (nua_client_request_queue(cr)) return 0; + if (nua_dialog_is_reporting(cr->cr_owner->nh_ds)) return 0; + return nua_client_request_try(cr); } return 0; } -/** Create a request message and send it. +/** Send a request message. * * If an error occurs, send error event to the application. * @@ -2558,26 +2542,11 @@ int nua_client_resend_request(nua_client_request_t *cr, static int nua_client_request_try(nua_client_request_t *cr) { - int error = -1; - msg_t *msg = msg_copy(cr->cr_msg); - sip_t *sip = sip_object(msg); - - cr->cr_answer_recv = 0, cr->cr_offer_sent = 0; - cr->cr_offer_recv = 0, cr->cr_answer_sent = 0; - - if (msg && sip) { - error = nua_client_request_sendmsg(cr, msg, sip); - if (!error) - return 0; - - if (error == -1) - msg_destroy(msg); - } + int error = nua_client_request_sendmsg(cr); if (error < 0) error = nua_client_response(cr, NUA_ERROR_AT(__FILE__, __LINE__), NULL); - assert(error > 0); return error; } @@ -2585,13 +2554,10 @@ int nua_client_request_try(nua_client_request_t *cr) * * @retval 0 if request is pending * @retval >=1 if error event has been sent - * @retval -1 if error occurred but event has not been sent, - and @a msg has not been destroyed - * @retval -2 if error occurred, event has not been sent, - * but @a msg has been destroyed + * @retval < 0 if no error event has been sent */ static -int nua_client_request_sendmsg(nua_client_request_t *cr, msg_t *msg, sip_t *sip) +int nua_client_request_sendmsg(nua_client_request_t *cr) { nua_handle_t *nh = cr->cr_owner; nua_dialog_state_t *ds = nh->nh_ds; @@ -2599,9 +2565,36 @@ int nua_client_request_sendmsg(nua_client_request_t *cr, msg_t *msg, sip_t *sip) char const *name = cr->cr_method_name; url_string_t const *url = (url_string_t *)cr->cr_target; nta_leg_t *leg; + msg_t *msg; + sip_t *sip; + int error; assert(cr->cr_orq == NULL); + cr->cr_offer_sent = cr->cr_answer_recv = 0; + cr->cr_offer_recv = cr->cr_answer_sent = 0; + + if (!ds->ds_leg && cr->cr_dialog) { + ds->ds_leg = nta_leg_tcreate(nh->nh_nua->nua_nta, + nua_stack_process_request, nh, + SIPTAG_CALL_ID(cr->cr_sip->sip_call_id), + SIPTAG_FROM(cr->cr_sip->sip_from), + SIPTAG_TO(cr->cr_sip->sip_to), + SIPTAG_CSEQ(cr->cr_sip->sip_cseq), + TAG_END()); + if (!ds->ds_leg) + return -1; + } + + if (cr->cr_sip->sip_from && ds->ds_leg) { + if (cr->cr_sip->sip_from->a_tag == NULL) { + if (sip_from_tag(msg_home(cr->cr_msg), cr->cr_sip->sip_from, + nta_leg_tag(ds->ds_leg, NULL)) < 0) { + return -1; + } + } + } + cr->cr_retry_count++; if (ds->ds_leg) @@ -2609,6 +2602,11 @@ int nua_client_request_sendmsg(nua_client_request_t *cr, msg_t *msg, sip_t *sip) else leg = nh->nh_nua->nua_dhandle->nh_ds->ds_leg; /* Default leg */ + msg = msg_copy(cr->cr_msg), sip = sip_object(msg); + + if (msg == NULL) + return -1; + if (nua_dialog_is_established(ds)) { while (sip->sip_route) sip_route_remove(msg, sip); @@ -2639,8 +2637,10 @@ int nua_client_request_sendmsg(nua_client_request_t *cr, msg_t *msg, sip_t *sip) * generated based on the dialog information and added to the request. * If the dialog has a route, it is added to the request, too. */ - if (nta_msg_request_complete(msg, leg, method, name, url) < 0) + if (nta_msg_request_complete(msg, leg, method, name, url) < 0) { + msg_destroy(msg); return -1; + } /**@MaxForwards header (with default value set by NTATAG_MAX_FORWARDS()) is * also added now, if it does not exist. @@ -2716,16 +2716,23 @@ int nua_client_request_sendmsg(nua_client_request_t *cr, msg_t *msg, sip_t *sip) cr->cr_contactize && !cr->cr_has_contact && !ds->ds_ltarget, - !ds->ds_route) < 0) + !ds->ds_route) < 0) { + msg_destroy(msg); return -1; + } } cr->cr_wait_for_cred = 0; if (cr->cr_methods->crm_send) - return cr->cr_methods->crm_send(cr, msg, sip, NULL); + error = cr->cr_methods->crm_send(cr, msg, sip, NULL); + else + error = nua_base_client_request(cr, msg, sip, NULL); - return nua_base_client_request(cr, msg, sip, NULL); + if (error != 0 && error != -2) + msg_destroy(msg); + + return error; } /**Add tags to request message and send it, @@ -2793,9 +2800,10 @@ int nua_base_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, } /** Callback for nta client transaction */ -int nua_client_orq_response(nua_client_request_t *cr, - nta_outgoing_t *orq, - sip_t const *sip) +int +nua_client_orq_response(nua_client_request_t *cr, + nta_outgoing_t *orq, + sip_t const *sip) { int status; char const *phrase; @@ -3090,11 +3098,8 @@ int nua_client_restart(nua_client_request_t *cr, int status, char const *phrase) { nua_handle_t *nh = cr->cr_owner; - nua_dialog_state_t *ds = nh->nh_ds; nta_outgoing_t *orq; int error = -1, terminated, graceful; - msg_t *msg = NULL; - sip_t *sip = NULL; if (cr->cr_retry_count > NH_PGET(nh, retry_count)) return 0; @@ -3102,32 +3107,10 @@ int nua_client_restart(nua_client_request_t *cr, orq = cr->cr_orq, cr->cr_orq = NULL; assert(orq); terminated = cr->cr_terminated, cr->cr_terminated = 0; graceful = cr->cr_graceful, cr->cr_graceful = 0; - cr->cr_offer_sent = cr->cr_answer_recv = 0; - cr->cr_offer_recv = cr->cr_answer_sent = 0; - if (!ds->ds_leg && cr->cr_dialog) { - sip_t const *sip = cr->cr_sip; - ds->ds_leg = nta_leg_tcreate(nh->nh_nua->nua_nta, - nua_stack_process_request, nh, - SIPTAG_CALL_ID(sip->sip_call_id), - SIPTAG_FROM(sip->sip_from), - SIPTAG_TO(sip->sip_to), - SIPTAG_CSEQ(sip->sip_cseq), - TAG_END()); - } - - if (ds->ds_leg || !cr->cr_dialog) { - msg = msg_copy(cr->cr_msg); - sip = sip_object(msg); - } - - if (msg && sip) { - cr->cr_restarting = 1; - error = nua_client_request_sendmsg(cr, msg, sip); - cr->cr_restarting = 0; - if (error !=0 && error != -2) - msg_destroy(msg); - } + cr->cr_restarting = 1; + error = nua_client_request_sendmsg(cr); + cr->cr_restarting = 0; if (error) { cr->cr_graceful = graceful; diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.c index eaf9cc3f85..7c3a0b1fbd 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.c @@ -52,6 +52,9 @@ #include #include +char const *s2_tester = "s2_tester"; +int s2_start_stop; + /* -- Module types ------------------------------------------------------ */ struct tp_magic_s @@ -207,6 +210,19 @@ int s2_check_callstate(enum nua_callstate state) return retval; } +int s2_check_substate(struct event *e, enum nua_substate state) +{ + int retval = 0; + tagi_t const *tagi; + + tagi = tl_find(e->data->e_tags, nutag_substate); + if (tagi) { + retval = (tag_value_t)state == tagi->t_value; + } + + return retval; +} + static void s2_nua_callback(nua_event_t event, int status, char const *phrase, @@ -371,6 +387,22 @@ s2_check_request(sip_method_t method, char const *name) return m != NULL; } +void +s2_save_uas_dialog(struct dialog *d, sip_t *sip) +{ + if (d && !d->local) { + assert(sip->sip_request); + d->local = sip_from_dup(d->home, sip->sip_to); + if (d->local->a_tag == NULL) + sip_from_tag(d->home, d->local, s2_generate_tag(d->home)); + d->remote = sip_to_dup(d->home, sip->sip_from); + d->call_id = sip_call_id_dup(d->home, sip->sip_call_id); + d->rseq = sip->sip_cseq->cs_seq; + /* d->route = sip_route_dup(d->home, sip->sip_record_route); */ + d->target = sip_contact_dup(d->home, sip->sip_contact); + } +} + struct message * s2_respond_to(struct message *m, struct dialog *d, int status, char const *phrase, @@ -386,6 +418,8 @@ s2_respond_to(struct message *m, struct dialog *d, assert(m); assert(m->msg); assert(m->tport); assert(100 <= status && status < 700); + s2_save_uas_dialog(d, m->sip); + ta_start(ta, tag, value); reply = s2_msg(0); sip = sip_object(reply); home = msg_home(reply); @@ -414,13 +448,7 @@ s2_respond_to(struct message *m, struct dialog *d, } } - if (d && !d->local) { - d->local = sip_from_dup(d->home, sip->sip_to); - d->remote = sip_to_dup(d->home, sip->sip_from); - d->call_id = sip_call_id_dup(d->home, sip->sip_call_id); - d->rseq = sip->sip_cseq->cs_seq; - /* d->route = sip_route_dup(d->home, sip->sip_record_route); */ - d->target = sip_contact_dup(d->home, m->sip->sip_contact); + if (d && !d->contact) { d->contact = sip_contact_dup(d->home, sip->sip_contact); } @@ -806,6 +834,9 @@ void s2_case(char const *number, char const *description) { _s2case = number; + + if (s2_start_stop) + printf("%s - starting %s %s\n", s2_tester, number, title); } /* ---------------------------------------------------------------------- */ @@ -875,10 +906,14 @@ tp_stack_class_t const s2_stack[1] = }}; /** Basic setup for test cases */ -void s2_setup_base(char const *hostname) +void s2_setup_base(char const *label, char const *hostname) { assert(s2 == NULL); + if (s2_start_stop > 1) { + printf("%s - setup %s test case\n", s2_tester, label ? label : "next"); + } + su_init(); s2 = su_home_new(sizeof *s2); @@ -897,6 +932,7 @@ void s2_setup_base(char const *hostname) s2->hostname = hostname; s2->tid = (unsigned long)time(NULL) * 510633671UL; + } SOFIAPUBVAR su_log_t nua_log[]; @@ -1489,22 +1525,43 @@ void s2_dns_domain(char const *domain, int use_naptr, va_end(va0); } +static char const *s2_teardown_label = NULL; + +void +s2_teardown_started(char const *label) +{ + if (!s2_teardown_label) { + s2_teardown_label = label; + if (s2_start_stop > 1) { + printf("%s - tearing down %s test case\n", s2_tester, label); + } + } +} + void s2_teardown(void) { s2 = NULL; su_deinit(); + + if (s2_start_stop > 1) { + printf("%s - %s test case tore down\n", s2_tester, + s2_teardown_label ? s2_teardown_label : "previous"); + } + + s2_teardown_label = NULL; } /* ====================================================================== */ #include -nua_t *s2_nua_setup(tag_type_t tag, tag_value_t value, ...) +nua_t *s2_nua_setup(char const *label, + tag_type_t tag, tag_value_t value, ...) { ta_list ta; - s2_setup_base(NULL); + s2_setup_base(label, NULL); s2_setup_dns(); s2_setup_logs(0); @@ -1618,4 +1675,3 @@ void s2_register_teardown(void) s2->registration->nh = NULL; } } - diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.h b/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.h index 9626c063a0..c5698ab23b 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_s2.h @@ -102,6 +102,8 @@ struct dialog msg_t *invite; /* latest invite sent */ }; +extern char const *s2_tester; +extern int s2_start_stop; extern struct tester *s2; extern tp_stack_class_t const s2_stack[1]; @@ -144,8 +146,12 @@ struct message *s2_next_request(void); struct message *s2_wait_for_request(sip_method_t method, char const *name); int s2_check_request(sip_method_t method, char const *name); +int s2_check_substate(struct event *e, enum nua_substate state); + #define SIP_METHOD_UNKNOWN sip_method_unknown, NULL +void s2_save_uas_dialog(struct dialog *d, sip_t *sip); + struct message *s2_respond_to(struct message *m, struct dialog *d, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...); @@ -161,15 +167,16 @@ int s2_save_register(struct message *m); void s2_flush_all(void); -void s2_setup_base(char const *hostname); +void s2_setup_base(char const *label, char const *hostname); void s2_setup_logs(int level); void s2_setup_tport(char const * const *protocols, tag_type_t tag, tag_value_t value, ...); void s2_teardown(void); -nua_t *s2_nua_setup(tag_type_t tag, tag_value_t value, ...); -void s2_nua_teardown(void); +nua_t *s2_nua_setup(char const *label, tag_type_t tag, tag_value_t value, ...); +void s2_teardown_started(char const *label); +void s2_nua_teardown(void); void s2_register_setup(void); void s2_register_teardown(void);