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

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) \
......
......@@ -79,7 +79,7 @@
/* Registrations and contacts */
int nua_registration_from_via(nua_registration_t **list,
su_home_t *home,
nua_handle_t *nh,
sip_via_t const *via,
int public);
......@@ -90,7 +90,7 @@ void nua_registration_remove(nua_registration_t *nr);
int nua_registration_set_aor(su_home_t *, nua_registration_t *nr,
sip_from_t const *aor);
int nua_registration_set_contact(su_home_t *,
int nua_registration_set_contact(nua_handle_t *,
nua_registration_t *nr,
sip_contact_t const *m,
int terminating);
......@@ -120,6 +120,7 @@ struct register_usage {
nua_registration_t *nr_next, **nr_prev, **nr_list; /* Doubly linked list and its head */
sip_from_t *nr_aor; /**< AoR for this registration, NULL if none */
sip_contact_t *nr_contact; /**< Our Contact */
sip_via_t *nr_via; /**< Corresponding Via headers */
/** Status of registration */
unsigned nr_ready:1;
......@@ -228,6 +229,14 @@ static int process_response_to_register(nua_handle_t *nh,
static void unregister_expires_contacts(msg_t *msg, sip_t *sip);
/* Interface towards outbound_t */
sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh,
su_home_t *home,
char const *extra_username,
sip_via_t const *v,
char const *transport,
char const *m_param,
...);
static int nua_stack_outbound_features(nua_handle_t *nh, outbound_t *ob);
static int nua_stack_outbound_refresh(nua_handle_t *,
......@@ -247,6 +256,7 @@ static int nua_stack_outbound_credentials(nua_handle_t *, auth_client_t **auc);
outbound_owner_vtable nua_stack_outbound_callbacks = {
sizeof nua_stack_outbound_callbacks,
nua_handle_contact_by_via,
nua_stack_outbound_refresh,
nua_stack_outbound_status,
nua_stack_outbound_failed,
......@@ -271,24 +281,85 @@ outbound_owner_vtable nua_stack_outbound_callbacks = {
*
* @par Related tags:
* NUTAG_REGISTRAR(), NUTAG_INSTANCE(), NUTAG_OUTBOUND(),
* NUTAG_KEEPALIVE(), NUTAG_KEEPALIVE_STREAM(),
* NUTAG_KEEPALIVE(), NUTAG_KEEPALIVE_STREAM(), NUTAG_M_USERNAME(),
* NUTAG_M_PARAMS(), NUTAG_M_FEATURES()
*
* @par Events:
* #nua_r_register, #nua_i_outbound
*
* @par Generating Contact Header
*
* If the application did not specify the Contact header in the tags,
* nua_register() will generate one. It will obtain the schema, IP address
* for the host and port number for the Contact URI from the transport
* socket. The diplay name is taken from NUTAG_M_DISPLAY(), URL username
* part is taken from NUTAG_M_USERNAME(), URI parameters from
* NUTAG_M_PARAMS(), and Contact header parameters from NUTAG_M_FEATURES().
* If NUTAG_CALLEE_CAPS(1) is specified, additional Contact header
* parameters are generated based on SDP capabilities and SIP @Allow header.
*
* Note that @b nua may append a identifier of its own to the @Contact URI
* username. Such nua-generated identifier trailer always starts with "="
* (equal sign), rest of the nua-generated identifier may contain any
* url-unreserved characters except "=".
*
* Likewise, nua may add transport parameters (such as "transport=tcp" or
* "maddr") to the @Contact URI. It can add addtional header parameters, like
* "+sip.instance" or "reg-id", too.
*
* For instance, if application uses tags like
* @code
* nua_register(nh,
* NUTAG_M_DISPLAY("1"),
* NUTAG_M_USERNAME("line-1"),
* NUTAG_M_PARAMS("user=phone"),
* NUTAG_M_FEATURES("audio"),
* NUTAG_CALLEE_CAPS(0),
* TAG_END())
* @endcode
* @b nua can generate a Contact header like
* @code
* Contact: 1 <sip:line-1=SSQAIbjv@192.168.1.200;transport=tcp;user=phone>
* ;audio;reg-id=1
* ;+sip.instance=urn:uuid:97701ad9-39df-1229-1083-dbc0a85f029c
* @endcode
*
* The incoming request from the proxy should contain the registered contact
* URI as the request URI. The application can use the username prefix set
* by NUTAG_M_USERNAME() and the non-transport parameters of the request URI
* set by NUTAG_M_PARAMS() when determining to which registration the
* incoming request belongs.
*
* For example, a request line correspoding to the @Contact in above example
* may look like:
* @code
* INVITE sip:line-1=SSQAIbjv@192.168.1.200;user=phone SIP/2.0
* @endcode
*
* @sa NUTAG_M_DISPLAY(), NUTAG_M_USERNAME(), NUTAG_M_PARAMS(),
* NUTAG_M_FEATURES(), NUTAG_CALLEE_CAPS().
*
* @par NAT, Firewall and Outbound Support
*
* If the application did not include the Contact header in the tags,
* nua_register() will generate one and start a protocol engine for outbound
* connections used for NAT and firewall traversal and connectivity checks.
* Normally, @b nua will start start a protocol engine for outbound
* connections used for NAT and firewall traversal and connectivity checks
* when registering.
*
* First, nua_register() will probe for NATs in between UA and registrar. It
* will send a REGISTER request as usual. Upon receiving the response it
* checks for the presence of valid "received" and "rport" parameters in the
* Via header returned by registrar. The presence of NAT is determined from
* the "received" parameter in a Via header. When a REGISTER request was
* sent, the stack inserted the source IP address in the Via header: if that
* is different from the source IP address seen by the registrar, the
* @note If the application provides @b nua with a
* @Contact header of its own (or includes a SIPTAG_CONTACT(NULL) tag in
* nua_register() tags), the outbound protocol engine is not started. It is
* assumed that the application knows better what it is doing when it sets
* the @Contact, or it is using experimental CPL upload as specified in
* <a href="http://www.ietf.org/internet-drafts/draft-lennox-sip-reg-payload-01.txt">
* draft-lennox-sip-reg-payload-01.txt</a>.
*
* First, outbound engine will probe for NATs in between UA and registrar.
* It will send a REGISTER request as usual. Upon receiving the response it
* checks for the presence of "received" and "rport" parameters in the Via
* header returned by registrar. The presence of NAT is determined from the
* "received" parameter in a Via header. When a REGISTER request was sent,
* the stack inserted the actual source IP address in the Via header: if
* that is different from the source IP address seen by the registrar, the
* registrar inserts the source IP address it sees into the "received"
* parameter.
*
......@@ -296,8 +367,8 @@ outbound_owner_vtable nua_stack_outbound_callbacks = {
* headers in outbound requests and again in incoming responses will make
* the above-described NAT check to fail.
*
* The response to the initial REGISTER should also include feature tags
* indicating whether registrar supports various SIP extensions: @e
* The response to the initial REGISTER should also include option tags
* indicating whether registrar supports various SIP extension options: @e
* outbound, @e pref, @e path, @e gruu.
*
* Basically, @e outbound means that instead of registering its contact URI
......@@ -438,7 +509,6 @@ outbound_owner_vtable nua_stack_outbound_callbacks = {
* @param tags empty
*/
int
nua_stack_register(nua_t *nua, nua_handle_t *nh, nua_event_t e,
tagi_t const *tags)
......@@ -495,7 +565,7 @@ nua_stack_register(nua_t *nua, nua_handle_t *nh, nua_event_t e,
/* Add Expires: 0 and remove the expire parameters from contacts */
unregister_expires_contacts(msg, sip);