Mon May 12 18:51:36 EDT 2008 Pekka Pessi <first.last@nokia.com>

* 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
This commit is contained in:
Michael Jerris 2008-05-13 19:10:47 +00:00
parent 052e33d6d2
commit 58312ce2d1
15 changed files with 235 additions and 106 deletions

View File

@ -1 +1 @@
Tue May 13 15:08:14 EDT 2008
Tue May 13 15:08:49 EDT 2008

View File

@ -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 \

View File

@ -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.
*

View File

@ -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 <nua_types.h>
#ifndef NTA_H
#include <sofia-sip/nta.h>
#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);

View File

@ -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,

View File

@ -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,
@ -114,7 +103,6 @@ static int nhp_save_params(nua_handle_t *nh,
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,6 +1560,7 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
enter;
if (nh == dnh)
nta_agent_get_params(nua->nua_nta,
NTATAG_UDP_MTU_REF(udp_mtu),
NTATAG_MAX_PROCEEDING_REF(max_proceeding),
@ -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)),
@ -1699,6 +1718,7 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
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),

View File

@ -35,6 +35,8 @@
* @date Created: Wed Mar 8 11:38:18 EET 2006 ppessi
*/
#include <nua_types.h>
/**@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)))

View File

@ -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,

View File

@ -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,

View File

@ -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 */

View File

@ -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;

View File

@ -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 */

View File

@ -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

View File

@ -104,7 +104,7 @@ 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:
/** The registration has been validated:
* We have successfully sent OPTIONS to ourselves.
*/
unsigned ob_validated:1;
@ -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 */

View File

@ -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);