From 58312ce2d1d196e8f24a76772862afb4ca1b416a Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Tue, 13 May 2008 19:10:47 +0000 Subject: [PATCH] Mon May 12 18:51:36 EDT 2008 Pekka Pessi * nua: using NUTAG_PROXY() as handle-specific tag Added nua_dialog_update_params() and virtual method usage_update_params() for each dialog usage. git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@8384 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- libs/sofia-sip/.update | 2 +- .../sofia-sip/libsofia-sip-ua/nua/Makefile.am | 2 +- .../libsofia-sip-ua/nua/nua_dialog.c | 20 +++ .../libsofia-sip-ua/nua/nua_dialog.h | 31 +++-- .../libsofia-sip-ua/nua/nua_notifier.c | 1 + .../libsofia-sip-ua/nua/nua_params.c | 124 ++++++++++-------- .../libsofia-sip-ua/nua/nua_params.h | 18 ++- .../libsofia-sip-ua/nua/nua_publish.c | 1 + .../libsofia-sip-ua/nua/nua_register.c | 53 +++++++- .../libsofia-sip-ua/nua/nua_session.c | 11 +- .../sofia-sip/libsofia-sip-ua/nua/nua_stack.c | 4 + .../sofia-sip/libsofia-sip-ua/nua/nua_stack.h | 1 + .../libsofia-sip-ua/nua/nua_subnotref.c | 1 + libs/sofia-sip/libsofia-sip-ua/nua/outbound.c | 69 +++++++--- libs/sofia-sip/libsofia-sip-ua/nua/outbound.h | 3 + 15 files changed, 235 insertions(+), 106 deletions(-) diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index 6d636bbb03..87682b3696 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Tue May 13 15:08:14 EDT 2008 +Tue May 13 15:08:49 EDT 2008 diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.am index 366c5ecc2b..0bb8cac709 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.am @@ -30,7 +30,7 @@ nobase_include_sofia_HEADERS = \ sofia-sip/nua.h sofia-sip/nua_tag.h libnua_la_SOURCES = nua.c nua_stack.h nua_common.c nua_stack.c \ - nua_extension.c \ + nua_extension.c nua_types.h \ nua_dialog.c nua_dialog.h \ outbound.c outbound.h \ nua_params.c nua_params.h \ diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c index 639cafb629..ba3b9f788c 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c @@ -468,6 +468,26 @@ void nua_dialog_deinit(nua_owner_t *own, ds->ds_terminating = 0; } +void nua_dialog_update_params(nua_dialog_state_t *ds, + nua_handle_preferences_t const *changed, + nua_handle_preferences_t const *params, + nua_handle_preferences_t const *defaults) +{ + nua_dialog_usage_t *usage; + + for (usage = ds->ds_usage; usage; usage = usage->du_next) { + usage->du_class->usage_update_params(usage, changed, params, defaults); + } +} + +void nua_base_usage_update_params(nua_dialog_usage_t const *du, + nua_handle_preferences_t const *changed, + nua_handle_preferences_t const *params, + nua_handle_preferences_t const *defaults) +{ + (void)du, (void)changed, (void)params, (void)defaults; +} + /**@internal * Set refresh value suitably. * 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 6620810483..a1c6c9488f 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h @@ -35,27 +35,12 @@ * @date Created: Wed Mar 8 11:38:18 EET 2006 ppessi */ -#ifndef NUA_OWNER_T -#define NUA_OWNER_T struct nua_owner_s -#endif -typedef NUA_OWNER_T nua_owner_t; +#include #ifndef NTA_H #include #endif -typedef struct nua_dialog_state nua_dialog_state_t; -typedef struct nua_dialog_usage nua_dialog_usage_t; -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; - -#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; char const *sm_method_name; @@ -386,6 +371,10 @@ typedef struct { nua_client_request_t *cr, nua_server_request_t *sr); char const *(*usage_name)(nua_dialog_usage_t const *du); + void (*usage_update_params)(nua_dialog_usage_t const *du, + nua_handle_preferences_t const *changed, + nua_handle_preferences_t const *params, + nua_handle_preferences_t const *defaults); void (*usage_peer_info)(nua_dialog_usage_t *du, nua_dialog_state_t const *ds, sip_t const *sip); @@ -452,6 +441,16 @@ void nua_dialog_usage_remove(nua_owner_t *, nua_client_request_t *cr, nua_server_request_t *sr); +void nua_dialog_update_params(nua_dialog_state_t *ds, + nua_handle_preferences_t const *changed, + nua_handle_preferences_t const *params, + nua_handle_preferences_t const *defaults); + +void nua_base_usage_update_params(nua_dialog_usage_t const *du, + nua_handle_preferences_t const *changed, + nua_handle_preferences_t const *params, + nua_handle_preferences_t const *defaults); + void nua_dialog_deinit(nua_owner_t *own, nua_dialog_state_t *ds); 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 d15e4298e4..f07be72d83 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c @@ -92,6 +92,7 @@ static nua_usage_class const nua_notify_usage[1] = { nua_notify_usage_add, nua_notify_usage_remove, nua_notify_usage_name, + nua_base_usage_update_params, NULL, nua_notify_usage_refresh, nua_notify_usage_shutdown, diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c index 5568639b23..7b6d6b80b8 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c @@ -82,17 +82,6 @@ su_inline void nhp_or_set(nua_handle_preferences_t *a, /* Bitwise or of bitfields, casted to unsigned */ a->nhp_set_.set_unsigned[0] |= b->nhp_set_.set_unsigned[0]; a->nhp_set_.set_unsigned[1] |= b->nhp_set_.set_unsigned[1]; - - /* - unsigned *ap, const *bp; - size_t i; - - ap = a->nhp_set_.set_unsigned; - bp = b->nhp_set_.set_unsigned; - for (i = 0; i < (sizeof a->nhp_set); i += (sizeof *ap)) - *ap++ |= *bp++; - - */ } static int nhp_set_tags(su_home_t *home, @@ -110,10 +99,9 @@ static int nhp_merge_lists(su_home_t *home, tag_value_t value); static int nhp_save_params(nua_handle_t *nh, - su_home_t *tmphome, - nua_global_preferences_t *gsrc, - nua_handle_preferences_t *src); - + su_home_t *tmphome, + nua_global_preferences_t *gsrc, + nua_handle_preferences_t *src); /* ====================================================================== */ /* Magical NUTAG_USER_AGENT() - add NHP_USER_AGENT there if it is not there */ @@ -310,6 +298,7 @@ int nua_stack_init_instance(nua_handle_t *nh, tagi_t const *tags) * NUTAG_ONLY183_100REL() \n * NUTAG_OUTBOUND() \n * NUTAG_PATH_ENABLE() \n + * NUTAG_PROXY() (aka NTATAG_DEFAULT_PROXY()) \n * NUTAG_REFER_EXPIRES() \n * NUTAG_REFER_WITH_ID() \n * NUTAG_REGISTRAR() \n @@ -430,6 +419,7 @@ int nua_stack_init_instance(nua_handle_t *nh, tagi_t const *tags) * NUTAG_ONLY183_100REL() \n * NUTAG_OUTBOUND() \n * NUTAG_PATH_ENABLE() \n + * NUTAG_PROXY() (aka NTATAG_DEFAULT_PROXY()) \n * NUTAG_REFER_EXPIRES() \n * NUTAG_REFER_WITH_ID() \n * NUTAG_REGISTRAR() \n @@ -482,13 +472,15 @@ int nua_stack_set_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, int status; char const *phrase; + nua_handle_preferences_t tmp[1]; + int any_changes = 0; + enter; { su_home_t tmphome[1] = { SU_HOME_INIT(tmphome) }; nua_handle_preferences_t *nhp = nh->nh_prefs; nua_handle_preferences_t const *dnhp = dnh->nh_prefs; - nua_handle_preferences_t tmp[1]; nua_global_preferences_t gtmp[1], *ngp = NULL; *tmp = *nhp; NHP_UNSET_ALL(tmp); @@ -521,7 +513,7 @@ int nua_stack_set_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, status = 900, phrase = "Error storing default handle parameters"; else if (nhp_set_tags(tmphome, tmp, ngp, tags) < 0) status = 900, phrase = "Error storing parameters"; - else if (nhp_save_params(nh, tmphome, ngp, tmp) < 0) + else if ((any_changes = nhp_save_params(nh, tmphome, ngp, tmp)) < 0) status = 900, phrase = su_strerror(ENOMEM); else status = 200, phrase = "OK", nh->nh_used_ptags = 1; @@ -562,7 +554,8 @@ int nua_stack_set_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, if (nua_stack_set_smime_params(nua, tags) < 0) { status = 900, phrase = "Error setting S/MIME parameters"; } - else if (nua->nua_nta && nta_agent_set_params(nua->nua_nta, TAG_NEXT(tags)) < 0) { + else if (nua->nua_nta && + nta_agent_set_params(nua->nua_nta, TAG_NEXT(tags)) < 0) { status = 900, phrase = "Error setting NTA parameters"; } else { @@ -581,6 +574,18 @@ int nua_stack_set_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, else { if (e == nua_r_set_params) UA_EVENT2(e, status, phrase); + + if (any_changes) { + nua_handle_preferences_t changed[1]; + + *changed = *nh->nh_prefs; + memcpy(&changed->nhp_set_, &tmp->nhp_set_, sizeof changed->nhp_set_); + + nua_dialog_update_params(nh->nh_ds, + changed, + nh->nh_prefs, + dnh->nh_prefs); + } return 0; } } @@ -612,11 +617,10 @@ static int nhp_set_tags(su_home_t *home, } /* Set copy of string from url to handle pref structure */ -#define NHP_SET_STR_BY_URL(nhp, name, v) \ +#define NHP_SET_STR_BY_URL(nhp, type, name, v) \ if ((v) != (tag_value_t)-1) { \ url_t const *_value = (url_t const *)(v); \ - char *_new; \ - _new = url_as_string(home, (void *)_value); \ + type *_new = (type *)url_as_string(home, (void *)_value); \ if (NHP_ISSET(nhp, name)) \ su_free(home, (void *)nhp->nhp_##name); \ NHP_SET(nhp, name, _new); \ @@ -953,7 +957,7 @@ static int nhp_set_tags(su_home_t *home, } /* NUTAG_REGISTRAR(registrar) */ else if (tag == nutag_registrar) { - NHP_SET_STR_BY_URL(nhp, registrar, value); + NHP_SET_STR_BY_URL(nhp, char, registrar, value); if (NHP_ISSET(nhp, registrar) && !str0cmp(nhp->nhp_registrar, "*")) NHP_SET_STR(nhp, registrar, 0); } @@ -981,6 +985,10 @@ static int nhp_set_tags(su_home_t *home, else if (tag == nutag_outbound) { NHP_SET_STR(nhp, outbound, value); } + /* NUTAG_PROXY() (aka NTATAG_DEFAULT_PROXY()) */ + else if (tag == ntatag_default_proxy) { + NHP_SET_STR_BY_URL(nhp, url_string_t, proxy, value); + } /* NUTAG_DETECT_NETWORK_UPDATES(detect_network_updates) */ else if (ngp && tag == nutag_detect_network_updates) { int detector = (int)value; @@ -1070,6 +1078,10 @@ static int nhp_merge_lists(su_home_t *home, } /** Save parameters in @a gtmp and @a tmp. + * + * @retval 1 - parameters were changed + * @retval 0 - no changes in parameters + * @retval -1 - an error */ static int nhp_save_params(nua_handle_t *nh, @@ -1132,7 +1144,7 @@ int nhp_save_params(nua_handle_t *nh, nh->nh_prefs = dst; - return 0; + return memcmp(dst, old, sizeof *dst) != 0; } static int nua_handle_tags_filter(tagi_t const *f, tagi_t const *t); @@ -1141,21 +1153,6 @@ static int nua_handle_param_filter(tagi_t const *f, tagi_t const *t); /** Save taglist to a handle */ int nua_handle_save_tags(nua_handle_t *nh, tagi_t *tags) { -#if HAVE_OPEN_C - /* Nice. An old symbian compiler */ - tagi_t tagfilter[2]; - tagi_t paramfilter[2]; -#else - tagi_t const tagfilter[] = { - { TAG_FILTER(nua_handle_tags_filter) }, - { TAG_NULL() } - }; - tagi_t const paramfilter[] = { - { TAG_FILTER(nua_handle_param_filter) }, - { TAG_NULL() } - }; -#endif - /* Initialization parameters */ url_string_t const *url = NULL; sip_to_t const *p_to = NULL; @@ -1171,6 +1168,10 @@ int nua_handle_save_tags(nua_handle_t *nh, tagi_t *tags) int error; #if HAVE_OPEN_C + /* Nice. An old symbian compiler */ + tagi_t tagfilter[2]; + tagi_t paramfilter[2]; + tagfilter[0].t_tag = tag_filter; tagfilter[0].t_value = tag_filter_v(nua_handle_tags_filter); tagfilter[1].t_tag = (tag_type_t)0; @@ -1180,6 +1181,16 @@ int nua_handle_save_tags(nua_handle_t *nh, tagi_t *tags) paramfilter[0].t_value = tag_filter_v(nua_handle_param_filter); paramfilter[1].t_tag = (tag_type_t)0; paramfilter[1].t_value = (tag_value_t)0; + +#else + tagi_t const tagfilter[] = { + { TAG_FILTER(nua_handle_tags_filter) }, + { TAG_NULL() } + }; + tagi_t const paramfilter[] = { + { TAG_FILTER(nua_handle_param_filter) }, + { TAG_NULL() } + }; #endif for (t = tags; t; t = tl_next(t)) { @@ -1525,7 +1536,7 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, nua_handle_t *dnh = nua->nua_dhandle; nua_global_preferences_t const *ngp = nua->nua_prefs; nua_handle_preferences_t const *nhp = nh->nh_prefs; - + nua_handle_preferences_t const nhp_zero[1] = {{ 0 }}; tagi_t *lst; int has_from; @@ -1549,18 +1560,19 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, enter; - nta_agent_get_params(nua->nua_nta, - NTATAG_UDP_MTU_REF(udp_mtu), - NTATAG_MAX_PROCEEDING_REF(max_proceeding), - NTATAG_SIP_T1_REF(sip_t1), - NTATAG_SIP_T2_REF(sip_t2), - NTATAG_SIP_T4_REF(sip_t4), - NTATAG_SIP_T1X64_REF(sip_t1x64), - NTATAG_DEBUG_DROP_PROB_REF(debug_drop_prob), - NTATAG_DEFAULT_PROXY_REF(proxy), - NTATAG_ALIASES_REF(aliases), - NTATAG_SIPFLAGS_REF(flags), - TAG_END()); + if (nh == dnh) + nta_agent_get_params(nua->nua_nta, + NTATAG_UDP_MTU_REF(udp_mtu), + NTATAG_MAX_PROCEEDING_REF(max_proceeding), + NTATAG_SIP_T1_REF(sip_t1), + NTATAG_SIP_T2_REF(sip_t2), + NTATAG_SIP_T4_REF(sip_t4), + NTATAG_SIP_T1X64_REF(sip_t1x64), + NTATAG_DEBUG_DROP_PROB_REF(debug_drop_prob), + NTATAG_DEFAULT_PROXY_REF(proxy), + NTATAG_ALIASES_REF(aliases), + NTATAG_SIPFLAGS_REF(flags), + TAG_END()); if (nh->nh_ds->ds_local) has_from = 1, *from = *nh->nh_ds->ds_local, from->a_params = NULL; @@ -1597,6 +1609,9 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, ? sip_##pref##_make(tmphome, (char *)nhp->nhp_##pref) \ : NULL)) + if (nh != dnh && nhp == dnh->nh_prefs) + nhp = nhp_zero; + su_home_auto(tmphome, sizeof(tmphome)); lst = tl_filtered_tlist @@ -1669,6 +1684,10 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, TIF(NUTAG_M_FEATURES, m_features), TIF(NUTAG_OUTBOUND, outbound), + /* Handle-specific proxy */ + TAG_IF(nh != dnh && nhp->nhp_set.nhb_proxy, + NUTAG_PROXY(nhp->nhp_proxy)), + /* Skip user-agent-level parameters if parameters are for handle only */ TAG_IF(nh != dnh, TAG_NEXT(media_params)), @@ -1693,12 +1712,13 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, #endif NTATAG_UDP_MTU(udp_mtu), - NTATAG_MAX_PROCEEDING(max_proceeding), + NTATAG_MAX_PROCEEDING(max_proceeding), NTATAG_SIP_T1(sip_t1), NTATAG_SIP_T2(sip_t2), NTATAG_SIP_T4(sip_t4), NTATAG_SIP_T1X64(sip_t1x64), NTATAG_DEBUG_DROP_PROB(debug_drop_prob), + /* Stack-wide proxy */ NTATAG_DEFAULT_PROXY(proxy), NTATAG_ALIASES(aliases), NTATAG_SIPFLAGS(flags), diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.h b/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.h index a9993fe9a3..0b0abe2162 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.h @@ -35,6 +35,8 @@ * @date Created: Wed Mar 8 11:38:18 EET 2006 ppessi */ +#include + /**@internal @brief NUA preferences. * * This structure contains values for various preferences and a separate @@ -50,7 +52,7 @@ * * @see NHP_GET(), NH_PGET(), NHP_ISSET(), NH_PISSET() */ -typedef struct nua_handle_preferences +struct nua_handle_preferences { unsigned nhp_retry_count; /**< times to retry a request */ unsigned nhp_max_subscriptions; @@ -133,6 +135,9 @@ typedef struct nua_handle_preferences /** Initial route set */ sip_route_t *nhp_initial_route; + /** Next hop URI (used instead of route). */ + url_string_t *nhp_proxy; + union { struct { /* A bit for each feature set by application */ /* NOTE: @@ -191,16 +196,17 @@ typedef struct nua_handle_preferences unsigned nhb_outbound:1; unsigned nhb_appl_method:1; unsigned nhb_initial_route:1; + unsigned nhb_proxy:1; unsigned :0; } set_bits; unsigned set_unsigned[2]; } nhp_set_; -} nua_handle_preferences_t; +}; #define nhp_set nhp_set_.set_bits /** Global preferences for nua. */ -typedef struct { +struct nua_global_preferences { /** Network detection: NONE, INFORMAL, TRY_FULL */ signed int ngp_detect_network_updates:3; /** Pass events during shutdown, too */ @@ -215,7 +221,7 @@ typedef struct { } set_bits; unsigned set_unsigned[2]; } ngp_set_; -} nua_global_preferences_t; +}; #define ngp_set ngp_set_.set_bits @@ -238,7 +244,7 @@ typedef struct { /* Get preference from handle, if set, otherwise from default handle */ #define NH_PGET(nh, pref) \ - NHP_GET((nh)->nh_prefs, (nh)->nh_nua->nua_dhandle->nh_prefs, pref) + NHP_GET((nh)->nh_prefs, (nh)->nh_dprefs, pref) /* Get preference from handle, if exists and set, otherwise from default handle */ @@ -255,7 +261,7 @@ typedef struct { (NHP_ISSET((nh)->nh_prefs, pref) && \ (nh)->nh_nua->nua_dhandle->nh_prefs != (nh)->nh_prefs) -/* Check if preference has been set by applicationx */ +/* Check if preference has been set by application */ #define NUA_PISSET(nua, nh, pref) \ (NHP_ISSET((nua)->nua_dhandle->nh_prefs, pref) || \ ((nh) && NHP_ISSET((nh)->nh_prefs, pref))) diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_publish.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_publish.c index 8b4331c508..1d1e62b530 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_publish.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_publish.c @@ -79,6 +79,7 @@ static nua_usage_class const nua_publish_usage[1] = { nua_publish_usage_add, nua_publish_usage_remove, nua_publish_usage_name, + nua_base_usage_update_params, NULL, nua_publish_usage_refresh, nua_publish_usage_shutdown, 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 3d0b85f126..51232a1d31 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_register.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_register.c @@ -107,6 +107,10 @@ static void nua_register_usage_remove(nua_handle_t *nh, nua_dialog_usage_t *du, nua_client_request_t *cr, nua_server_request_t *sr); +static void nua_register_usage_update_params(nua_dialog_usage_t const *du, + nua_handle_preferences_t const *, + nua_handle_preferences_t const *, + nua_handle_preferences_t const *); static void nua_register_usage_peer_info(nua_dialog_usage_t *du, nua_dialog_state_t const *ds, sip_t const *sip); @@ -169,6 +173,7 @@ nua_usage_class const nua_register_usage[1] = { nua_register_usage_add, nua_register_usage_remove, nua_register_usage_name, + nua_register_usage_update_params, nua_register_usage_peer_info, nua_register_usage_refresh, nua_register_usage_shutdown @@ -672,6 +677,11 @@ static int nua_register_client_init(nua_client_request_t *cr, NH_PGET(nh, instance)); if (!nr->nr_ob) return nua_client_return(cr, 900, "Cannot create outbound", msg); + + nua_register_usage_update_params(du, + NULL, + nh->nh_prefs, + nh->nh_dprefs); } if (nr->nr_ob) { @@ -687,13 +697,6 @@ static int nua_register_client_init(nua_client_request_t *cr, unreg = 1; /* All contacts have expires=0 */ } - outbound_set_options(ob, - NH_PGET(nh, outbound), - NH_PGET(nh, keepalive), - NH_PISSET(nh, keepalive_stream) - ? NH_PGET(nh, keepalive_stream) - : NH_PGET(nh, keepalive)); - if (outbound_set_contact(ob, sip->sip_contact, nr->nr_via, unreg) < 0) return nua_client_return(cr, 900, "Cannot set outbound contact", msg); } @@ -1038,6 +1041,42 @@ void nua_register_connection_closed(tp_stack_t *sip_stack, nua_dialog_usage_set_refresh_range(du, 0, 0); } +static void +nua_register_usage_update_params(nua_dialog_usage_t const *du, + nua_handle_preferences_t const *changed, + nua_handle_preferences_t const *nhp, + nua_handle_preferences_t const *dnhp) +{ + nua_registration_t *nr = nua_dialog_usage_private(du); + outbound_t *ob = nr->nr_ob; + + if (!ob) + return; + + if (!changed || + NHP_ISSET(changed, outbound) || + NHP_ISSET(changed, keepalive) || + NHP_ISSET(changed, keepalive_stream)) { + char const *outbound = + NHP_ISSET(nhp, outbound) ? nhp->nhp_outbound + : dnhp->nhp_outbound; + unsigned keepalive = + NHP_ISSET(nhp, keepalive) ? nhp->nhp_keepalive + : dnhp->nhp_keepalive; + unsigned keepalive_stream = + NHP_ISSET(nhp, keepalive_stream) ? nhp->nhp_keepalive_stream + : NHP_ISSET(dnhp, keepalive_stream) ? nhp->nhp_keepalive_stream + : keepalive; + + outbound_set_options(ob, outbound, keepalive, keepalive_stream); + } + + if (!changed || NHP_ISSET(changed, proxy)) { + if (NHP_ISSET(nhp, proxy)) + outbound_set_proxy(ob, nhp->nhp_proxy); + } +} + static void nua_register_usage_refresh(nua_handle_t *nh, nua_dialog_state_t *ds, 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 b0abfd4604..9a0427597f 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c @@ -207,6 +207,7 @@ static nua_usage_class const nua_session_usage[1] = { nua_session_usage_add, nua_session_usage_remove, nua_session_usage_name, + nua_base_usage_update_params, NULL, nua_session_usage_refresh, nua_session_usage_shutdown @@ -335,9 +336,6 @@ void nua_session_usage_destroy(nua_handle_t *nh, /* ======================================================================== */ /* INVITE and call (session) processing */ -int nua_stack_prack(nua_t *nua, nua_handle_t *nh, nua_event_t e, - tagi_t const *tags); - static int session_timer_is_supported(struct session_timer const *t); static void session_timer_preferences(struct session_timer *t, @@ -1206,6 +1204,8 @@ int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags) sip_authorization_t *wa; sip_proxy_authorization_t *pa; sip_cseq_t *cseq; + int proxy_is_set; + url_string_t *proxy; nta_outgoing_t *ack; int status = 200; char const *phrase = "OK", *reason = NULL; @@ -1314,9 +1314,14 @@ int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags) } } + proxy_is_set = NH_PISSET(nh, proxy); + proxy = NH_PGET(nh, proxy); + if ((ack = nta_outgoing_mcreate(nh->nh_nua->nua_nta, NULL, NULL, NULL, msg, NTATAG_ACK_BRANCH(invite_branch), + TAG_IF(proxy_is_set, + NTATAG_DEFAULT_PROXY(proxy)), SIPTAG_END(), TAG_NEXT(tags)))) { /* TR engine keeps this around for T2 so it catches all 2XX retransmissions */ 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 97c3bb3930..f21f977620 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c @@ -2633,6 +2633,8 @@ int nua_base_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_handle_t *nh = cr->cr_owner; + int proxy_is_set = NH_PISSET(nh, proxy); + url_string_t * proxy = NH_PGET(nh, proxy); if (nh->nh_auth) { if (cr->cr_challenged || @@ -2648,6 +2650,8 @@ int nua_base_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, nua_client_orq_response, cr, NULL, msg, + TAG_IF(proxy_is_set, + NTATAG_DEFAULT_PROXY(proxy)), TAG_NEXT(tags)); return cr->cr_orq ? 0 : -1; 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 68da7a43d5..f81c7dd6bc 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h @@ -154,6 +154,7 @@ struct nua_handle_s nua_handle_t *nh_identity; /**< Identity */ nua_handle_preferences_t *nh_prefs; /**< Preferences */ +#define nh_dprefs nh_nua->nua_dhandle->nh_prefs /* Handle type is determined by special event and flags. */ nua_event_t nh_special; /**< Special event */ diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c index 8bb4d55d44..5a30b4cadb 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c @@ -91,6 +91,7 @@ static nua_usage_class const nua_subscribe_usage[1] = { nua_subscribe_usage_add, nua_subscribe_usage_remove, nua_subscribe_usage_name, + nua_base_usage_update_params, NULL, nua_subscribe_usage_refresh, nua_subscribe_usage_shutdown diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/outbound.c b/libs/sofia-sip/libsofia-sip-ua/nua/outbound.c index 6778662b6d..60418ae035 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/outbound.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/outbound.c @@ -104,8 +104,8 @@ struct outbound { unsigned ob_registering:1; /** 2XX response to REGISTER containg ob_rcontact has been received */ unsigned ob_registered:1; - /**The registration has been validated: - * We have successfully sent OPTIONS to ourselves. + /** The registration has been validated: + * We have successfully sent OPTIONS to ourselves. */ unsigned ob_validated:1; /** The registration has been validated once. @@ -113,8 +113,11 @@ struct outbound { * up if OPTIONS probe fails. */ unsigned ob_once_validated:1; + + unsigned ob_proxy_override:1; /**< Override stack default proxy */ unsigned :0; + url_string_t *ob_proxy; /**< Outbound-specific proxy */ char const *ob_instance; /**< Our instance ID */ int32_t ob_reg_id; /**< Flow-id */ sip_contact_t *ob_rcontact; /**< Our contact */ @@ -209,10 +212,11 @@ outbound_new(outbound_owner_t *owner, ob->ob_nta = agent; if (instance) - ob->ob_instance = su_strcat_all(ob->ob_home, "+sip.instance=\"<", instance, ">\"", NULL); + ob->ob_instance = + su_sprintf(ob->ob_home, "+sip.instance=\"<%s>\"", instance); ob->ob_reg_id = 0; - /* Generate a cookie (used as Call-ID) for us */ + /* Generate a random cookie (used as Call-ID) for us */ su_md5_init(md5); su_guid_generate(guid); if (instance) @@ -246,16 +250,23 @@ void outbound_unref(outbound_t *ob) /** Set various outbound and nat-traversal related options. */ int outbound_set_options(outbound_t *ob, - char const *options, + char const *_options, unsigned interval, unsigned stream_interval) { struct outbound_prefs prefs[1] = {{ 0 }}; - char const *s; + char *s, *options = su_strdup(NULL, _options); + int invalid; prefs->interval = interval; prefs->stream_interval = stream_interval; +#define MATCH(v) (len == sizeof(#v) - 1 && strncasecmp(#v, s, len) == 0) + + if (options) { + for (s = options; s[0]; s++) if (s[0] == '-') s[0] = '_'; + } + prefs->gruuize = 1; prefs->outbound = 0; prefs->natify = 1; @@ -263,17 +274,11 @@ int outbound_set_options(outbound_t *ob, prefs->validate = 1; prefs->use_rport = 1; -#define MATCH(v) (len == sizeof(#v) - 1 && strncasecmp(#v, s, len) == 0) - for (s = options; s && s[0]; ) { size_t len = span_token(s); int value = 1; - if (len > 3 && strncasecmp(s, "no-", 3) == 0) - value = 0, s += 3, len -= 3; - else if (len > 4 && strncasecmp(s, "not-", 4) == 0) - value = 0, s += 4, len -= 4; - else if (len > 3 && strncasecmp(s, "no_", 3) == 0) + if (len > 3 && strncasecmp(s, "no_", 3) == 0) value = 0, s += 3, len -= 3; else if (len > 4 && strncasecmp(s, "not_", 4) == 0) value = 0, s += 4, len -= 4; @@ -284,14 +289,12 @@ int outbound_set_options(outbound_t *ob, else if (MATCH(outbound)) prefs->outbound = value; else if (MATCH(natify)) prefs->natify = value; else if (MATCH(validate)) prefs->validate = value; - else if (MATCH(options-keepalive)) prefs->okeepalive = value; else if (MATCH(options_keepalive)) prefs->okeepalive = value; - else if (MATCH(use-connect)) prefs->use_connect = value; else if (MATCH(use_connect)) prefs->use_connect = value; - else if (MATCH(use-rport) || MATCH(use_rport)) prefs->use_rport = value; - else if (MATCH(use-socks) || MATCH(use_socks)) prefs->use_socks = value; - else if (MATCH(use-upnp) || MATCH(use_upnp)) prefs->use_upnp = value; - else if (MATCH(use-stun) || MATCH(use_stun)) prefs->use_stun = value; + else if (MATCH(use_rport)) prefs->use_rport = value; + else if (MATCH(use_socks)) prefs->use_socks = value; + else if (MATCH(use_upnp)) prefs->use_upnp = value; + else if (MATCH(use_stun)) prefs->use_stun = value; else SU_DEBUG_1(("outbound(%p): unknown option \"%.*s\"\n", (void *)ob->ob_owner, (int)len, s)); @@ -303,7 +306,10 @@ int outbound_set_options(outbound_t *ob, s += len; } - if (s && s[0]) { + invalid = s && s[0]; + su_free(NULL, options); + + if (invalid) { SU_DEBUG_1(("outbound(%p): invalid options \"%s\"\n", (void *)ob->ob_owner, options)); return -1; @@ -326,6 +332,25 @@ int outbound_set_options(outbound_t *ob, return 0; } +/** Override stack default proxy for outbound */ +int outbound_set_proxy(outbound_t *ob, + url_string_t *proxy) +{ + url_string_t *new_proxy = NULL, *old_proxy = ob->ob_proxy; + + if (proxy) + new_proxy = (url_string_t *)url_as_string(ob->ob_home, proxy->us_url); + + if (proxy == NULL || new_proxy != NULL) { + ob->ob_proxy_override = 1; + ob->ob_proxy = new_proxy; + su_free(ob->ob_home, old_proxy); + return 0; + } + + return -1; +} + /* ---------------------------------------------------------------------- */ /** Obtain contacts for REGISTER */ @@ -784,6 +809,8 @@ static int keepalive_options(outbound_t *ob) ob, NULL, req, + TAG_IF(ob->ob_proxy_override, + NTATAG_DEFAULT_PROXY(ob->ob_proxy)), TAG_END()); if (!ob->ob_keepalive.orq) @@ -949,6 +976,8 @@ static int keepalive_options_with_registration_probe(outbound_t *ob) ob, NULL, req, + TAG_IF(ob->ob_proxy_override, + NTATAG_DEFAULT_PROXY(ob->ob_proxy)), SIPTAG_SUBJECT_STR("REGISTRATION PROBE"), /* NONE is used to remove Max-Forwards: 0 found in ordinary keepalives */ diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/outbound.h b/libs/sofia-sip/libsofia-sip-ua/nua/outbound.h index 175e81b293..c1e13e6fa1 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/outbound.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/outbound.h @@ -70,6 +70,9 @@ int outbound_set_options(outbound_t *ob, unsigned dgram_interval, unsigned stream_interval); +int outbound_set_proxy(outbound_t *ob, + url_string_t *proxy); + int outbound_get_contacts(outbound_t *ob, sip_contact_t **return_current_contact, sip_contact_t **return_previous_contact);