Commit 9d7b2952 authored by Pekka Pessi's avatar Pekka Pessi

nua: added NUTAG_M_DISPLAY(), NUTAG_M_USERNAME(), NUTAG_M_PARAMS() and NUTAG_M_FEATURES().

These tags are used to modify the Contact header generated by the stack in
the nua_handle_contact_by_via() header. Currently, the tags only affect
Contact header generated for registration.

Updated internal outbound interface in order to make use of the new features.

darcs-hash:20060913135519-65a35-6531f086bb5e7f454e568ebb144768163a6bb4c9.gz
parent 906b5f64
......@@ -275,6 +275,8 @@ nua_handle_t *nua_default(nua_t *nua)
* @par Events:
* none
*
* @sa nua_handle_bind(), nua_handle_destroy(), nua_handle_ref(),
* nua_handle_unref().
*/
nua_handle_t *nua_handle(nua_t *nua, nua_hmagic_t *hmagic,
tag_type_t tag, tag_value_t value, ...)
......@@ -514,6 +516,7 @@ sip_to_t const *nua_handle_local(nua_handle_t const *nh)
return nh ? nh->nh_ds->ds_local : NULL;
}
/* Documented with nua_stack_set_params() */
void nua_set_params(nua_t *nua, tag_type_t tag, tag_value_t value, ...)
{
ta_list ta;
......@@ -526,6 +529,7 @@ void nua_set_params(nua_t *nua, tag_type_t tag, tag_value_t value, ...)
ta_end(ta);
}
/* Documented with nua_stack_get_params() */
void nua_get_params(nua_t *nua, tag_type_t tag, tag_value_t value, ...)
{
ta_list ta;
......@@ -550,11 +554,13 @@ void nua_get_params(nua_t *nua, tag_type_t tag, tag_value_t value, ...)
SU_DEBUG_1(("nua: " #event " with invalid handle %p\n", nh)); \
}
/* Documented with nua_stack_set_params() */
void nua_set_hparams(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
{
NUA_SIGNAL(nh, nua_r_set_params, tag, value);
}
/* Documented with nua_stack_get_params() */
void nua_get_hparams(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...)
{
NUA_SIGNAL(nh, nua_r_get_params, tag, value);
......@@ -1108,9 +1114,15 @@ void nua_respond(nua_handle_t *nh,
/** Destroy a handle
*
* Destroy an operation handle and asks stack to discard resources
* and ongoing sessions and transactions associated with this handle.
* For example calls are terminated with BYE request.
* Terminate the protocol state associated with an operation handle. The
* stack discards resources and terminates the ongoing dialog usage,
* sessions and transactions associated with this handle. For example, calls
* are terminated with BYE request. Also, the reference count for the handle
* is also decremented.
*
* The handles use reference counting for memory management. In order to
* make it more convenient for programmer, nua_handle_destroy() decreases
* the reference count, too.
*
* @param nh Pointer to operation handle
*
......@@ -1122,6 +1134,8 @@ void nua_respond(nua_handle_t *nh,
*
* @par Events:
* none
*
* @sa nua_handle(), nua_handle_bind(), nua_handle_ref(), nua_handle_unref().
*/
void nua_handle_destroy(nua_handle_t *nh)
{
......
......@@ -207,8 +207,16 @@ static void nh_destructor(void *arg)
}
/** Make a new reference to handle.
*
* The handles use reference counting for memory management. In addition to
* the memory management, there is protocol state associated with the
* handles. The protocol state is terminated with nua_handle_destroy(). In
* order to make it more convenient for programmer, nua_handle_destroy()
* decreases the reference count, too.
*
* @note All handle references are destroyed when the nua object is destroyed.
*
* @sa nua_handle_unref(), nua_handle(), nua_handle_destroy().
*/
nua_handle_t *nua_handle_ref(nua_handle_t *nh)
{
......@@ -216,13 +224,22 @@ nua_handle_t *nua_handle_ref(nua_handle_t *nh)
}
/** Destroy reference to handle. */
/** Destroy reference to handle.
*
* The handles use reference counting for memory management. In addition to
* the memory management, there is protocol state associated with the
* handles. The protocol state is terminated with nua_handle_destroy(). In
* order to make it more convenient for programmer, nua_handle_destroy()
* decreases the reference count, too.
*
* @sa nua_handle_ref(), nua_handle(), nua_handle_destroy().
*/
int nua_handle_unref(nua_handle_t *nh)
{
return su_home_unref(nh->nh_home);
}
/** Generate an instance identifier */
/** Generate an instance identifier. */
char const *nua_generate_instance_identifier(su_home_t *home)
{
char str[su_guid_strlen + 1];
......
......@@ -53,6 +53,65 @@
#include <assert.h>
/* ====================================================================== */
/* Helper macros and functions for handling #nua_handle_preferences_t. */
#define NHP_IS_ANY_SET(nhp) nhp_is_any_set((nhp))
/** Check if any preference is set in @a nhp. */
su_inline int nhp_is_any_set(nua_handle_preferences_t const *nhp)
{
char nhp_zero[sizeof nhp->nhp_set] = { 0 };
return memcmp(&nhp->nhp_set, nhp_zero, sizeof nhp->nhp_set);
}
/** If preference is set in @a b, mark it set also in @a a. */
su_inline void nhp_or_set(nua_handle_preferences_t *a,
nua_handle_preferences_t const *b)
{
unsigned *ap = (unsigned *)&a->nhp_set;
unsigned const *bp = (unsigned const *)&b->nhp_set;
int i;
for (i = 0; i < (sizeof a->nhp_set); i += (sizeof *ap))
*ap++ |= *bp++;
}
/* Set string in handle pref structure */
#define NHP_SET_STR(nhp, name, str) \
if (str != NONE) { \
char *new_str = su_strdup(tmphome, str); \
NHP_SET(nhp, name, new_str); \
error |= (new_str != NULL && str == NULL); \
}
/* Set header in handle pref structure */
#define NHP_SET_HEADER(nhp, name, header, str) \
if (header != NONE || str != NONE) { \
sip_##name##_t *new_header; \
if (header != NONE) \
new_header = sip_##name##_dup(tmphome, header); \
else \
new_header = sip_##name##_make(tmphome, str); \
if (new_header != NULL || (header == NULL || str == NULL)) { \
NHP_SET(nhp, name, new_header); \
} \
else { \
error = 1; \
} \
}
/* Zap pointers which are not set */
#define NHP_ZAP_UNSET_PTR(nhp, pref) \
(!(nhp)->nhp_set.nhb_##pref ? (nhp)->nhp_##pref = NULL : NULL)
/* Free changed items */
#define NHP_ZAP_OVERRIDEN(tbf, nhp, pref) \
((tbf)->nhp_set.nhb_##pref \
&& (tbf)->nhp_##pref != (nhp)->nhp_##pref \
? su_free(nh->nh_home, (void *)(tbf)->nhp_##pref) : (void)0)
/* ====================================================================== */
/* Stack and handle parameters */
......@@ -334,6 +393,10 @@ int nua_stack_set_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
url_string_t const *registrar = NONE;
char const *instance = NONE;
char const *m_display = NONE;
char const *m_username = NONE;
char const *m_params = NONE;
char const *m_features = NONE;
char const *outbound = NONE;
int error = 0;
......@@ -496,6 +559,22 @@ int nua_stack_set_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
else if (t->t_tag == nutag_instance) {
instance = (void *)t->t_value;
}
/* NUTAG_M_DISPLAY_REF(m_display) */
else if (t->t_tag == nutag_m_display) {
m_display = (void *)t->t_value;
}
/* NUTAG_M_USERNAME_REF(m_username) */
else if (t->t_tag == nutag_m_username) {
m_username = (void *)t->t_value;
}
/* NUTAG_M_PARAMS_REF(m_params) */
else if (t->t_tag == nutag_m_params) {
m_params = (void *)t->t_value;
}
/* NUTAG_M_FEATURES_REF(m_features) */
else if (t->t_tag == nutag_m_features) {
m_features = (void *)t->t_value;
}
/* NUTAG_OUTBOUND_REF(outbound) */
else if (t->t_tag == nutag_outbound) {
outbound = (void *)t->t_value;
......@@ -528,30 +607,6 @@ int nua_stack_set_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
nhp->nhp_refresher = nua_no_refresher;
}
/* Set string in handle pref structure */
#define NHP_SET_STR(nhp, name, str) \
if (str != NONE) { \
char *new_str = su_strdup(tmphome, str); \
NHP_SET(nhp, name, new_str); \
error |= (new_str != NULL && str == NULL); \
}
/* Set header in handle pref structure */
#define NHP_SET_HEADER(nhp, name, header, str) \
if (header != NONE || str != NONE) { \
sip_##name##_t *new_header; \
if (header != NONE) \
new_header = sip_##name##_dup(tmphome, header); \
else \
new_header = sip_##name##_make(tmphome, str); \
if (new_header != NULL || (header == NULL || str == NULL)) { \
NHP_SET(nhp, name, new_header); \
} \
else { \
error = 1; \
} \
}
/* Add contents of NUTAG_ALLOW() to list of currently allowed methods */
if (allow == NONE && allow_str == NONE && allowing != NULL) {
sip_allow_t *methods = sip_allow_make(tmphome, allowing);
......@@ -581,6 +636,10 @@ int nua_stack_set_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
NHP_SET_HEADER(nhp, organization, organization, organization_str);
NHP_SET_STR(nhp, instance, instance);
NHP_SET_STR(nhp, m_display, m_display);
NHP_SET_STR(nhp, m_username, m_username);
NHP_SET_STR(nhp, m_params, m_params);
NHP_SET_STR(nhp, m_features, m_features);
NHP_SET_STR(nhp, outbound, outbound);
if (!error && NHP_IS_ANY_SET(nhp)) {
......@@ -592,16 +651,16 @@ int nua_stack_set_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
if (ahp && su_home_move(nh->nh_home, tmphome) >= 0) {
memcpy(ahp, nhp, sizeof *ahp);
/* Zap pointers which are not set */
#define NHP_ZAP_UNSET_PTR(nhp, pref) \
(!(nhp)->nhp_set.set_bits.nhb_##pref ? (nhp)->nhp_##pref = NULL : NULL)
NHP_ZAP_UNSET_PTR(ahp, supported);
NHP_ZAP_UNSET_PTR(ahp, allow);
NHP_ZAP_UNSET_PTR(ahp, user_agent);
NHP_ZAP_UNSET_PTR(ahp, ua_name);
NHP_ZAP_UNSET_PTR(ahp, organization);
NHP_ZAP_UNSET_PTR(ahp, instance);
NHP_ZAP_UNSET_PTR(ahp, m_display);
NHP_ZAP_UNSET_PTR(ahp, m_username);
NHP_ZAP_UNSET_PTR(ahp, m_params);
NHP_ZAP_UNSET_PTR(ahp, m_features);
NHP_ZAP_UNSET_PTR(ahp, outbound);
nh->nh_prefs = ahp;
......@@ -613,14 +672,10 @@ int nua_stack_set_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
else if (su_home_move(nh->nh_home, tmphome) >= 0) {
/* Update prefs structure */
nua_handle_preferences_t tbf[1];
nhp->nhp_set.set_any |= ohp->nhp_set.set_any;
*tbf = *ohp; *ohp = *nhp;
/* Free changed items */
#define NHP_ZAP_OVERRIDEN(tbf, nhp, pref) \
((tbf)->nhp_set.set_bits.nhb_##pref \
&& (tbf)->nhp_##pref != (nhp)->nhp_##pref \
? su_free(nh->nh_home, (void *)(tbf)->nhp_##pref) : (void)0)
nhp_or_set(nhp, ohp);
*tbf = *ohp; *ohp = *nhp;
NHP_ZAP_OVERRIDEN(tbf, nhp, supported);
NHP_ZAP_OVERRIDEN(tbf, nhp, allow);
......@@ -628,8 +683,11 @@ int nua_stack_set_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
NHP_ZAP_OVERRIDEN(tbf, nhp, ua_name);
NHP_ZAP_OVERRIDEN(tbf, nhp, organization);
NHP_ZAP_OVERRIDEN(tbf, nhp, instance);
NHP_ZAP_OVERRIDEN(tbf, nhp, m_display);
NHP_ZAP_OVERRIDEN(tbf, nhp, m_username);
NHP_ZAP_OVERRIDEN(tbf, nhp, m_params);
NHP_ZAP_OVERRIDEN(tbf, nhp, m_features);
NHP_ZAP_OVERRIDEN(tbf, nhp, outbound);
}
else
/* Fail miserably with ENOMEM */
......@@ -650,6 +708,7 @@ int nua_stack_set_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
media_path != NONE || allow != NONE || allow_str != NONE;
#endif
/* Return when called in handle-specific way */
if (nh != dnh)
return e == nua_r_set_params ? UA_EVENT2(e, 200, "OK") : 0;
......@@ -834,13 +893,13 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
/* Include tag in list returned to user
* if it has been earlier set (by user) */
#define TIF(TAG, pref) \
TAG_IF(nhp->nhp_set.set_bits.nhb_##pref, TAG(nhp->nhp_##pref))
TAG_IF(nhp->nhp_set.nhb_##pref, TAG(nhp->nhp_##pref))
/* Include string tag made out of SIP header
* if it has been earlier set (by user) */
#define TIF_STR(TAG, pref) \
TAG_IF(nhp->nhp_set.set_bits.nhb_##pref, \
TAG(nhp->nhp_set.set_bits.nhb_##pref && nhp->nhp_##pref \
TAG_IF(nhp->nhp_set.nhb_##pref, \
TAG(nhp->nhp_set.nhb_##pref && nhp->nhp_##pref \
? sip_header_as_string(tmphome, (void *)nhp->nhp_##pref) : NULL))
lst = tl_filtered_tlist
......@@ -891,9 +950,13 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e,
TIF(SIPTAG_ORGANIZATION, organization),
TIF_STR(SIPTAG_ORGANIZATION_STR, organization),
TIF(NUTAG_INSTANCE, instance),
TIF(NUTAG_M_DISPLAY, m_display),
TIF(NUTAG_M_USERNAME, m_username),
TIF(NUTAG_M_PARAMS, m_params),
TIF(NUTAG_M_FEATURES, m_features),
TIF(NUTAG_OUTBOUND, outbound),
TIF(NUTAG_DETECT_NETWORK_UPDATES, detect_network_updates),
TIF(NUTAG_INSTANCE, instance),
TIF(NUTAG_KEEPALIVE, keepalive),
TIF(NUTAG_KEEPALIVE_STREAM, keepalive_stream),
......
......@@ -98,7 +98,12 @@ typedef struct nua_handle_preferences
char const *nhp_ua_name;
sip_organization_t *nhp_organization;
char const *nhp_m_display;
char const *nhp_m_username;
char const *nhp_m_params;
char const *nhp_m_features;
char const *nhp_instance;
/**< Outbound OPTIONS */
char const *nhp_outbound;
......@@ -106,64 +111,65 @@ typedef struct nua_handle_preferences
uint32_t nhp_detect_network_updates;
/* A bit for each feature set by application */
union {
uint32_t set_any;
struct {
unsigned nhb_retry_count:1;
unsigned nhb_max_subscriptions:1;
unsigned nhb_invite_enable:1;
unsigned nhb_auto_alert:1;
unsigned nhb_early_media:1;
unsigned nhb_only183_100rel:1;
unsigned nhb_auto_answer:1;
unsigned nhb_auto_ack:1;
unsigned nhb_invite_timeout:1;
unsigned nhb_keepalive:1;
unsigned nhb_keepalive_stream:1;
unsigned nhb_session_timer:1;
unsigned nhb_min_se:1;
unsigned nhb_refresher:1;
unsigned nhb_update_refresh:1;
unsigned nhb_message_enable:1;
unsigned nhb_win_messenger_enable:1;
unsigned nhb_message_auto_respond:1;
unsigned nhb_callee_caps:1;
unsigned nhb_media_features:1;
unsigned nhb_service_route_enable:1;
unsigned nhb_path_enable:1;
unsigned nhb_refer_with_id:1;
unsigned nhb_refer_expires:1;
unsigned nhb_substate:1;
unsigned nhb_allow:1;
unsigned nhb_supported:1;
unsigned nhb_user_agent:1;
unsigned nhb_ua_name:1;
unsigned nhb_organization:1;
unsigned nhb_instance:1;
unsigned nhb_outbound:1;
unsigned nhb_detect_network_updates:1;
unsigned :0;
} set_bits;
struct {
unsigned nhb_retry_count:1;
unsigned nhb_max_subscriptions:1;
unsigned nhb_invite_enable:1;
unsigned nhb_auto_alert:1;
unsigned nhb_early_media:1;
unsigned nhb_only183_100rel:1;
unsigned nhb_auto_answer:1;
unsigned nhb_auto_ack:1;
unsigned nhb_invite_timeout:1;
unsigned nhb_keepalive:1;
unsigned nhb_keepalive_stream:1;
unsigned nhb_session_timer:1;
unsigned nhb_min_se:1;
unsigned nhb_refresher:1;
unsigned nhb_update_refresh:1;
unsigned nhb_message_enable:1;
unsigned nhb_win_messenger_enable:1;
unsigned nhb_message_auto_respond:1;
unsigned nhb_callee_caps:1;
unsigned nhb_media_features:1;
unsigned nhb_service_route_enable:1;
unsigned nhb_path_enable:1;
unsigned nhb_refer_with_id:1;
unsigned nhb_refer_expires:1;
unsigned nhb_substate:1;
unsigned nhb_allow:1;
unsigned nhb_supported:1;
unsigned nhb_user_agent:1;
unsigned nhb_ua_name:1;
unsigned nhb_organization:1;
unsigned nhb_m_display:1;
unsigned nhb_m_username:1;
unsigned :0;
unsigned nhb_m_params:1;
unsigned nhb_m_features:1;
unsigned nhb_instance:1;
unsigned nhb_outbound:1;
unsigned nhb_detect_network_updates:1;
unsigned :0;
} nhp_set;
} nua_handle_preferences_t;
#define DNHP_GET(dnhp, pref) ((dnhp)->nhp_##pref)
#define NHP_GET(nhp, dnhp, pref) \
((nhp)->nhp_set.set_bits.nhb_##pref \
((nhp)->nhp_set.nhb_##pref \
? (nhp)->nhp_##pref : (dnhp)->nhp_##pref)
#define NHP_SET(nhp, pref, value) \
((nhp)->nhp_##pref = (value), \
(nhp)->nhp_set.set_bits.nhb_##pref = 1)
(nhp)->nhp_set.nhb_##pref = 1)
/* Check if preference is set */
#define NHP_ISSET(nhp, pref) \
((nhp)->nhp_set.set_bits.nhb_##pref)
((nhp)->nhp_set.nhb_##pref)
#define NHP_UNSET_ALL(nhp) ((nhp)->nhp_set.set_any = 0)
#define NHP_SET_ALL(nhp) ((nhp)->nhp_set.set_any = 0xffffffffU)
#define NHP_IS_ANY_SET(nhp) ((nhp)->nhp_set.set_any != 0)
#define NHP_UNSET_ALL(nhp) (memset(&(nhp)->nhp_set, 0, sizeof (nhp)->nhp_set))
#define NHP_SET_ALL(nhp) (memset(&(nhp)->nhp_set, 255, sizeof (nhp)->nhp_set))
/* Get preference from handle, if set, otherwise from default handle */
#define NH_PGET(nh, pref) \
......
This diff is collapsed.
......@@ -102,6 +102,10 @@ tag_typedef_t nutag_certificate_phrase = STRTAG_TYPEDEF(certificate_phrase);
tag_typedef_t nutag_registrar = URLTAG_TYPEDEF(registrar);
tag_typedef_t nutag_identity = PTRTAG_TYPEDEF(identity);
tag_typedef_t nutag_m_display = STRTAG_TYPEDEF(m_display);
tag_typedef_t nutag_m_username = STRTAG_TYPEDEF(m_username);
tag_typedef_t nutag_m_params = STRTAG_TYPEDEF(m_params);
tag_typedef_t nutag_m_features = STRTAG_TYPEDEF(m_features);
tag_typedef_t nutag_instance = STRTAG_TYPEDEF(instance);
tag_typedef_t nutag_outbound = STRTAG_TYPEDEF(outbound);
......
......@@ -184,6 +184,7 @@ static int outbound_contacts_from_via(outbound_t *ob,
/* ---------------------------------------------------------------------- */
/** Create a new outbound object */
outbound_t *
outbound_new(outbound_owner_t *owner,
outbound_owner_vtable const *owner_methods,
......@@ -334,7 +335,6 @@ int outbound_set_features(outbound_t *ob, char *features)
ob->ob_features = new_features;
su_free(ob->ob_home, old_features);
return 0;
}
......@@ -1005,9 +1005,9 @@ int outbound_process_request(outbound_t *ob,
int outbound_contacts_from_via(outbound_t *ob, sip_via_t const *via)
{
su_home_t *home = ob->ob_home;
char *uri;
sip_contact_t *rcontact, *dcontact;
int reg_id = 0;
char reg_id_param[20] = "";
sip_contact_t *previous_previous, *previous_rcontact, *previous_dcontact;
sip_via_t *v, v0[1], *previous_via;
int contact_uri_changed;
......@@ -1017,11 +1017,27 @@ int outbound_contacts_from_via(outbound_t *ob, sip_via_t const *via)
v = v0; *v0 = *via; v0->v_next = NULL;
dcontact = ob->ob_oo->oo_contact(ob->ob_owner, home,
NULL, v, v->v_protocol, NULL);
if (ob->ob_instance && ob->ob_reg_id != 0)
snprintf(reg_id_param, sizeof reg_id_param, ";reg-id=%u", ob->ob_reg_id);
rcontact = ob->ob_oo->oo_contact(ob->ob_owner, home,
NULL, v, v->v_protocol,
ob->ob_features ? ob->ob_features : "",
ob->ob_instance, reg_id_param, NULL);
#if 0
char *uri;
/* uri contains < > */
uri = sip_contact_string_from_via(NULL, via, NULL, v->v_protocol);
dcontact = sip_contact_make(home, uri);
if (ob->ob_instance) {
char reg_id[20];
......@@ -1040,9 +1056,10 @@ int outbound_contacts_from_via(outbound_t *ob, sip_via_t const *via)
else
rcontact = dcontact;
v = sip_via_dup(home, v);
free(uri);
#endif
v = sip_via_dup(home, v);
if (!rcontact || !dcontact || !v) {
msg_header_free(home, (void *)dcontact);
......@@ -1106,7 +1123,7 @@ int outbound_contacts_from_via(outbound_t *ob, sip_via_t const *via)
*/
int outbound_set_contact(outbound_t *ob,
sip_contact_t const *application_contact,
sip_contact_t const *stack_contact,
sip_via_t const *v,
int terminating)
{
su_home_t *home = ob->ob_home;
......@@ -1129,33 +1146,30 @@ int outbound_set_contact(outbound_t *ob,
previous = ob->ob_contacts ? ob->ob_rcontact : NULL;
}
}
else if (stack_contact) {
char reg_id[20];
else if (v) {
char const *tport = !v->v_next ? v->v_protocol : NULL;
char reg_id_param[20];
if (!ob->ob_rcontact ||
url_cmp_all(ob->ob_rcontact->m_url, stack_contact->m_url)) {
contact_uri_changed = 1;
previous = ob->ob_contacts ? ob->ob_rcontact : NULL;
}
dcontact = sip_contact_copy(home, stack_contact);
dcontact = ob->ob_oo->oo_contact(ob->ob_owner, home,
NULL, v, tport, NULL);
if (!dcontact)
return -1;
if (ob->ob_instance && ob->ob_reg_id)
snprintf(reg_id, sizeof reg_id, ";reg-id=%u", ob->ob_reg_id);
else
strcpy(reg_id, "");
if (ob->ob_instance && ob->ob_reg_id != 0)
snprintf(reg_id_param, sizeof reg_id_param, ";reg-id=%u", ob->ob_reg_id);
rcontact = sip_contact_format(home, "<" URL_PRINT_FORMAT ">%s%s%s%s%s",
URL_PRINT_ARGS(dcontact->m_url),
ob->ob_instance ? ";" : "",
ob->ob_instance ? ob->ob_instance : "",
reg_id,
ob->ob_features ? ";" : "",
ob->ob_dcontact ? ob->ob_features : "");
rcontact = ob->ob_oo->oo_contact(ob->ob_owner, home,
NULL, v, v->v_protocol,
ob->ob_features ? ob->ob_features : "",
ob->ob_instance, reg_id_param, NULL);
if (!rcontact)
return -1;
if (!ob->ob_rcontact ||
url_cmp_all(ob->ob_rcontact->m_url, rcontact->m_url)) {
contact_uri_changed = 1;
previous = ob->ob_contacts ? ob->ob_rcontact : NULL;
}
}
ob->ob_by_stack = application_contact == NULL;
......
......@@ -97,7 +97,7 @@ enum {
int outbound_set_contact(outbound_t *ob,
sip_contact_t const *application_contact,
sip_contact_t const *stack_contact,
sip_via_t const *v,
int terminating);
sip_contact_t const *outbound_dialog_contact(outbound_t const *ob);
......@@ -120,6 +120,13 @@ void outbound_peer_info(outbound_t *ob, sip_t const *sip);
struct outbound_owner_vtable
{
int oo_size;
sip_contact_t *(*oo_contact)(outbound_owner_t *,
su_home_t *home,
char const *extra_username,
sip_via_t const *v,
char const *transport,
char const *m_param,
...);
int (*oo_refresh)(outbound_owner_t *, outbound_t *ob);
int (*oo_status)(outbound_owner_t *, outbound_t *ob,
int status, char const *phrase,
......
......@@ -770,7 +770,7 @@ SOFIAPUBVAR tag_typedef_t nutag_certificate_phrase;
nutag_certificate_phrase_ref, tag_str_vr((&x))
SOFIAPUBVAR tag_typedef_t nutag_certificate_phrase_ref;
/** Local SIPS url
/** Local SIPS url.
*
* The application can specify an alternative local address for
* NUA user agent engine. Usually the alternative address is a
......@@ -1078,28 +1078,146 @@ SOFIAPUBVAR tag_typedef_t nutag_authtime;
#define NUTAG_AUTHTIME_REF(x) nutag_authtime_ref, tag_uint_vr(&(x))
SOFIAPUBVAR tag_typedef_t nutag_authtime_ref;
/** Events
/**Display name for @Contact.
*
* Specify display name for the Contact header URI generated for
* registration request and dialog-creating requests/responses.
*
* Note that display name is not included the request-URI when proxy
* forwards the request towards user-agent.
*
* @par Used with
* Currently not processed by NUA
* nua_register(), nua_set_hparams(), nua_set_params().
*
* @par Parameter type
* string (char *)
*
* @par Values
* Valid display name.
*
* @sa NUTAG_M_USERNAME(), NUTAG_M_PARAMS(), NUTAG_M_FEATURES(),
* NUTAG_CALLEE_CAPS().
*
* Corresponding tag taking reference parameter is NUTAG_M_DISPLAY_REF()
*/
#define NUTAG_M_DISPLAY(x) nutag_m_display, tag_str_v(x)
SOFIAPUBVAR tag_typedef_t nutag_m_display;
#define NUTAG_M_DISPLAY_REF(x) nutag_m_display_ref, tag_str_vr(&(x))
SOFIAPUBVAR tag_typedef_t nutag_m_display_ref;
/**Username prefix for @Contact.
*
* Specify username part for the Contact header URI generated for
* registration request and dialog-creating requests/responses.
*
* Using username, application can make multiple registrations using
* multiple identities, or it can distinguish between different logical
* destinations.
*
* @par Used with
* nua_register(), nua_set_hparams(), nua_set_params().
*
* @par Parameter type
* string (char *)
*
* @par Values
* Valid SIP username.
*
* @sa NUTAG_M_DISPLAY(), NUTAG_M_PARAMS(), NUTAG_M_FEATURES(),
* NUTAG_CALLEE_CAPS().
*
* Corresponding tag taking reference parameter is NUTAG_M_USERNAME_REF()
*/
#define NUTAG_M_USERNAME(x) nutag_m_username, tag_str_v(x)
SOFIAPUBVAR tag_typedef_t nutag_m_username;
#define NUTAG_M_USERNAME_REF(x) nutag_m_username_ref, tag_str_vr(&(x))
SOFIAPUBVAR tag_typedef_t nutag_m_username_ref;
/**URL parameters for @Contact.
*
* Specify URL parameters for the Contact header URI generated for
* registration request and dialog-creating requests/responses.
*
* Please note that some proxies may remove even the non-transport
* parameters from the request-URI when they forward the request towards
* user-agent.
*
* @par Used with
* nua_register(), nua_set_hparams(), nua_set_params().
*
* @par Parameter type
* string (char *)
*
* @par Values
* Semicolon-separated URL parameters.
*
* @sa NUTAG_M_DISPLAY(), NUTAG_M_USERNAME(), NUTAG_M_FEATURES(),
* NUTAG_CALLEE_CAPS().
*
* Corresponding tag taking reference parameter is NUTAG_M_PARAMS_REF()
*/
#define NUTAG_M_PARAMS(x) nutag_m_params, tag_str_v(x)
SOFIAPUBVAR tag_typedef_t nutag_m_params;
#define NUTAG_M_PARAMS_REF(x) nutag_m_params_ref, tag_str_vr(&(x))
SOFIAPUBVAR tag_typedef_t nutag_m_params_ref;
/**Header parameters for registration @Contact.
*
* Specify header parameters for the @Contact header generated for
* registration request and dialog-creating requests/responses. Such header
* parameters include "q", indicating preference for the @Contact URI, and
* "expires", indicating the desired expiration time for the registration.
*
* Additional header parameters are typically media feature tags, specified in
* @RFC3840. If NUTAG_CALLEE_CAPS(1) is specified, additional @Contact header
* parameters are generated based on SDP capabilities and SIP @Allow header.
*
* When using the "outbound" extension option, the stack will also add
* "+sip.instance" and "reg-id" header parameters to the @Contact.