[Freeswitch-svn] [commit] r4923 - in freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua: iptsec iptsec/sofia-sip nta nua nua/sofia-sip sdp sip
Freeswitch SVN
mikej at freeswitch.org
Fri Apr 13 10:33:32 EDT 2007
Author: mikej
Date: Fri Apr 13 10:33:30 2007
New Revision: 4923
Modified:
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/iptsec/Doxyfile
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/iptsec/auth_client.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/iptsec/sofia-sip/auth_client_plugin.h
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nta/nta.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_common.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_extension.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.h
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_publish.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_register.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_registrar.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_tag.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua.h
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua_tag.h
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_100rel.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_basic_call.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_call_reject.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_cancel_bye.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_nua.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_offer_answer.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_proxy.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_proxy.h
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_register.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_session_timer.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_simple.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/sdp/run_test_sdp
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/sip/sip_feature.c
freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/sip/torture_sip.c
Log:
sync with current darcs tree
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/iptsec/Doxyfile
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/iptsec/Doxyfile (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/iptsec/Doxyfile Fri Apr 13 10:33:30 2007
@@ -19,3 +19,6 @@
GENERATE_TAGFILE = ../docs/iptsec.doxytags
ALIASES +=
+
+PREDEFINED += SOFIA_EXTEND_AUTH_CLIENT=1
+
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/iptsec/auth_client.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/iptsec/auth_client.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/iptsec/auth_client.c Fri Apr 13 10:33:30 2007
@@ -31,6 +31,8 @@
#include "config.h"
+#define SOFIA_EXTEND_AUTH_CLIENT 1
+
#include <sofia-sip/su.h>
#include <sofia-sip/su_md5.h>
@@ -77,9 +79,7 @@
char const *user,
char const *pass);
-static int ca_clear_credentials(auth_client_t *ca,
- char const *scheme,
- char const *realm);
+static int ca_clear_credentials(auth_client_t *ca);
/** Initialize authenticators.
@@ -340,8 +340,8 @@
* @param[in] user username
* @param[in] pass password
*
- * @retval number of matching clients
- * @retval 0 when no matching client was found
+ * @retval number of updated clients
+ * @retval 0 when no client was updated
* @retval -1 upon an error
*/
int auc_all_credentials(auth_client_t **auc_list,
@@ -375,6 +375,9 @@
char const *user,
char const *pass)
{
+ char *new_user, *new_pass;
+ char *old_user, *old_pass;
+
assert(ca);
if (!ca || !ca->ca_scheme || !ca->ca_realm)
@@ -384,12 +387,24 @@
(realm != NULL && strcmp(realm, ca->ca_realm)))
return -1;
- ca->ca_user = su_strdup(ca->ca_home, user);
- ca->ca_pass = su_strdup(ca->ca_home, pass);
+ old_user = ca->ca_user, old_pass = ca->ca_pass;
+
+ if (str0cmp(user, old_user) == 0 && str0cmp(pass, old_pass) == 0)
+ return 0;
+
+ new_user = su_strdup(ca->ca_home, user);
+ new_pass = su_strdup(ca->ca_home, pass);
- if (!ca->ca_user || !ca->ca_pass)
+ if (!new_user || !new_pass)
return -1;
+ ca->ca_user = new_user, ca->ca_pass = new_pass;
+ if (AUTH_CLIENT_IS_EXTENDED(ca))
+ ca->ca_clear = 0;
+
+ su_free(ca->ca_home, old_user);
+ su_free(ca->ca_home, old_pass);
+
return 1;
}
@@ -416,12 +431,15 @@
char *u, *p;
if (!ca->ca_user || !ca->ca_pass)
continue;
+ if (AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear)
+ continue;
if (!ca->ca_scheme[0] || strcmp(ca->ca_scheme, d->ca_scheme))
continue;
if (!ca->ca_realm[0] || strcmp(ca->ca_realm, d->ca_realm))
continue;
- if (d->ca_user && strcmp(d->ca_user, ca->ca_user) == 0 &&
+ if (!(AUTH_CLIENT_IS_EXTENDED(d) && d->ca_clear) &&
+ d->ca_user && strcmp(d->ca_user, ca->ca_user) == 0 &&
d->ca_pass && strcmp(d->ca_pass, ca->ca_pass) == 0) {
retval++;
break;
@@ -435,6 +453,9 @@
if (d->ca_user) su_free(d->ca_home, (void *)d->ca_user);
if (d->ca_pass) su_free(d->ca_home, (void *)d->ca_pass);
d->ca_user = u, d->ca_pass = p;
+ if (AUTH_CLIENT_IS_EXTENDED(d))
+ d->ca_clear = 0;
+
retval++;
break;
}
@@ -457,13 +478,24 @@
* @retval -1 upon an error
*/
int auc_clear_credentials(auth_client_t **auc_list,
- char const *scheme,
- char const *realm)
+ char const *scheme,
+ char const *realm)
{
int retval = 0;
+ int match;
for (; *auc_list; auc_list = &(*auc_list)->ca_next) {
- int match = ca_clear_credentials(*auc_list, scheme, realm);
+ auth_client_t *ca = *auc_list;
+
+ if (!AUTH_CLIENT_IS_EXTENDED(ca))
+ continue;
+
+ if ((scheme != NULL && strcasecmp(scheme, ca->ca_scheme)) ||
+ (realm != NULL && strcmp(realm, ca->ca_realm)))
+ continue;
+
+ match = ca->ca_auc->auc_clear(*auc_list);
+
if (match < 0) {
retval = -1;
break;
@@ -476,21 +508,14 @@
}
static
-int ca_clear_credentials(auth_client_t *ca,
- char const *scheme,
- char const *realm)
+int ca_clear_credentials(auth_client_t *ca)
{
- assert(ca);
-
- if (!ca || !ca->ca_scheme || !ca->ca_realm)
- return -1;
+ assert(ca); assert(ca->ca_home->suh_size >= (int)(sizeof *ca));
- if ((scheme != NULL && strcasecmp(scheme, ca->ca_scheme)) ||
- (realm != NULL && strcmp(realm, ca->ca_realm)))
+ if (!ca)
return -1;
- su_free(ca->ca_home, (void *)ca->ca_user), ca->ca_user = NULL;
- su_free(ca->ca_home, (void *)ca->ca_pass), ca->ca_pass = NULL;
+ ca->ca_clear = 1;
return 1;
}
@@ -513,6 +538,8 @@
for (ca = *auc_list; ca; ca = ca->ca_next) {
if (!ca->ca_user || !ca->ca_pass || !ca->ca_credential_class)
return 0;
+ if (AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear)
+ return 0;
}
return 1;
@@ -570,8 +597,11 @@
if (!ca->ca_auc)
continue;
- if (ca->ca_auc->auc_authorize(ca, home, method, url, body, &h) < 0
- || msg_header_insert(msg, pub, h) < 0)
+ if (ca->ca_auc->auc_authorize(ca, home, method, url, body, &h) < 0)
+ return -1;
+ if (h == NULL)
+ continue;
+ if (msg_header_insert(msg, pub, h) < 0)
return -1;
}
@@ -639,14 +669,15 @@
msg_payload_t const *body,
msg_header_t **);
-const auth_client_plugin_t ca_basic_plugin =
+static const auth_client_plugin_t ca_basic_plugin =
{
/* auc_plugin_size: */ sizeof ca_basic_plugin,
/* auc_size: */ sizeof (auth_client_t),
/* auc_name: */ "Basic",
/* auc_challenge: */ NULL,
/* auc_authorize: */ auc_basic_authorization,
- /* auc_info: */ NULL
+ /* auc_info: */ NULL,
+ /* auc_clear: */ ca_clear_credentials
};
/**Create a basic authorization header.
@@ -683,6 +714,9 @@
if (user == NULL || pass == NULL)
return -1;
+ if (AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear)
+ return 0;
+
ulen = strlen(user), plen = strlen(pass), uplen = ulen + 1 + plen;
b64len = BASE64_SIZE(uplen);
basiclen = strlen("Basic ") + b64len;
@@ -746,7 +780,8 @@
/* auc_name: */ "Digest",
/* auc_challenge: */ auc_digest_challenge,
/* auc_authorize: */ auc_digest_authorization,
- /* auc_info: */ auc_digest_info
+ /* auc_info: */ auc_digest_info,
+ /* auc_clear: */ ca_clear_credentials
};
/** Store a digest authorization challenge.
@@ -826,9 +861,9 @@
* sip_authorization_class or sip_proxy_authorization_class, as well as
* http_authorization_class or http_proxy_authorization_class.
*
- * @return
- * Returns a pointer to newly created authorization header, or NULL upon an
- * error.
+ * @retval 1 when authorization headers has been created
+ * @retval 0 when there is no credentials
+ * @retval -1 upon an error
*/
static
int auc_digest_authorization(auth_client_t *ca,
@@ -854,6 +889,9 @@
auth_response_t ar[1] = {{ 0 }};
char ncount[17];
+ if (!user || !pass || (AUTH_CLIENT_IS_EXTENDED(ca) && ca->ca_clear))
+ return 0;
+
ar->ar_size = sizeof(ar);
ar->ar_username = user;
ar->ar_realm = ac->ac_realm;
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/iptsec/sofia-sip/auth_client_plugin.h
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/iptsec/sofia-sip/auth_client_plugin.h (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/iptsec/sofia-sip/auth_client_plugin.h Fri Apr 13 10:33:30 2007
@@ -29,6 +29,9 @@
/**@file sofia-sip/auth_client_plugin.h
* @brief Client-side plugin interface for authentication
*
+ * @note For extensions in 1.12.6 or later,
+ * you have to #define SOFIA_EXTEND_AUTH_CLIENT to 1.
+ *
* @author Pekka Pessi <Pekka.Pessi at nokia.com>
*
* @date Created: Fri May 19 16:18:21 EEST 2006
@@ -58,6 +61,10 @@
char *ca_pass;
msg_hclass_t *ca_credential_class;
+
+#if SOFIA_EXTEND_AUTH_CLIENT
+ int ca_clear;
+#endif
};
struct auth_client_plugin
@@ -81,8 +88,19 @@
/** Store nextnonce from Authentication-Info or Proxy-Authentication-Info. */
int (*auc_info)(auth_client_t *ca, msg_auth_info_t const *ai);
+
+#if SOFIA_EXTEND_AUTH_CLIENT
+ /** Clear credentials (user/pass). @NEW_1_12_6 */
+ int (*auc_clear)(auth_client_t *ca);
+#endif
};
+/** Check if authentication client has been extended. @NEW_1_12_6 */
+#define AUTH_CLIENT_IS_EXTENDED(ca) \
+ ((ca)->ca_auc->auc_plugin_size > \
+ offsetof(auth_client_plugin_t, auc_clear) \
+ && (ca)->ca_auc->auc_clear != NULL)
+
SOFIA_END_DECLS
#endif /* !defined AUTH_CLIENT_PLUGIN_H */
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nta/nta.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nta/nta.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nta/nta.c Fri Apr 13 10:33:30 2007
@@ -8016,7 +8016,7 @@
{
nta_agent_t *sa = orq->orq_agent;
short orq_status = orq->orq_status;
- int internal = sip == NULL || (sip->sip_flags & NTA_INTERNAL_MSG) == 0;
+ int internal = sip == NULL || (sip->sip_flags & NTA_INTERNAL_MSG) != 0;
if (status < 100) status = 100;
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_common.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_common.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_common.c Fri Apr 13 10:33:30 2007
@@ -216,6 +216,50 @@
return su_strdup(home, str);
}
+/** Check if event is a request that can be responded with nua_respond().
+ *
+ * Note that if event status is 200 or greater, it already has been
+ * responded. This function is provided for compatibility with future
+ * versions of nua. An unknown event can always be handled in the event
+ * callback like this:
+ * @code
+ * switch (event) {
+ * ...
+ * default:
+ * if (status < 200 && nua_event_is_incoming_request(event))
+ * nua_respond(nh, SIP_501_NOT_IMPLEMENTED,
+ * NUTAG_WITH_THIS(nua), TAG_END());
+ * if (hmagic == NULL)
+ * nua_handle_destroy(nh);
+ * return;
+ * ...
+ * @endcode
+ *
+ * @sa #nua_event_t, nua_respond()
+ *
+ * @NEW_1_12_6
+ */
+int nua_event_is_incoming_request(nua_event_t event)
+{
+ switch (event) {
+ case nua_i_invite: return 1;
+ case nua_i_cancel: return 1;
+ case nua_i_register: return 1;
+ case nua_i_bye: return 1;
+ case nua_i_options: return 1;
+ case nua_i_refer: return 1;
+ case nua_i_publish: return 1;
+ case nua_i_prack: return 1;
+ case nua_i_info: return 1;
+ case nua_i_update: return 1;
+ case nua_i_message: return 1;
+ case nua_i_subscribe: return 1;
+ case nua_i_notify: return 1;
+ case nua_i_method: return 1;
+ default: return 0;
+ }
+}
+
/** Get name for a NUA event. */
char const *nua_event_name(nua_event_t event)
{
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c Fri Apr 13 10:33:30 2007
@@ -443,24 +443,6 @@
ds->ds_terminating = 0;
}
-
-/**@internal
- * Set expiration time.
- */
-void nua_dialog_usage_set_expires(nua_dialog_usage_t *du,
- unsigned delta)
-{
- if (delta) {
- sip_time_t now = sip_now(), expires = now + delta;
- if (expires < now)
- expires = SIP_TIME_MAX;
- du->du_expires = expires;
- nua_dialog_usage_set_refresh(du, delta);
- }
- else
- du->du_expires = 0, du->du_refresh = 0;
-}
-
/**@internal
* Set refresh value suitably.
*
@@ -514,6 +496,15 @@
du->du_refresh = target;
}
+/** Set absolute refresh time */
+void nua_dialog_usage_refresh_at(nua_dialog_usage_t *du,
+ sip_time_t target)
+{
+ SU_DEBUG_7(("nua(): refresh %s after %lu seconds\n",
+ nua_dialog_usage_name(du), target - sip_now()));
+ du->du_refresh = target;
+}
+
/**@internal Do not refresh. */
void nua_dialog_usage_reset_refresh(nua_dialog_usage_t *du)
{
@@ -561,8 +552,13 @@
return 1;
}
-/** (Gracefully) terminate usage */
-void nua_dialog_usage_shutdown(nua_owner_t *owner,
+/** (Gracefully) terminate usage.
+ *
+ * @retval >0 shutdown done
+ * @retval 0 shutdown in progress
+ * @retval <0 try again later
+ */
+int nua_dialog_usage_shutdown(nua_owner_t *owner,
nua_dialog_state_t *ds,
nua_dialog_usage_t *du)
{
@@ -570,6 +566,8 @@
du->du_refresh = 0;
du->du_shutdown = 1;
assert(du->du_class->usage_shutdown);
- du->du_class->usage_shutdown(owner, ds, du);
+ return du->du_class->usage_shutdown(owner, ds, du);
}
+ else
+ return 200;
}
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h Fri Apr 13 10:33:30 2007
@@ -112,6 +112,7 @@
unsigned sr_event:1; /**< Reported to application */
unsigned sr_initial:1; /**< Handle was created by this request */
unsigned sr_add_contact:1; /**< Add Contact header to the response */
+ unsigned sr_target_refresh:1; /**< Refresh target */
unsigned sr_terminating:1; /**< Terminate usage after final response */
unsigned sr_gracefully:1; /**< Terminate usage gracefully */
@@ -299,6 +300,7 @@
unsigned cr_auto:1; /**< Request was generated by stack */
unsigned cr_has_contact:1; /**< Request has user Contact */
unsigned cr_contactize:1; /**< Request needs Contact */
+ unsigned cr_dialog:1; /**< Request can initiate dialog */
/* Current state */
unsigned cr_challenged:1; /**< Request was challenged */
@@ -396,7 +398,6 @@
* Non-zero if the usage is established, SIP_TIME_MAX if there no
* expiration time.
*/
- sip_time_t du_expires;
sip_time_t du_refresh; /**< When to refresh */
@@ -439,13 +440,14 @@
int nua_dialog_shutdown(nua_owner_t *owner, nua_dialog_state_t *ds);
-void nua_dialog_usage_set_expires(nua_dialog_usage_t *du, unsigned delta);
-
void nua_dialog_usage_set_refresh(nua_dialog_usage_t *du, unsigned delta);
void nua_dialog_usage_refresh_range(nua_dialog_usage_t *du,
unsigned min, unsigned max);
+void nua_dialog_usage_refresh_at(nua_dialog_usage_t *du,
+ sip_time_t target);
+
void nua_dialog_usage_reset_refresh(nua_dialog_usage_t *du);
void nua_dialog_usage_refresh(nua_owner_t *owner,
@@ -453,9 +455,9 @@
nua_dialog_usage_t *du,
sip_time_t now);
-void nua_dialog_usage_shutdown(nua_owner_t *owner,
- nua_dialog_state_t *ds,
- nua_dialog_usage_t *du);
+int nua_dialog_usage_shutdown(nua_owner_t *owner,
+ nua_dialog_state_t *ds,
+ nua_dialog_usage_t *du);
static inline
int nua_dialog_is_established(nua_dialog_state_t const *ds)
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_extension.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_extension.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_extension.c Fri Apr 13 10:33:30 2007
@@ -75,7 +75,7 @@
{
/* create_dialog */ 0,
/* in_dialog */ 0,
- /* target_refresh */ 0
+ /* target_refresh */ 1,
},
/* nua_method_client_template */ NULL,
/* nua_method_client_init */ NULL,
@@ -146,7 +146,7 @@
SIP_METHOD_UNKNOWN,
nua_i_method, /* Event */
{
- 0, /* Do not create dialog */
+ 1, /* Do create dialog */
0, /* Can be an initial request */
1, /* Perhaps a target refresh request? */
1, /* Add a contact? */
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c Fri Apr 13 10:33:30 2007
@@ -135,7 +135,7 @@
* (or SIPTAG_ALLOW_EVENTS() or SIPTAG_ALLOW_EVENTS_STR()). The application
* can decide whether to accept the SUBSCRIBE request or reject it. The
* nua_response() call responding to a SUBSCRIBE request must have
- * NUTAG_WITH() (or NUTAG_WITH_CURRENT()/NUTAG_WITH_SAVED()) tag.
+ * NUTAG_WITH() (or NUTAG_WITH_THIS()/NUTAG_WITH_SAVED()) tag.
*
* If the application accepts the SUBSCRIBE request, it must immediately
* send an initial NOTIFY establishing the dialog. This is because the
@@ -690,9 +690,15 @@
SIPTAG_EVENT(du ? du->du_event : NULL),
TAG_NEXT(tags));
- if (nu && nu->nu_requested && du->du_cr == cr)
- /* Re-SUBSCRIBEd while NOTIFY was in progress, resend NOTIFY */
- nua_client_resend_request(cr, 0);
+ if (du && du->du_cr == cr && !cr->cr_terminated) {
+ if (nu->nu_requested) {
+ /* Re-SUBSCRIBEd while NOTIFY was in progress, resend NOTIFY */
+ nua_client_resend_request(cr, 0);
+ }
+ else if (nu->nu_expires) {
+ nua_dialog_usage_refresh_at(du, nu->nu_expires);
+ }
+ }
return 0;
}
@@ -710,7 +716,7 @@
if (cr) {
int terminating = 0;
- if (du->du_expires && du->du_expires <= now)
+ if (nu->nu_expires && nu->nu_expires <= now)
terminating = 1;
else if (nu->nu_requested && nu->nu_requested <= now)
terminating = 1;
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c Fri Apr 13 10:33:30 2007
@@ -149,9 +149,10 @@
NHP_SET(nhp, auto_ack, 1);
NHP_SET(nhp, invite_timeout, 120);
- NHP_SET(nhp, session_timer, 1800);
+ nhp->nhp_session_timer = 1800;
+ nhp->nhp_refresher = nua_no_refresher;
+
NHP_SET(nhp, min_se, 120);
- NHP_SET(nhp, refresher, nua_no_refresher);
NHP_SET(nhp, update_refresh, 0);
NHP_SET(nhp, message_enable, 1);
@@ -1503,6 +1504,11 @@
#define TIF(TAG, pref) \
TAG_IF(nhp->nhp_set.nhb_##pref, TAG(nhp->nhp_##pref))
+ /* Include tag in the list returned to user
+ * if it has been earlier set (by user) returning default parameters */
+#define TIFD(TAG, pref) \
+ TAG_IF(nh == dnh || 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) \
@@ -1540,9 +1546,9 @@
TIF(NUTAG_AUTOACK, auto_ack),
TIF(NUTAG_INVITE_TIMER, invite_timeout),
- TIF(NUTAG_SESSION_TIMER, session_timer),
+ TIFD(NUTAG_SESSION_TIMER, session_timer),
TIF(NUTAG_MIN_SE, min_se),
- TIF(NUTAG_SESSION_REFRESHER, refresher),
+ TIFD(NUTAG_SESSION_REFRESHER, refresher),
TIF(NUTAG_UPDATE_REFRESH, update_refresh),
TIF(NUTAG_ENABLEMESSAGE, message_enable),
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.h
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.h (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.h Fri Apr 13 10:33:30 2007
@@ -169,8 +169,8 @@
unsigned nhb_allow:1;
unsigned nhb_supported:1;
- unsigned nhb_allow_events:1;
unsigned :0; /* at most 32 bits ... */
+ unsigned nhb_allow_events:1;
unsigned nhb_user_agent:1;
unsigned nhb_organization:1;
@@ -226,4 +226,9 @@
(NHP_ISSET((nh)->nh_prefs, pref) && \
(nh)->nh_nua->nua_dhandle->nh_prefs != (nh)->nh_prefs)
+/* Check if preference has been set by applicationx */
+#define NUA_PISSET(nua, nh, pref) \
+ (NHP_ISSET((nua)->nua_dhandle->nh_prefs, pref) || \
+ ((nh) && NHP_ISSET((nh)->nh_prefs, pref)))
+
#endif /* NUA_PARAMS_H */
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_publish.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_publish.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_publish.c Fri Apr 13 10:33:30 2007
@@ -443,7 +443,7 @@
* events with nua_set_params() tag NUTAG_ALLOW_EVENTS().
*
* The nua_response() call responding to a PUBLISH request must have
- * NUTAG_WITH() (or NUTAG_WITH_CURRENT()/NUTAG_WITH_SAVED()) tag. Note that
+ * NUTAG_WITH() (or NUTAG_WITH_THIS()/NUTAG_WITH_SAVED()) tag. Note that
* a successful response to PUBLISH @b MUST include @Expires and @SIPETag
* headers.
*
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_register.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_register.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_register.c Fri Apr 13 10:33:30 2007
@@ -881,7 +881,7 @@
if (mindelta == SIP_TIME_MAX)
mindelta = 3600;
- nua_dialog_usage_set_expires(du, mindelta);
+ nua_dialog_usage_set_refresh(du, mindelta);
/* RFC 3608 Section 6.1 Procedures at the UA
@@ -935,7 +935,7 @@
nua_registration_set_ready(nr, 1);
}
else if (du) {
- nua_dialog_usage_set_expires(du, 0);
+ nua_dialog_usage_set_refresh(du, 0);
su_free(nh->nh_home, nr->nr_route);
nr->nr_route = NULL;
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_registrar.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_registrar.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_registrar.c Fri Apr 13 10:33:30 2007
@@ -60,7 +60,7 @@
* the REGISTER method with NUTAG_ALLOW() tag.
*
* The nua_response() call responding to a REGISTER request must have
- * NUTAG_WITH() (or NUTAG_WITH_CURRENT()/NUTAG_WITH_SAVED()) tag. Note that
+ * NUTAG_WITH() (or NUTAG_WITH_THIS()/NUTAG_WITH_SAVED()) tag. Note that
* a successful response to REGISTER @b MUST include the @Contact header
* bound to the the AoR URI (in @To header).
*
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c Fri Apr 13 10:33:30 2007
@@ -149,14 +149,23 @@
unsigned ss_precondition:1; /**< Precondition required */
- unsigned ss_timer_set:1; /**< We have active session timer. */
-
unsigned ss_reporting:1; /**< True if reporting state */
unsigned : 0;
-
- unsigned ss_session_timer; /**< Value of Session-Expires (delta) */
- unsigned ss_min_se; /**< Minimum session expires */
- enum nua_session_refresher ss_refresher; /**< none, local or remote */
+
+ struct session_timer {
+ unsigned interval; /**< Negotiated expiration time */
+ enum nua_session_refresher refresher; /**< Our Negotiated role */
+
+ struct {
+ unsigned expires, defaults; /**< Value of Session-Expires (delta) */
+ unsigned min_se; /**< Minimum session expires */
+ /** none, local or remote */
+ enum nua_session_refresher refresher;
+ unsigned supported:1, require:1, :0;
+ } local, remote;
+
+ unsigned timer_set:1; /**< We have active session timer. */
+ } ss_timer[1];
char const *ss_reason; /**< Reason for termination. */
@@ -204,11 +213,16 @@
nua_dialog_state_t *ds,
nua_dialog_usage_t *du)
{
+ nua_session_usage_t *ss = nua_dialog_usage_private(du);
+
if (ds->ds_has_session)
return -1;
ds->ds_has_session = 1;
ds->ds_got_session = 1;
+ ss->ss_timer->local.refresher = nua_any_refresher;
+ ss->ss_timer->remote.refresher = nua_any_refresher;
+
return 0;
}
@@ -297,19 +311,29 @@
int nua_stack_prack(nua_t *nua, nua_handle_t *nh, nua_event_t e,
tagi_t const *tags);
-static void session_timer_preferences(nua_session_usage_t *ss,
- unsigned expires,
- unsigned min_se,
- enum nua_session_refresher refresher);
-
-static int session_timer_is_supported(nua_handle_t const *nh);
-
-static int prefer_session_timer(nua_handle_t const *nh);
-
-static int use_session_timer(nua_session_usage_t *ss, int uas, int always,
- msg_t *msg, sip_t *);
-static int init_session_timer(nua_session_usage_t *ss, sip_t const *, int refresher);
-static void set_session_timer(nua_session_usage_t *ss);
+static int session_timer_is_supported(struct session_timer const *t);
+
+static void session_timer_preferences(struct session_timer *t,
+ sip_t const *sip,
+ sip_supported_t const *supported,
+ unsigned expires, int isset,
+ enum nua_session_refresher refresher,
+ unsigned min_se);
+
+static void session_timer_store(struct session_timer *t,
+ sip_t const *sip);
+
+static int session_timer_check_min_se(msg_t *msg, sip_t *sip,
+ sip_t const *request,
+ unsigned long min_se);
+
+static int session_timer_add_headers(struct session_timer *t,
+ int initial,
+ msg_t *msg, sip_t *sip);
+
+static void session_timer_negotiate(struct session_timer *t);
+
+static void session_timer_set(nua_session_usage_t *ss);
static int session_timer_check_restart(nua_client_request_t *cr,
int status, char const *phrase,
@@ -551,6 +575,7 @@
{
nua_handle_t *nh = cr->cr_owner;
nua_dialog_usage_t *du;
+ nua_session_usage_t *ss;
cr->cr_usage = du = nua_dialog_usage_for_session(nh->nh_ds);
/* Errors returned by nua_invite_client_init()
@@ -573,16 +598,22 @@
}
else
du = nua_dialog_usage_add(nh, nh->nh_ds, nua_session_usage, NULL);
+
if (!du)
return -1;
if (nua_client_bind(cr, du) < 0)
return nua_client_return(cr, 900, "INVITE already in progress", msg);
- session_timer_preferences(nua_dialog_usage_private(du),
+ ss = nua_dialog_usage_private(du);
+
+ session_timer_preferences(ss->ss_timer,
+ sip,
+ NH_PGET(nh, supported),
NH_PGET(nh, session_timer),
- NH_PGET(nh, min_se),
- NH_PGET(nh, refresher));
+ NUA_PISSET(nh->nh_nua, nh, session_timer),
+ NH_PGET(nh, refresher),
+ NH_PGET(nh, min_se));
cr->cr_neutral = 0;
@@ -608,12 +639,13 @@
if (invite_timeout == 0)
invite_timeout = UINT_MAX;
/* Send CANCEL if we don't get response within timeout*/
- nua_dialog_usage_set_expires(du, invite_timeout);
+ /* nua_dialog_usage_set_expires(du, invite_timeout); Xyzzy */
nua_dialog_usage_set_refresh(du, 0);
/* Add session timer headers */
- if (session_timer_is_supported(nh))
- use_session_timer(ss, 0, prefer_session_timer(nh), msg, sip);
+ if (session_timer_is_supported(ss->ss_timer))
+ session_timer_add_headers(ss->ss_timer, ss->ss_state == nua_callstate_init,
+ msg, sip);
ss->ss_100rel = NH_PGET(nh, early_media);
ss->ss_precondition = sip_has_feature(sip->sip_require, "precondition");
@@ -672,7 +704,6 @@
int status, char const *phrase,
sip_t const *sip)
{
- nua_handle_t *nh = cr->cr_owner;
nua_dialog_usage_t *du = cr->cr_usage;
nua_session_usage_t *ss = nua_dialog_usage_private(du);
@@ -682,8 +713,10 @@
else if (status < 300) {
du->du_ready = 1;
- init_session_timer(ss, sip, NH_PGET(nh, refresher));
- set_session_timer(ss);
+ if (session_timer_is_supported(ss->ss_timer))
+ session_timer_store(ss->ss_timer, sip);
+
+ session_timer_set(ss);
}
return nua_session_client_response(cr, status, phrase, sip);
@@ -1263,42 +1296,37 @@
nua_client_request_t const *cr = du->du_cr;
nua_server_request_t const *sr;
- assert(cr);
-
if (ss->ss_state >= nua_callstate_terminating ||
- /* No INVITE template */
- cr == NULL ||
/* INVITE is in progress or being authenticated */
- cr->cr_orq || cr->cr_wait_for_cred)
+ (cr && (cr->cr_orq || cr->cr_wait_for_cred)))
return;
- /* UPDATE in progress or being authenticated */
+ /* UPDATE has been queued */
for (cr = ds->ds_cr; cr; cr = cr->cr_next)
if (cr->cr_method == sip_method_update)
return;
- /* INVITE or UPDATE in progress */
+ /* INVITE or UPDATE in progress on server side */
for (sr = ds->ds_sr; sr; sr = sr->sr_next)
if (sr->sr_usage == du &&
(sr->sr_method == sip_method_invite ||
sr->sr_method == sip_method_update))
return;
- if (!ss->ss_refresher) {
- if (du->du_expires == 0 || now < du->du_expires)
- /* Refresh contact & route set using re-INVITE */
- nua_client_resend_request(du->du_cr, 0);
- else {
- ss->ss_reason = "SIP;cause=408;text=\"Session timeout\"";
- nua_stack_bye(nh->nh_nua, nh, nua_r_bye, NULL);
- }
+ if (ss->ss_timer->refresher == nua_remote_refresher) {
+ ss->ss_reason = "SIP;cause=408;text=\"Session timeout\"";
+ nua_stack_bye(nh->nh_nua, nh, nua_r_bye, NULL);
+ return;
}
else if (NH_PGET(nh, update_refresh)) {
nua_stack_update(nh->nh_nua, nh, nua_r_update, NULL);
}
- else {
+ else if (du->du_cr) {
nua_client_resend_request(du->du_cr, 0);
}
+ else {
+ nua_stack_invite(nh->nh_nua, nh, nua_r_invite, NULL);
+ }
}
/** @interal Shut down session usage.
@@ -1787,8 +1815,6 @@
sip_t const *request = sr->sr_request.sip;
- unsigned min = NH_PGET(nh, min_se);
-
if (!sr->sr_initial)
sr->sr_usage = nua_dialog_usage_get(nh->nh_ds, nua_session_usage, NULL);
@@ -1817,21 +1843,15 @@
}
if (request->sip_session_expires &&
- nta_check_session_expires(NULL, request, min, TAG_END())) {
- sip_min_se_t *min_se, min_se0[1];
-
- min_se = sip_min_se_init(min_se0);
- min_se->min_delta = min;
-
- if (request->sip_min_se && request->sip_min_se->min_delta > min)
- min_se = request->sip_min_se;
-
- sip_add_dup(msg, sip, (sip_header_t *)min_se);
-
- return SR_STATUS1(sr, SIP_422_SESSION_TIMER_TOO_SMALL);
+ sip_has_feature(NH_PGET(nh, supported), "timer") &&
+ session_timer_check_min_se(msg, sip, request, NH_PGET(nh, min_se))) {
+ if (sip->sip_min_se)
+ return SR_STATUS1(sr, SIP_422_SESSION_TIMER_TOO_SMALL);
+ else
+ return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR);
}
- session_get_description(sr->sr_request.sip, &sr->sr_sdp, &sr->sr_sdp_len);
+ session_get_description(request, &sr->sr_sdp, &sr->sr_sdp_len);
return 0;
}
@@ -1885,14 +1905,7 @@
if (ss->ss_precondition)
ss->ss_100rel = 1;
- session_timer_preferences(ss,
- NH_PGET(nh, session_timer),
- NH_PGET(nh, min_se),
- NH_PGET(nh, refresher));
-
- /* Session Timer negotiation */
- if (sip_has_supported(NH_PGET(nh, supported), "timer"))
- init_session_timer(ss, request, ss->ss_refresher);
+ session_timer_store(ss->ss_timer, request);
assert(ss->ss_state >= nua_callstate_ready ||
ss->ss_state == nua_callstate_init);
@@ -2043,9 +2056,18 @@
return 0;
}
- if (ss->ss_refresher && 200 <= sr->sr_status && sr->sr_status < 300)
- if (session_timer_is_supported(nh))
- use_session_timer(ss, 1, 1, msg, sip);
+ if (200 <= sr->sr_status && sr->sr_status < 300) {
+ session_timer_preferences(ss->ss_timer,
+ sip,
+ NH_PGET(nh, supported),
+ NH_PGET(nh, session_timer),
+ NUA_PISSET(nh->nh_nua, nh, session_timer),
+ NH_PGET(nh, refresher),
+ NH_PGET(nh, min_se));
+
+ if (session_timer_is_supported(ss->ss_timer))
+ session_timer_add_headers(ss->ss_timer, 0, msg, sip);
+ }
return nua_base_server_respond(sr, tags);
}
@@ -2249,7 +2271,7 @@
nua_stack_event(nh->nh_nua, nh, msg, nua_i_ack, SIP_200_OK, NULL);
signal_call_state_change(nh, ss, 200, "OK", nua_callstate_ready);
- set_session_timer(ss);
+ session_timer_set(ss);
nua_server_request_destroy(sr);
@@ -2560,171 +2582,6 @@
}
/* ---------------------------------------------------------------------- */
-/* Session timer - RFC 4028 */
-
-static int session_timer_is_supported(nua_handle_t const *nh)
-{
- /* Is timer feature supported? */
- return sip_has_supported(NH_PGET(nh, supported), "timer");
-}
-
-static int prefer_session_timer(nua_handle_t const *nh)
-{
- return
- NH_PGET(nh, refresher) != nua_no_refresher ||
- NH_PGET(nh, session_timer) != 0;
-}
-
-/* Initialize session timer */
-static
-void session_timer_preferences(nua_session_usage_t *ss,
- unsigned expires,
- unsigned min_se,
- enum nua_session_refresher refresher)
-{
- if (expires < min_se)
- expires = min_se;
- if (refresher && expires == 0)
- expires = 3600;
-
- ss->ss_min_se = min_se;
- ss->ss_session_timer = expires;
- ss->ss_refresher = refresher;
-}
-
-
-/** Add timer featuretag and Session-Expires/Min-SE headers */
-static int
-use_session_timer(nua_session_usage_t *ss, int uas, int always,
- msg_t *msg, sip_t *sip)
-{
- sip_min_se_t min_se[1];
- sip_session_expires_t session_expires[1];
-
- static sip_param_t const x_params_uac[] = {"refresher=uac", NULL};
- static sip_param_t const x_params_uas[] = {"refresher=uas", NULL};
-
- /* Session-Expires timer */
- if (ss->ss_refresher == nua_no_refresher && !always)
- return 0;
-
- sip_min_se_init(min_se)->min_delta = ss->ss_min_se;
- sip_session_expires_init(session_expires)->x_delta = ss->ss_session_timer;
-
- if (ss->ss_refresher == nua_remote_refresher)
- session_expires->x_params = uas ? x_params_uac : x_params_uas;
- else if (ss->ss_refresher == nua_local_refresher)
- session_expires->x_params = uas ? x_params_uas : x_params_uac;
-
- sip_add_tl(msg, sip,
- TAG_IF(ss->ss_session_timer,
- SIPTAG_SESSION_EXPIRES(session_expires)),
- TAG_IF(ss->ss_min_se != 0
- /* Min-SE: 0 is optional with initial INVITE */
- || ss->ss_state != nua_callstate_init,
- SIPTAG_MIN_SE(min_se)),
- TAG_IF(ss->ss_refresher == nua_remote_refresher,
- SIPTAG_REQUIRE_STR("timer")),
- TAG_END());
-
- return 1;
-}
-
-static int
-init_session_timer(nua_session_usage_t *ss,
- sip_t const *sip,
- int refresher)
-{
- int server;
-
- /* Session timer is not needed */
- if (!sip->sip_session_expires) {
- if (!sip_has_supported(sip->sip_supported, "timer"))
- ss->ss_refresher = nua_local_refresher;
- return 0;
- }
-
- ss->ss_refresher = nua_no_refresher;
- ss->ss_session_timer = sip->sip_session_expires->x_delta;
-
- if (sip->sip_min_se != NULL
- && sip->sip_min_se->min_delta > ss->ss_min_se)
- ss->ss_min_se = sip->sip_min_se->min_delta;
-
- server = sip->sip_request != NULL;
-
- if (!sip_has_supported(sip->sip_supported, "timer"))
- ss->ss_refresher = nua_local_refresher;
- else if (!str0casecmp("uac", sip->sip_session_expires->x_refresher))
- ss->ss_refresher = server ? nua_remote_refresher : nua_local_refresher;
- else if (!str0casecmp("uas", sip->sip_session_expires->x_refresher))
- ss->ss_refresher = server ? nua_local_refresher : nua_remote_refresher;
- else if (!server)
- return 0; /* XXX */
- /* User preferences */
- else if (refresher == nua_local_refresher)
- ss->ss_refresher = nua_local_refresher;
- else
- ss->ss_refresher = nua_remote_refresher;
-
- SU_DEBUG_7(("nua session: session expires in %u refreshed by %s (%s %s)\n",
- ss->ss_session_timer,
- ss->ss_refresher == nua_local_refresher ? "local" : "remote",
- server ? sip->sip_request->rq_method_name : "response to",
- server ? "request" : sip->sip_cseq->cs_method_name));
-
- return 1;
-}
-
-static int session_timer_check_restart(nua_client_request_t *cr,
- int status, char const *phrase,
- sip_t const *sip)
-{
- if (cr->cr_usage && status == 422) {
- nua_session_usage_t *ss = nua_dialog_usage_private(cr->cr_usage);
-
- if (sip->sip_min_se && ss->ss_min_se < sip->sip_min_se->min_delta)
- ss->ss_min_se = sip->sip_min_se->min_delta;
- if (ss->ss_min_se > ss->ss_session_timer)
- ss->ss_session_timer = ss->ss_min_se;
-
- return nua_client_restart(cr, 100, "Re-Negotiating Session Timer");
- }
-
- return nua_base_client_check_restart(cr, status, phrase, sip);
-}
-
-static void
-set_session_timer(nua_session_usage_t *ss)
-{
- nua_dialog_usage_t *du = nua_dialog_usage_public(ss);
-
- if (ss == NULL)
- return;
-
- if (ss->ss_refresher == nua_local_refresher) {
- ss->ss_timer_set = 1;
- nua_dialog_usage_set_expires(du, ss->ss_session_timer);
- }
- else if (ss->ss_refresher == nua_remote_refresher) {
- ss->ss_timer_set = 1;
- nua_dialog_usage_set_expires(du, ss->ss_session_timer + 32);
- nua_dialog_usage_reset_refresh(du);
- }
- else {
- ss->ss_timer_set = 0;
- nua_dialog_usage_set_expires(du, UINT_MAX);
- nua_dialog_usage_reset_refresh(du);
- }
-}
-
-static inline int
-is_session_timer_set(nua_session_usage_t *ss)
-{
- return ss->ss_timer_set;
-}
-
-/* ---------------------------------------------------------------------- */
/* Automatic notifications from a referral */
static int
@@ -2787,7 +2644,6 @@
return 0;
}
-
static void
nh_referral_respond(nua_handle_t *nh, int status, char const *phrase)
{
@@ -3099,8 +2955,17 @@
}
/* Add session timer headers */
- if (session_timer_is_supported(nh))
- use_session_timer(ss, 0, prefer_session_timer(nh), msg, sip);
+ session_timer_preferences(ss->ss_timer,
+ sip,
+ NH_PGET(nh, supported),
+ NH_PGET(nh, session_timer),
+ NUA_PISSET(nh->nh_nua, nh, session_timer),
+ NH_PGET(nh, refresher),
+ NH_PGET(nh, min_se));
+
+ if (session_timer_is_supported(ss->ss_timer))
+ session_timer_add_headers(ss->ss_timer, ss->ss_state < nua_callstate_ready,
+ msg, sip);
retval = nua_base_client_request(cr, msg, sip, NULL);
@@ -3109,9 +2974,15 @@
ss->ss_update_needed = 0;
if (!cr->cr_restarting) {
+ enum nua_callstate state = ss->ss_state;
+
+ if (state == nua_callstate_ready)
+ state = nua_callstate_calling;
+
if (offer_sent)
ss->ss_oa_sent = "offer";
- signal_call_state_change(nh, ss, 0, "UPDATE sent", ss->ss_state);
+
+ signal_call_state_change(nh, ss, 0, "UPDATE sent", state);
}
}
@@ -3129,9 +3000,18 @@
assert(200 <= status);
if (ss && sip && status < 300) {
- if (is_session_timer_set(ss)) {
- init_session_timer(ss, sip, NH_PGET(nh, refresher));
- set_session_timer(ss);
+ if (session_timer_is_supported(ss->ss_timer)) {
+ nua_server_request_t *sr;
+
+ for (sr = nh->nh_ds->ds_sr; sr; sr = sr->sr_next)
+ if (sr->sr_method == sip_method_invite ||
+ sr->sr_method == sip_method_update)
+ break;
+
+ if (!sr && (!du->du_cr || !du->du_cr->cr_orq)) {
+ session_timer_store(ss->ss_timer, sip);
+ session_timer_set(ss);
+ }
}
}
@@ -3225,7 +3105,7 @@
/* Do session timer negotiation */
if (request->sip_session_expires)
- init_session_timer(ss, request, NH_PGET(nh, refresher));
+ session_timer_store(ss->ss_timer, request);
if (sr->sr_sdp) { /* Check for overlap */
nua_client_request_t *cr;
@@ -3306,11 +3186,28 @@
}
}
- if (ss->ss_refresher && 200 <= sr->sr_status && sr->sr_status < 300)
- if (session_timer_is_supported(nh)) {
- use_session_timer(ss, 1, 1, msg, sip);
- set_session_timer(ss); /* XXX */
+ if (200 <= sr->sr_status && sr->sr_status < 300) {
+ session_timer_preferences(ss->ss_timer,
+ sip,
+ NH_PGET(nh, supported),
+ NH_PGET(nh, session_timer),
+ NUA_PISSET(nh->nh_nua, nh, session_timer),
+ NH_PGET(nh, refresher),
+ NH_PGET(nh, min_se));
+
+ if (ss && session_timer_is_supported(ss->ss_timer)) {
+ nua_server_request_t *sr0;
+
+ session_timer_add_headers(ss->ss_timer, 0, msg, sip);
+
+ for (sr0 = nh->nh_ds->ds_sr; sr0; sr0 = sr0->sr_next)
+ if (sr0->sr_method == sip_method_invite)
+ break;
+
+ if (!sr0 && (!sr->sr_usage->du_cr || !sr->sr_usage->du_cr->cr_orq))
+ session_timer_set(ss);
}
+ }
return nua_base_server_respond(sr, tags);
}
@@ -3348,9 +3245,15 @@
return retval;
}
- if (offer_recv_or_answer_sent)
+ if (offer_recv_or_answer_sent) {
/* signal offer received, answer sent */
- signal_call_state_change(nh, ss, status, phrase, ss->ss_state);
+ enum nua_callstate state = ss->ss_state;
+
+ if (state == nua_callstate_ready && status < 200)
+ state = nua_callstate_received;
+
+ signal_call_state_change(nh, ss, status, phrase, state);
+ }
if (200 <= status && status < 300
&& ss->ss_state < nua_callstate_ready
@@ -3900,6 +3803,287 @@
}
/* ======================================================================== */
+/* Session timer - RFC 4028 */
+
+static int session_timer_is_supported(struct session_timer const *t)
+{
+ return t->local.supported;
+}
+
+/** Set session timer preferences */
+static
+void session_timer_preferences(struct session_timer *t,
+ sip_t const *sip,
+ sip_supported_t const *supported,
+ unsigned expires,
+ int isset,
+ enum nua_session_refresher refresher,
+ unsigned min_se)
+{
+ memset(&t->local, 0, sizeof t->local);
+
+ t->local.require = sip_has_feature(sip->sip_require, "timer");
+ t->local.supported =
+ sip_has_feature(supported, "timer") ||
+ sip_has_feature(sip->sip_supported, "timer");
+ if (isset || refresher != nua_no_refresher)
+ t->local.expires = expires;
+ else
+ t->local.defaults = expires;
+ t->local.min_se = min_se;
+ t->local.refresher = refresher;
+}
+
+static int session_timer_check_restart(nua_client_request_t *cr,
+ int status, char const *phrase,
+ sip_t const *sip)
+{
+ if (status == 422) {
+ nua_session_usage_t *ss = nua_dialog_usage_private(cr->cr_usage);
+
+ if (ss && session_timer_is_supported(ss->ss_timer)) {
+ struct session_timer *t = ss->ss_timer;
+
+ if (sip->sip_min_se && t->local.min_se < sip->sip_min_se->min_delta)
+ t->local.min_se = sip->sip_min_se->min_delta;
+ if (t->local.expires != 0 && t->local.min_se > t->local.expires)
+ t->local.expires = t->local.min_se;
+
+ return nua_client_restart(cr, 100, "Re-Negotiating Session Timer");
+ }
+ }
+
+ return nua_base_client_check_restart(cr, status, phrase, sip);
+}
+
+/** Check that received Session-Expires is longer than Min-SE */
+static
+int session_timer_check_min_se(msg_t *msg,
+ sip_t *sip,
+ sip_t const *request,
+ unsigned long min)
+{
+ if (min == 0)
+ min = 1;
+
+ /*
+ If an incoming request contains a Supported header field with a value
+ 'timer' and a Session Expires header field, the UAS MAY reject the
+ INVITE request with a 422 (Session Interval Too Small) response if
+ the session interval in the Session-Expires header field is smaller
+ than the minimum interval defined by the UAS' local policy. When
+ sending the 422 response, the UAS MUST include a Min-SE header field
+ with the value of its minimum interval. This minimum interval MUST
+ NOT be lower than 90 seconds.
+ */
+ if (request->sip_session_expires &&
+ sip_has_feature(request->sip_supported, "timer") &&
+ request->sip_session_expires->x_delta < min) {
+ sip_min_se_t min_se[1];
+
+ if (min < 90)
+ min = 90;
+
+ sip_min_se_init(min_se)->min_delta = min;
+
+ /* Include extension parameters, if any */
+ if (request->sip_min_se)
+ min_se->min_params = request->sip_min_se->min_params;
+
+ sip_add_dup(msg, sip, (sip_header_t *)min_se);
+
+ return 422;
+ }
+
+ return 0;
+}
+
+/** Store session timer parameters in request from uac / response from uas */
+static
+void session_timer_store(struct session_timer *t,
+ sip_t const *sip)
+{
+ sip_require_t const *require = sip->sip_require;
+ sip_supported_t const *supported = sip->sip_supported;
+ sip_session_expires_t const *x = sip->sip_session_expires;
+
+ t->remote.require = require && sip_has_feature(require, "timer");
+ t->remote.supported =
+ t->remote.supported || (supported && sip_has_feature(supported, "timer"));
+
+ t->remote.expires = 0;
+ t->remote.refresher = nua_any_refresher;
+ t->remote.min_se = 0;
+
+ if (x) {
+ t->remote.expires = x->x_delta;
+
+ if (x->x_refresher) {
+ int uas = sip->sip_request != NULL;
+
+ if (strcasecmp(x->x_refresher, "uac") == 0)
+ t->remote.refresher = uas ? nua_remote_refresher : nua_local_refresher;
+ else if (strcasecmp(x->x_refresher, "uas") == 0)
+ t->remote.refresher = uas ? nua_local_refresher : nua_remote_refresher;
+ }
+ }
+
+ if (sip->sip_min_se)
+ t->remote.min_se = sip->sip_min_se->min_delta;
+}
+
+/** Add timer feature and Session-Expires/Min-SE headers to request/response
+ *
+ */
+static int
+session_timer_add_headers(struct session_timer *t,
+ int initial,
+ msg_t *msg, sip_t *sip)
+{
+ unsigned long expires, min;
+ sip_min_se_t min_se[1];
+ sip_session_expires_t x[1];
+ int uas;
+
+ enum nua_session_refresher refresher = nua_any_refresher;
+
+ static sip_param_t const x_params_uac[] = {"refresher=uac", NULL};
+ static sip_param_t const x_params_uas[] = {"refresher=uas", NULL};
+
+ if (!t->local.supported)
+ return 0;
+
+ uas = sip->sip_status != NULL;
+
+ min = t->local.min_se;
+ if (min < t->remote.min_se)
+ min = t->remote.min_se;
+
+ if (uas) {
+ session_timer_negotiate(t);
+
+ refresher = t->refresher;
+ expires = t->interval;
+ }
+ else {
+ /* RFC 4028:
+ * The UAC MAY include the refresher parameter with value 'uac' if it
+ * wants to perform the refreshes. However, it is RECOMMENDED that the
+ * parameter be omitted so that it can be selected by the negotiation
+ * mechanisms described below.
+ */
+ if (t->local.refresher == nua_local_refresher)
+ refresher = nua_local_refresher;
+
+ expires = t->local.expires;
+ if (expires != 0 && expires < min)
+ expires = min;
+ }
+
+ sip_min_se_init(min_se)->min_delta = min;
+
+ sip_session_expires_init(x)->x_delta = expires;
+ if (refresher == nua_remote_refresher)
+ x->x_params = uas ? x_params_uac : x_params_uas;
+ else if (refresher == nua_local_refresher)
+ x->x_params = uas ? x_params_uas : x_params_uac;
+
+ sip_add_tl(msg, sip,
+ TAG_IF(expires != 0, SIPTAG_SESSION_EXPIRES(x)),
+ TAG_IF(min != 0
+ /* Min-SE: 0 is optional with initial INVITE */
+ || !initial,
+ SIPTAG_MIN_SE(min_se)),
+ TAG_IF(refresher == nua_remote_refresher && expires != 0,
+ SIPTAG_REQUIRE_STR("timer")),
+ TAG_END());
+
+ return 1;
+}
+
+static
+void session_timer_negotiate(struct session_timer *t)
+{
+ if (!t->local.supported)
+ t->refresher = nua_no_refresher;
+ else if (!t->remote.supported)
+ t->refresher = nua_local_refresher;
+ else if (t->remote.refresher == nua_local_refresher)
+ t->refresher = nua_local_refresher;
+ else if (t->remote.refresher == nua_remote_refresher)
+ t->refresher = nua_remote_refresher;
+ else if (t->local.refresher == nua_local_refresher)
+ t->refresher = nua_local_refresher;
+ else
+ t->refresher = nua_remote_refresher;
+
+ t->interval = t->remote.expires;
+ if (t->interval == 0)
+ t->interval = t->local.expires;
+ if (t->local.expires != 0 && t->interval > t->local.expires)
+ t->interval = t->local.expires;
+ if (t->local.defaults != 0 && t->interval > t->local.defaults)
+ t->interval = t->local.defaults;
+
+ if (t->interval != 0) {
+ if (t->interval < t->local.min_se)
+ t->interval = t->local.min_se;
+ if (t->interval < t->remote.min_se)
+ t->interval = t->remote.min_se;
+ }
+
+ if (t->interval == 0)
+ t->refresher = nua_no_refresher;
+}
+
+static void
+session_timer_set(nua_session_usage_t *ss)
+{
+ nua_dialog_usage_t *du = nua_dialog_usage_public(ss);
+ struct session_timer *t;
+
+ if (ss == NULL)
+ return;
+
+ t = ss->ss_timer;
+
+ session_timer_negotiate(t);
+
+ if (t->refresher == nua_local_refresher) {
+ unsigned low = t->interval / 2, high = t->interval / 2;
+
+ if (t->interval >= 90)
+ low -=5, high += 5;
+
+ nua_dialog_usage_refresh_range(du, low, high);
+ t->timer_set = 1;
+ }
+ else if (t->refresher == nua_remote_refresher) {
+ /* if the side not performing refreshes does not receive a
+ session refresh request before the session expiration, it SHOULD send
+ a BYE to terminate the session, slightly before the session
+ expiration. The minimum of 32 seconds and one third of the session
+ interval is RECOMMENDED. */
+ unsigned interval = t->interval;
+
+ interval -= 32 > interval / 6 ? interval / 3 : 32 + interval / 3;
+
+ nua_dialog_usage_refresh_range(du, interval, interval);
+ t->timer_set = 1;
+ }
+ else {
+ nua_dialog_usage_reset_refresh(du);
+ t->timer_set = 0;
+ }
+}
+
+static inline int
+session_timer_has_been_set(struct session_timer const *t)
+{
+ return t->timer_set;
+}
+
+/* ======================================================================== */
/** Get SDP from a SIP message.
*
@@ -4020,6 +4204,8 @@
return retval;
}
+/* ====================================================================== */
+
/** @NUA_EVENT nua_i_options
*
* Incoming OPTIONS request. The user-agent should respond to an OPTIONS
@@ -4093,4 +4279,3 @@
return nua_base_server_respond(sr, tags);
}
-
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c Fri Apr 13 10:33:30 2007
@@ -989,11 +989,10 @@
nua_stack_authenticate(nua_t *nua, nua_handle_t *nh, nua_event_t e,
tagi_t const *tags)
{
+ nua_client_request_t *cr = nh->nh_ds->ds_cr;
int status = nh_authorize(nh, TAG_NEXT(tags));
if (status > 0) {
- nua_client_request_t *cr = nh->nh_ds->ds_cr;
-
if (cr && cr->cr_wait_for_cred) {
nua_client_restart_request(cr, cr->cr_terminating, tags);
}
@@ -1003,6 +1002,14 @@
NULL);
}
}
+ else if (cr && cr->cr_wait_for_cred) {
+ cr->cr_wait_for_cred = 0;
+
+ if (status < 0)
+ nua_client_response(cr, 900, "Cannot add credentials", NULL);
+ else
+ nua_client_response(cr, 904, "No matching challenge", NULL);
+ }
else if (status < 0) {
nua_stack_event(nua, nh, NULL, e, 900, "Cannot add credentials", NULL);
}
@@ -1049,6 +1056,7 @@
nua_server_methods_t const *sm;
nua_server_request_t *sr, sr0[1];
int status, initial = 1;
+ int create_dialog;
char const *user_agent = NH_PGET(nh, user_agent);
sip_supported_t const *supported = NH_PGET(nh, supported);
@@ -1135,11 +1143,15 @@
return 481;
}
+ create_dialog = sm->sm_flags.create_dialog;
+ if (method == sip_method_message && NH_PGET(nh, win_messenger_enable))
+ create_dialog = 1;
sr = memset(sr0, 0, (sizeof sr0));
sr->sr_methods = sm;
sr->sr_method = method = sip->sip_request->rq_method;
sr->sr_add_contact = sm->sm_flags.add_contact;
+ sr->sr_target_refresh = sm->sm_flags.target_refresh;
sr->sr_owner = nh;
sr->sr_initial = initial;
@@ -1171,12 +1183,12 @@
}
if (sr->sr_status < 300 && sm->sm_preprocess && sm->sm_preprocess(sr)) {
- if (sr->sr_status < 200) /* Preprocess may have set response status */
+ if (sr->sr_status < 200) /* Set response status if preprocess did not */
SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR);
}
if (sr->sr_status < 300) {
- if (sm->sm_flags.target_refresh)
+ if (sr->sr_target_refresh)
nua_dialog_uas_route(nh, nh->nh_ds, sip, 1); /* Set route and tags */
nua_dialog_store_peer_info(nh, nh->nh_ds, sip);
}
@@ -1273,7 +1285,7 @@
* content negotiation fails.
*
* When responding to an incoming INVITE request, the nua_respond() can be
- * called without NUTAG_WITH() (or NUTAG_WITH_CURRENT() or
+ * called without NUTAG_WITH() (or NUTAG_WITH_THIS() or
* NUTAG_WITH_SAVED()). Otherwise, NUTAG_WITH() will contain an indication
* of the request being responded.
*
@@ -1302,7 +1314,7 @@
* nothing
*
* @par Related Tags:
- * NUTAG_WITH(), NUTAG_WITH_CURRENT(), NUTAG_WITH_SAVED() \n
+ * NUTAG_WITH(), NUTAG_WITH_THIS(), NUTAG_WITH_SAVED() \n
* NUTAG_EARLY_ANSWER() \n
* SOATAG_ADDRESS() \n
* SOATAG_AF() \n
@@ -1696,6 +1708,7 @@
cr->cr_method = method;
cr->cr_method_name = name;
cr->cr_contactize = methods->crm_flags.target_refresh;
+ cr->cr_dialog = methods->crm_flags.create_dialog;
cr->cr_auto = 1;
if (su_msg_is_non_null(nh->nh_nua->nua_signal)) {
@@ -1927,6 +1940,10 @@
has_contact = 1;
else if (t->t_tag == nutag_url)
url = (url_string_t const *)t->t_value;
+ else if (t->t_tag == nutag_dialog) {
+ cr->cr_dialog = t->t_value > 1;
+ cr->cr_contactize = t->t_value >= 1;
+ }
else if (t->t_tag == nutag_auth && t->t_value) {
/* XXX ignoring errors */
if (nh->nh_auth)
@@ -1965,7 +1982,7 @@
sip_add_dup(msg, sip, (sip_header_t *)nua->nua_from) < 0)
goto error;
- if (cr->cr_methods->crm_flags.create_dialog) {
+ if (cr->cr_dialog) {
ds->ds_leg = nta_leg_tcreate(nua->nua_nta,
nua_stack_process_request, nh,
SIPTAG_CALL_ID(sip->sip_call_id),
@@ -2030,7 +2047,6 @@
if (sip_add_tagis(cr->cr_msg, NULL, &tags) < 0)
/* XXX */;
- cr->cr_retry_count = 0;
cr->cr_terminating = terminating;
return nua_client_request_try(cr);
@@ -2125,6 +2141,8 @@
assert(cr->cr_orq == NULL);
+ cr->cr_retry_count++;
+
if (ds->ds_leg)
leg = ds->ds_leg;
else
@@ -2161,7 +2179,7 @@
* are used: @Allow, @Supported, @Organization, and @UserAgent headers are
* added to the request if they are not already set.
*/
- if (!sip->sip_allow && !ds->ds_route)
+ if (!sip->sip_allow)
sip_add_dup(msg, sip, (sip_header_t*)NH_PGET(nh, allow));
if (!sip->sip_supported && NH_PGET(nh, supported))
@@ -2337,7 +2355,7 @@
}
else {
if (sip) {
- if (cr->cr_methods->crm_flags.target_refresh)
+ if (cr->cr_contactize)
nua_dialog_uac_route(nh, nh->nh_ds, sip, 1);
nua_dialog_store_peer_info(nh, nh->nh_ds, sip);
}
@@ -2392,7 +2410,7 @@
assert(cr && status >= 200 && phrase && sip);
- if (cr->cr_retry_count >= NH_PGET(nh, retry_count))
+ if (cr->cr_retry_count > NH_PGET(nh, retry_count))
return 0;
if (cr->cr_methods->crm_check_restart)
@@ -2482,7 +2500,6 @@
orq = cr->cr_orq, cr->cr_orq = NULL;
cr->cr_wait_for_cred = 1;
- cr->cr_retry_count++;
nua_client_report(cr, status, phrase, NULL, orq, NULL);
nta_outgoing_destroy(orq);
@@ -2507,7 +2524,7 @@
msg_t *msg;
sip_t *sip;
- if (++cr->cr_retry_count > NH_PGET(nh, retry_count))
+ if (cr->cr_retry_count > NH_PGET(nh, retry_count))
return 0;
orq = cr->cr_orq, cr->cr_orq = NULL; assert(orq);
@@ -2641,22 +2658,23 @@
if (cr->cr_terminated < 0) {
/* XXX - dialog has been terminated */;
- nua_dialog_deinit(nh, nh->nh_ds);
+ nua_dialog_deinit(nh, nh->nh_ds), cr->cr_usage = NULL;
}
else if (du) {
if (cr->cr_terminated ||
(!du->du_ready && status >= 300 && nua_client_is_bound(cr))) {
/* Usage has been destroyed */
- nua_dialog_usage_remove(nh, nh->nh_ds, du);
+ nua_dialog_usage_remove(nh, nh->nh_ds, du), cr->cr_usage = NULL;
}
else if (cr->cr_graceful) {
/* Terminate usage gracefully */
- nua_dialog_usage_shutdown(nh, nh->nh_ds, du);
+ if (nua_dialog_usage_shutdown(nh, nh->nh_ds, du) > 0)
+ cr->cr_usage = NULL;
}
}
else if (cr->cr_terminated) {
if (nh->nh_ds->ds_usage == NULL)
- nua_dialog_remove(nh, nh->nh_ds, NULL);
+ nua_dialog_remove(nh, nh->nh_ds, NULL), cr->cr_usage = NULL;
}
cr->cr_reporting = 0, nh->nh_ds->ds_reporting = 0;
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h Fri Apr 13 10:33:30 2007
@@ -336,8 +336,6 @@
sip_t const *sip,
int create_dialog);
-enum { create_dialog = 1 };
-
int nua_stack_init_handle(nua_t *nua, nua_handle_t *nh,
tag_type_t tag, tag_value_t value, ...);
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c Fri Apr 13 10:33:30 2007
@@ -61,6 +61,7 @@
enum nua_substate eu_substate; /**< Subscription state */
sip_time_t eu_expires; /**< Proposed expiration time */
unsigned eu_notified; /**< Number of NOTIFYs received */
+ unsigned eu_unsolicited:1; /**< Not SUBSCRIBEd or REFERed */
unsigned eu_refer:1; /**< Implied subscription by refer */
unsigned eu_final_wait:1; /**< Waiting for final NOTIFY */
unsigned eu_no_id:1; /**< Do not use "id" (even if we have one) */
@@ -443,11 +444,12 @@
*/
}
- nua_stack_tevent(nh->nh_nua, nh, NULL,
- nua_i_notify, NUA_INTERNAL_ERROR,
- NUTAG_SUBSTATE(nua_substate_terminated),
- SIPTAG_EVENT(du->du_event),
- TAG_END());
+ if (!eu->eu_unsolicited)
+ nua_stack_tevent(nh->nh_nua, nh, NULL,
+ nua_i_notify, NUA_INTERNAL_ERROR,
+ NUTAG_SUBSTATE(nua_substate_terminated),
+ SIPTAG_EVENT(du->du_event),
+ TAG_END());
nua_dialog_usage_remove(nh, ds, du);
}
@@ -504,10 +506,10 @@
SIP_METHOD_NOTIFY,
nua_i_notify, /* Event */
{
- 1, /* Do create dialog */
- 0, /* Not always in-dialog request */
- 1, /* Target refresh request */
- 1, /* Add Contact to response */
+ /* create_dialog: */ 1, /* Do create dialog */
+ /* in_dialog: */ 0, /* Not always in-dialog request */
+ /* target_refresh: */ 1, /* Target refresh request */
+ /* add_contact: */ 1, /* Add Contact to response */
},
nua_notify_server_init,
nua_notify_server_preprocess,
@@ -557,17 +559,21 @@
enum nua_substate substate = nua_substate_terminated;
sip_subscription_state_t *subs = sip->sip_subscription_state;
char const *what = "", *reason = NULL;
+ int solicited = 1;
du = nua_dialog_usage_get(ds, nua_subscribe_usage, o);
- sr->sr_usage = du;
if (du == NULL) {
if (!sip_is_allowed(NH_PGET(sr->sr_owner, appl_method), SIP_METHOD_NOTIFY))
return SR_STATUS(sr, 481, "Subscription Does Not Exist");
- /* Let application to handle unsolicited NOTIFY */
- return 0;
+
+ solicited = 0; /* Let application to handle unsolicited NOTIFY */
+ du = nua_dialog_usage_add(sr->sr_owner, ds, nua_subscribe_usage, o);
+ if (!du)
+ return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR);
}
+ sr->sr_usage = du;
eu = nua_dialog_usage_private(du); assert(eu);
eu->eu_notified++;
if (!o->o_id)
@@ -602,12 +608,17 @@
}
eu->eu_substate = substate;
+ if (!solicited)
+ eu->eu_unsolicited = 1;
SU_DEBUG_5(("nua(%p): %s: %s (%s)\n",
(void *)sr->sr_owner, "nua_notify_server_preprocess",
what, reason ? reason : ""));
- return SR_STATUS1(sr, SIP_200_OK);
+ if (solicited)
+ return SR_STATUS1(sr, SIP_200_OK);
+
+ return 0;
}
@@ -656,10 +667,13 @@
NUTAG_SUBSTATE(substate),
TAG_NEXT(tags));
- if (retval >= 2 || du == NULL)
+ if (retval != 1 || du == NULL)
return retval;
- if (retry >= 0) { /* Try to subscribe again */
+ if (eu->eu_unsolicited) {
+ /* Xyzzy */;
+ }
+ else if (retry >= 0) { /* Try to subscribe again */
/* XXX - this needs through testing */
nua_dialog_remove(nh, nh->nh_ds, du); /* tear down */
nua_dialog_usage_refresh_range(du, retry, retry + 5);
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_tag.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_tag.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/nua_tag.c Fri Apr 13 10:33:30 2007
@@ -149,3 +149,4 @@
tag_typedef_t nutag_detect_network_updates = UINTTAG_TYPEDEF(detect_network_updates);
tag_typedef_t nutag_with = PTRTAG_TYPEDEF(with);
+tag_typedef_t nutag_dialog = UINTTAG_TYPEDEF(dialog);
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua.h
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua.h (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua.h Fri Apr 13 10:33:30 2007
@@ -346,6 +346,9 @@
tag_type_t, tag_value_t,
...);
+/** Check if event can be responded with nua_respond() */
+SOFIAPUBFUN int nua_event_is_incoming_request(nua_event_t e);
+
#define nua_handle_home(nh) ((su_home_t *)(nh))
/** Generate an instance identifier */
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua_tag.h
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua_tag.h (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua_tag.h Fri Apr 13 10:33:30 2007
@@ -157,6 +157,9 @@
*/
#define NUTAG_WITH_THIS(nua) nutag_with, tag_ptr_v(nua_current_request((nua)))
+#define NUTAG_WITH_CURRENT(nua) \
+ nutag_with, tag_ptr_v(nua_current_request((nua)))
+
/**Specify request to respond to.
*
* @par Used with
@@ -174,6 +177,26 @@
*/
#define NUTAG_WITH_SAVED(e) nutag_with, tag_ptr_v(nua_saved_event_request((e)))
+/**An (extension) method is used to create dialog or refresh target.
+ *
+ * @par Used with
+ * nua_method()
+ *
+ * @par Parameter type
+ * unsigned int (0, 1, 2)
+ *
+ * @par Values
+ * - 0 if dialog target is not refreshed
+ * - 1 if dialog target is refreshed
+ * - > 1 if dialog is to be created
+ *
+ * @NEW_1_12_6.
+ *
+ * @sa nua_method(), #nua_i_method
+ */
+#define NUTAG_DIALOG(b) nutag_dialog, tag_uint_v((b))
+SOFIAPUBVAR tag_typedef_t nutag_dialog;
+
/**Set request retry count.
*
* Retry count determines how many times stack will automatically retry
@@ -471,40 +494,48 @@
/**Default session timer in seconds.
*
- * Set default session timer in seconds when using session timer extension.
- * The value given here is the proposed session expiration time in seconds.
- * Note that the session timer extension is ponly used
+ * Set default value for session timer in seconds when the session timer
+ * extension is used. The tag value is the proposed session expiration time
+ * in seconds, the session is refreshed twice during the expiration time.
*
* @par Sending INVITE and UPDATE Requests
*
- * If NUTAG_SESSION_TIMER() is used with non-zero value, the value is
- * used in the @SessionExpires header included in the INVITE or UPDATE
- * requests. The intermediate proxies or the ultimate destination can lower
- * the interval in @SessionExpires header. If the value is too low, they can
+ * If NUTAG_SESSION_TIMER() is used with non-zero value, the value is used
+ * in the @SessionExpires header included in the INVITE or UPDATE requests.
+ * The intermediate proxies or the ultimate destination can lower the
+ * interval in @SessionExpires header. If the value is too low, they can
* reject the request with the status code <i>422 Session Timer Too
- * Small</i>. When Re-INVITE will be sent in given intervals. In that case,
- * @b nua retries the request automatically.
- *
- * @par Returning Response to the INVITE and UPDATE Requests
+ * Small</i>. In that case, @b nua increases the value of @SessionExpires
+ * header and retries the request automatically.
+ *
+ * @par Returning a Response to the INVITE and UPDATE Requests
*
* The NUTAG_SESSION_TIMER() value is also used when sending the final
* response to the INVITE or UPDATE requests. If the NUTAG_SESSION_TIMER()
- * value is 0 or the value in the @SessionExpires header of the requeast is
+ * value is 0 or the value in the @SessionExpires header of the request is
* lower than the value in NUTAG_SESSION_TIMER(), the value from the
* incoming @SessionExpires header is used. However, if the value in
* @SessionExpires is lower than the minimal acceptable session expiration
* interval specified with the tag NUTAG_MIN_SE() the request is
* automatically rejected with <i>422 Session Timer Too Small</i>.
*
+ * @par Refreshes
+ *
+ * After the initial INVITE request, the SIP session is refreshed at the
+ * intervals indicated by the @SessionExpires header returned in the 2XX
+ * response. The party indicated with the "refresher" parameter of the
+ * @SessionExpires header sends a re-INVITE requests (or an UPDATE
+ * request if NUTAG_UPDATE_REFRESH(1) parameter tag has been set).
+ *
* @par When to Use NUTAG_SESSION_TIMER()?
*
* The session time extension is enabled ("timer" feature tag is included in
* @Supported header) but not activated by default (no @SessionExpires
* header is included in the requests or responses by default). Using
- * non-zero value with NUTAG_SESSION_TIMER() activates it. When the
- * extension is activated, @nua refreshes the call state by sending periodic
- * re-INVITE or UPDATE requests unless the remote end indicated that it will
- * take care of refreshes.
+ * non-zero value with NUTAG_SESSION_TIMER() or NUTAG_SESSION_REFRESHER()
+ * activates it. When the extension is activated, @nua refreshes the call
+ * state by sending periodic re-INVITE or UPDATE requests unless the remote
+ * end indicated that it will take care of refreshes.
*
* The session timer extension is mainly useful for proxies or back-to-back
* user agents that keep call state. The call state is "soft" meaning that
@@ -512,6 +543,10 @@
* will be destroyed. An ordinary user-agent can also make use of session
* timer if it cannot get any activity feedback from RTP or other media.
*
+ * @note The session timer extension is used only if the feature
+ * tag "timer" is listed in the @Supported header, set by NUTAG_SUPPORTED(),
+ * SIPTAG_SUPPORTED(), or SIPTAG_SUPPORTED_STR() tags.
+ *
* @par Used with
* nua_invite(), nua_update(), nua_respond() \n
* nua_set_params() or nua_set_hparams() \n
@@ -530,8 +565,8 @@
* Corresponding tag taking reference parameter is NUTAG_SESSION_TIMER_REF()
*
* @sa NUTAG_SUPPORTED(), NUTAG_MIN_SE(), NUTAG_SESSION_REFRESHER(),
- * nua_invite(), #nua_r_invite, #nua_i_invite, nua_update(), #nua_r_update,
- * #nua_i_update,
+ * nua_invite(), #nua_r_invite, #nua_i_invite, nua_respond(),
+ * nua_update(), #nua_r_update, #nua_i_update,
* NUTAG_UPDATE_REFRESH(), @RFC4028, @SessionExpires, @MinSE
*/
#define NUTAG_SESSION_TIMER(x) nutag_session_timer, tag_uint_v((x))
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_100rel.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_100rel.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_100rel.c Fri Apr 13 10:33:30 2007
@@ -163,6 +163,7 @@
nua_set_params(ctx->b.nua,
NUTAG_EARLY_MEDIA(1),
+ NUTAG_SESSION_TIMER(180),
TAG_END());
run_b_until(ctx, nua_r_set_params, until_final_response);
@@ -970,6 +971,8 @@
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_update);
TEST(e->data->e_status, 200);
+ TEST_1(sip = sip_object(e->data->e_msg));
+ TEST_1(sip->sip_session_expires);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_proceeding);
@@ -1197,14 +1200,14 @@
nua_set_params(ctx->a.nua,
NUTAG_EARLY_MEDIA(1),
- SIPTAG_SUPPORTED_STR("100rel, precondition"),
+ SIPTAG_SUPPORTED_STR("100rel, precondition, timer"),
TAG_END());
run_a_until(ctx, nua_r_set_params, until_final_response);
nua_set_params(ctx->b.nua,
NUTAG_EARLY_MEDIA(1),
NUTAG_ONLY183_100REL(1),
- SIPTAG_SUPPORTED_STR("100rel, precondition"),
+ SIPTAG_SUPPORTED_STR("100rel, precondition, timer"),
TAG_END());
run_b_until(ctx, nua_r_set_params, until_final_response);
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_basic_call.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_basic_call.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_basic_call.c Fri Apr 13 10:33:30 2007
@@ -205,9 +205,16 @@
sip_replaces_t *repa, *repb;
nua_handle_t *nh;
+ static int once = 0;
+ sip_time_t se, min_se;
+
if (print_headings)
printf("TEST NUA-3.1: Basic call\n");
+ /* Disable session timer from proxy */
+ test_proxy_get_session_timer(ctx->p, &se, &min_se);
+ test_proxy_set_session_timer(ctx->p, 0, 0);
+
a_call->sdp = "m=audio 5008 RTP/AVP 8";
b_call->sdp = "m=audio 5010 RTP/AVP 0 8";
@@ -272,6 +279,10 @@
TEST_1(sip->sip_contact);
TEST_S(sip->sip_contact->m_display, "Bob");
TEST_S(sip->sip_contact->m_url->url_user, "b+b");
+ if (!once) {
+ /* The session expiration is not used by default. */
+ TEST_1(sip->sip_session_expires == NULL);
+ }
/* Test that B uses application-specific contact */
if (ctx->proxy_tests)
TEST_1(sip->sip_contact->m_url->url_user);
@@ -293,6 +304,10 @@
TEST_1(sip->sip_contact);
TEST_S(sip->sip_contact->m_display, "Alice");
TEST_S(sip->sip_contact->m_url->url_user, "a+a");
+ if (!once++) {
+ /* The Session-Expires header is not used by default. */
+ TEST_1(sip->sip_session_expires == NULL);
+ }
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */
TEST_1(is_offer_recv(e->data->e_tags));
@@ -342,6 +357,8 @@
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
+ test_proxy_set_session_timer(ctx->p, se, min_se);
+
if (print_headings)
printf("TEST NUA-3.1: PASSED\n");
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_call_reject.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_call_reject.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_call_reject.c Fri Apr 13 10:33:30 2007
@@ -262,6 +262,7 @@
/* ------------------------------------------------------------------------ */
int reject_302(CONDITION_PARAMS), reject_305(CONDITION_PARAMS);
+int redirect_always(CONDITION_PARAMS);
int reject_604(CONDITION_PARAMS);
/*
@@ -336,6 +337,26 @@
}
}
+int redirect_always(CONDITION_PARAMS)
+{
+ if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
+ return 0;
+
+ if (event == nua_i_invite) {
+ char user[30];
+ sip_contact_t m[1];
+ *m = *ep->contact;
+ snprintf(user, sizeof user, "user-%u", ep->flags.n++);
+ m->m_url->url_user = user;
+ RESPOND(ep, call, nh, SIP_302_MOVED_TEMPORARILY,
+ SIPTAG_CONTACT(m), TAG_END());
+ nua_handle_destroy(nh);
+ call->nh = NULL;
+ return 1;
+ }
+
+ return 0;
+}
int reject_604(CONDITION_PARAMS)
{
@@ -476,6 +497,25 @@
if (print_headings)
printf("TEST NUA-4.3: PASSED\n");
+ if (print_headings)
+ printf("TEST NUA-4.3.1: redirect until retry count is exceeded\n");
+
+ TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
+ INVITE(a, a_call, a_call->nh,
+ TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
+ SIPTAG_SUBJECT_STR("redirect always"),
+ SOATAG_USER_SDP_STR(a_call->sdp),
+ TAG_END());
+ run_ab_until(ctx, -1, until_terminated, -1, redirect_always);
+
+ free_events_in_list(ctx, a->events);
+ nua_handle_destroy(a_call->nh), a_call->nh = NULL;
+ free_events_in_list(ctx, b->events);
+ nua_handle_destroy(b_call->nh), b_call->nh = NULL;
+
+ if (print_headings)
+ printf("TEST NUA-4.3: PASSED\n");
+
END();
}
@@ -874,7 +914,7 @@
}
}
-int authenticate_once(CONDITION_PARAMS)
+int authenticate_bad(CONDITION_PARAMS)
{
if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
return 0;
@@ -882,13 +922,8 @@
save_event_in_list(ctx, event, ep, call);
if (event == nua_r_invite && status == 401) {
- if (ep->flags.bit0) {
- nua_handle_destroy(nh); if (call) call->nh = NULL;
- return 1;
- }
- ep->flags.bit0 = 1;
AUTHENTICATE(ep, call, nh, NUTAG_AUTH("Digest:\"No hope\":jaska:secret"),
- SIPTAG_SUBJECT_STR("Got 401"),
+ SIPTAG_SUBJECT_STR("Bad password"),
TAG_END());
return 0;
}
@@ -925,7 +960,8 @@
SOATAG_USER_SDP_STR(a_call->sdp),
TAG_END());
- run_ab_until(ctx, -1, authenticate_once, -1, reject_401_bad);
+
+ run_ab_until(ctx, -1, authenticate_bad, -1, reject_401_bad);
/*
Client transitions
@@ -941,7 +977,12 @@
TEST_1(is_offer_sent(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite);
TEST(sip_object(e->data->e_msg)->sip_status->st_status, 401);
- TEST_1(!e->next);
+ /* nua_authenticate() fails and INVITE returns an internal error response */
+ TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite);
+ TEST(e->data->e_status, 904);
+ TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
+ TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */
+ TEST_1(!e->next);
free_events_in_list(ctx, a->events);
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_cancel_bye.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_cancel_bye.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_cancel_bye.c Fri Apr 13 10:33:30 2007
@@ -871,13 +871,12 @@
return len;
}
-int test_early_bye(struct context *ctx)
+int test_bye_before_200(struct context *ctx)
{
BEGIN();
struct endpoint *a = &ctx->a, *b = &ctx->b;
struct call *a_call = a->call, *b_call = b->call;
struct event *e;
- struct nat_filter *f = NULL;
a_call->sdp = "m=audio 5008 RTP/AVP 8";
b_call->sdp = "m=audio 5010 RTP/AVP 0 8";
@@ -950,6 +949,41 @@
if (print_headings)
printf("TEST NUA-6.1: PASSED\n");
+ END();
+}
+
+
+int bye_when_completing(CONDITION_PARAMS)
+{
+ if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
+ return 0;
+
+ save_event_in_list(ctx, event, ep, call);
+
+ switch (callstate(tags)) {
+ case nua_callstate_completing:
+ ack_sent = 0;
+ BYE(ep, call, nh, TAG_END());
+ return 0;
+ case nua_callstate_terminated:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+
+int test_bye_before_ack(struct context *ctx)
+{
+ BEGIN();
+ struct endpoint *a = &ctx->a, *b = &ctx->b;
+ struct call *a_call = a->call, *b_call = b->call;
+ struct event *e;
+ struct nat_filter *f = NULL;
+
+ a_call->sdp = "m=audio 5008 RTP/AVP 8";
+ b_call->sdp = "m=audio 5010 RTP/AVP 0 8";
+
/* Early BYE 2
A B
@@ -1048,21 +1082,275 @@
END();
}
-int bye_when_completing(CONDITION_PARAMS)
+int reject_reinvite_401(CONDITION_PARAMS);
+
+int test_bye_after_receiving_401(struct context *ctx)
{
- if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
- return 0;
+ BEGIN();
+ struct endpoint *a = &ctx->a, *b = &ctx->b;
+ struct call *a_call = a->call, *b_call = b->call;
+ struct event *e;
+
+ a_call->sdp = "m=audio 5008 RTP/AVP 8";
+ b_call->sdp = "m=audio 5010 RTP/AVP 0 8";
+
+/* BYE after receiving 401
+
+ A B
+ |-------INVITE------>|
+ |<----100 Trying-----|
+ | |
+ |<----180 Ringing----|
+ |<-------200---------|
+ |--------ACK-------->|
+ | |
+ |<------INVITE-------|
+ |--------401-------->|
+ |<--------ACK--------|
+ | |
+ |<--------BYE--------|
+ |------200 OK------->|
+ | |
+*/
+ if (print_headings)
+ printf("TEST NUA-6.3: BYE after receiving 401\n");
+
+ TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
+
+ INVITE(a, a_call, a_call->nh,
+ TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
+ SIPTAG_SUBJECT_STR("NUA-6.3"),
+ SOATAG_USER_SDP_STR(a_call->sdp),
+ NUTAG_AUTOANSWER(0),
+ TAG_END());
+
+ run_ab_until(ctx, -1, until_ready, -1, accept_call);
+
+ free_events_in_list(ctx, a->events);
+
+ TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_invite);
+ free_events_in_list(ctx, b->events);
+
+ /* re-INVITE A. */
+ INVITE(b, b_call, b_call->nh,
+ SIPTAG_SUBJECT_STR("NUA-6.3 re-INVITE"),
+ TAG_END());
+ run_ab_until(ctx, -1, reject_reinvite_401, -1, until_final_response);
+
+ TEST_1(nua_handle_has_active_call(a_call->nh));
+ TEST_1(nua_handle_has_active_call(b_call->nh));
+
+ free_events_in_list(ctx, a->events);
+ free_events_in_list(ctx, b->events);
+
+ BYE(b, b_call, b_call->nh, TAG_END());
+
+ run_ab_until(ctx, -1, until_terminated, -1, until_terminated);
+
+ free_events_in_list(ctx, a->events);
+ nua_handle_destroy(a_call->nh), a_call->nh = NULL;
+
+ free_events_in_list(ctx, b->events);
+ nua_handle_destroy(b_call->nh), b_call->nh = NULL;
+
+ if (print_headings)
+ printf("TEST NUA-6.3: PASSED\n");
+
+ END();
+}
+
+int test_bye_after_sending_401(struct context *ctx)
+{
+ BEGIN();
+ struct endpoint *a = &ctx->a, *b = &ctx->b;
+ struct call *a_call = a->call, *b_call = b->call;
+ struct event *e;
+
+ a_call->sdp = "m=audio 5008 RTP/AVP 8";
+ b_call->sdp = "m=audio 5010 RTP/AVP 0 8";
+
+/* BYE after sending 401
+
+ A B
+ |-------INVITE------>|
+ |<----100 Trying-----|
+ | |
+ |<----180 Ringing----|
+ |<-------200---------|
+ |--------ACK-------->|
+ | |
+ |<------INVITE-------|
+ |--------401-------->|
+ |<--------ACK--------|
+ | |
+ |--------BYE-------->|
+ |<------200 OK-------|
+ | |
+*/
+ if (print_headings)
+ printf("TEST NUA-6.4: BYE after sending 401\n");
+
+ TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
+
+ INVITE(a, a_call, a_call->nh,
+ TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
+ SIPTAG_SUBJECT_STR("NUA-6.4"),
+ SOATAG_USER_SDP_STR(a_call->sdp),
+ NUTAG_AUTOANSWER(0),
+ TAG_END());
+
+ run_ab_until(ctx, -1, until_ready, -1, accept_call);
+
+ free_events_in_list(ctx, a->events);
+
+ TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_invite);
+ free_events_in_list(ctx, b->events);
+
+ /* re-INVITE A. */
+ INVITE(b, b_call, b_call->nh,
+ SIPTAG_SUBJECT_STR("NUA-6.4 re-INVITE"),
+ TAG_END());
+ run_ab_until(ctx, -1, reject_reinvite_401, -1, until_final_response);
+
+ TEST_1(nua_handle_has_active_call(a_call->nh));
+ TEST_1(nua_handle_has_active_call(b_call->nh));
+
+ free_events_in_list(ctx, a->events);
+ free_events_in_list(ctx, b->events);
+
+ BYE(a, a_call, a_call->nh, TAG_END());
+
+ run_ab_until(ctx, -1, until_terminated, -1, until_terminated);
+
+ free_events_in_list(ctx, a->events);
+ nua_handle_destroy(a_call->nh), a_call->nh = NULL;
+
+ free_events_in_list(ctx, b->events);
+ nua_handle_destroy(b_call->nh), b_call->nh = NULL;
+
+ if (print_headings)
+ printf("TEST NUA-6.4: PASSED\n");
+
+ END();
+}
+
+int test_bye_after_receiving_401_to_update(struct context *ctx)
+{
+ BEGIN();
+ struct endpoint *a = &ctx->a, *b = &ctx->b;
+ struct call *a_call = a->call, *b_call = b->call;
+ struct event *e;
+
+ a_call->sdp = "m=audio 5008 RTP/AVP 8";
+ b_call->sdp = "m=audio 5010 RTP/AVP 0 8";
+
+/* BYE after receiving 401
+
+ A B
+ |-------INVITE------>|
+ |<----100 Trying-----|
+ | |
+ |<----180 Ringing----|
+ |<-------200---------|
+ |--------ACK-------->|
+ | |
+ |<------UPDATE-------|
+ |--------401-------->|
+ | |
+ |<--------BYE--------|
+ |------200 OK------->|
+ | |
+*/
+ if (print_headings)
+ printf("TEST NUA-6.5: BYE after receiving 401 to UPDATE\n");
+
+ TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
+
+ INVITE(a, a_call, a_call->nh,
+ TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
+ SIPTAG_SUBJECT_STR("NUA-6.5"),
+ SOATAG_USER_SDP_STR(a_call->sdp),
+ NUTAG_AUTOANSWER(0),
+ NUTAG_APPL_METHOD("UPDATE"),
+ TAG_END());
+
+ run_ab_until(ctx, -1, until_ready, -1, accept_call);
+
+ free_events_in_list(ctx, a->events);
+
+ TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_invite);
+ free_events_in_list(ctx, b->events);
+
+ /* UPDATE A. */
+ UPDATE(b, b_call, b_call->nh,
+ SIPTAG_SUBJECT_STR("NUA-6.4 UPDATE"),
+ TAG_END());
+ BYE(b, b_call, b_call->nh, TAG_END()); /* Queued until nua_authenticate */
+ run_ab_until(ctx, -1, reject_reinvite_401, -1, until_final_response);
+
+ TEST_1(nua_handle_has_active_call(a_call->nh));
+ TEST_1(nua_handle_has_active_call(b_call->nh));
+
+ free_events_in_list(ctx, a->events);
+ free_events_in_list(ctx, b->events);
+
+ AUTHENTICATE(b, b_call, b_call->nh, TAG_END());
+
+ run_ab_until(ctx, -1, until_terminated, -1, until_terminated);
+
+ free_events_in_list(ctx, a->events);
+ nua_handle_destroy(a_call->nh), a_call->nh = NULL;
+
+ free_events_in_list(ctx, b->events);
+ nua_handle_destroy(b_call->nh), b_call->nh = NULL;
+
+ if (print_headings)
+ printf("TEST NUA-6.3: PASSED\n");
+
+ END();
+}
+
+int reject_reinvite_401(CONDITION_PARAMS)
+{
+ void *request = nua_current_request(nua);
save_event_in_list(ctx, event, ep, call);
- switch (callstate(tags)) {
- case nua_callstate_completing:
- ack_sent = 0;
- BYE(ep, call, nh, TAG_END());
+ if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
+ return 0;
+
+ if (status < 200 && (event == nua_i_invite || event == nua_i_update)) {
+ RESPOND(ep, call, nh, SIP_401_UNAUTHORIZED,
+ NUTAG_WITH(request),
+ SIPTAG_WWW_AUTHENTICATE_STR("Digest realm=\"test_nua\", "
+ "nonce=\"nsdhfuds\", algorithm=MD5, "
+ "qop=\"auth\""),
+ TAG_END());
return 0;
+ }
+
+ if (event == nua_i_state) switch (callstate(tags)) {
+ case nua_callstate_ready:
+ return 1;
case nua_callstate_terminated:
+ if (call)
+ nua_handle_destroy(call->nh), call->nh = NULL;
return 1;
default:
return 0;
}
+
+ return 0;
+}
+
+
+int test_early_bye(struct context *ctx)
+{
+ return
+ test_bye_before_200(ctx) ||
+ test_bye_before_ack(ctx) ||
+ test_bye_after_receiving_401(ctx) ||
+ test_bye_after_sending_401(ctx) ||
+ test_bye_after_receiving_401_to_update(ctx) ||
+ 0;
}
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_nua.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_nua.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_nua.c Fri Apr 13 10:33:30 2007
@@ -248,8 +248,15 @@
}
#if HAVE_ALARM
else if (o_alarm) {
- alarm(o_expensive ? 60 : 120);
signal(SIGALRM, sig_alarm);
+ if (o_expensive) {
+ printf("%s: extending timeout to %u because expensive tests\n",
+ name, 240);
+ alarm(240);
+ }
+ else {
+ alarm(120);
+ }
}
#endif
@@ -316,8 +323,8 @@
retval |= test_session_timer(ctx); SINGLE_FAILURE_CHECK();
retval |= test_refer(ctx); SINGLE_FAILURE_CHECK();
retval |= test_100rel(ctx); SINGLE_FAILURE_CHECK();
- retval |= test_events(ctx); SINGLE_FAILURE_CHECK();
retval |= test_simple(ctx); SINGLE_FAILURE_CHECK();
+ retval |= test_events(ctx); SINGLE_FAILURE_CHECK();
retval |= test_extension(ctx); SINGLE_FAILURE_CHECK();
if (!o_loop)
break;
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_offer_answer.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_offer_answer.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_offer_answer.c Fri Apr 13 10:33:30 2007
@@ -86,7 +86,7 @@
sip_t *sip;
if (print_headings)
- printf("TEST NUA-6.3: No SDP answer from callee\n");
+ printf("TEST NUA-6.5: No SDP answer from callee\n");
a_call->sdp = "m=audio 5008 RTP/AVP 8";
b_call->sdp = NULL;
@@ -184,7 +184,7 @@
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
if (print_headings)
- printf("TEST NUA-6.3: PASSED\n");
+ printf("TEST NUA-6.5: PASSED\n");
END();
}
@@ -229,7 +229,7 @@
sip_t const *sip;
if (print_headings)
- printf("TEST NUA-6.4: No SDP offer from caller\n");
+ printf("TEST NUA-6.6: No SDP offer from caller\n");
a_call->sdp = "v=0\r\n"
"o=- 1 1 IN IP4 127.0.0.1\r\n"
@@ -330,7 +330,7 @@
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
if (print_headings)
- printf("TEST NUA-6.4: PASSED\n");
+ printf("TEST NUA-6.6: PASSED\n");
END();
}
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_proxy.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_proxy.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_proxy.c Fri Apr 13 10:33:30 2007
@@ -375,6 +375,27 @@
}
}
+void test_proxy_set_session_timer(struct proxy *p,
+ sip_time_t session_expires,
+ sip_time_t min_se)
+{
+ if (p) {
+ p->prefs.session_expires = session_expires;
+ p->prefs.min_se = min_se;
+ }
+}
+
+void test_proxy_get_session_timer(struct proxy *p,
+ sip_time_t *return_session_expires,
+ sip_time_t *return_min_se)
+{
+ if (p) {
+ if (return_session_expires)
+ *return_session_expires = p->prefs.session_expires;
+ if (return_min_se) *return_min_se = p->prefs.min_se;
+ }
+}
+
/* ---------------------------------------------------------------------- */
static sip_contact_t *create_transport_contacts(struct proxy *p)
@@ -427,6 +448,7 @@
sip_session_expires_t *x = NULL, x0[1];
sip_min_se_t *min_se = NULL, min_se0[1];
+ char const *require = NULL;
mf = sip->sip_max_forwards;
@@ -447,24 +469,33 @@
}
if (method == sip_method_invite) {
- if (!sip->sip_min_se ||
- sip->sip_min_se->min_delta < proxy->prefs.min_se) {
- min_se = sip_min_se_init(min_se0);
- min_se->min_delta = proxy->prefs.min_se;
- }
-
- if (!sip->sip_session_expires) {
- x = sip_session_expires_init(x0);
- x->x_delta = proxy->prefs.session_expires;
- }
- else if (sip->sip_session_expires->x_delta < proxy->prefs.min_se
- && sip_has_supported(sip->sip_supported, "timer")) {
- if (min_se == NULL)
- min_se = sip->sip_min_se; assert(min_se);
- nta_incoming_treply(irq, SIP_422_SESSION_TIMER_TOO_SMALL,
- SIPTAG_MIN_SE(min_se),
- TAG_END());
- return 422;
+ if (proxy->prefs.min_se) {
+ if (!sip->sip_min_se ||
+ sip->sip_min_se->min_delta < proxy->prefs.min_se) {
+ min_se = sip_min_se_init(min_se0);
+ min_se->min_delta = proxy->prefs.min_se;
+ }
+
+ if (sip->sip_session_expires
+ && sip->sip_session_expires->x_delta < proxy->prefs.min_se
+ && sip_has_supported(sip->sip_supported, "timer")) {
+ if (min_se == NULL)
+ min_se = sip->sip_min_se; assert(min_se);
+ nta_incoming_treply(irq, SIP_422_SESSION_TIMER_TOO_SMALL,
+ SIPTAG_MIN_SE(min_se),
+ TAG_END());
+ return 422;
+ }
+ }
+
+ if (proxy->prefs.session_expires) {
+ if (!sip->sip_session_expires ||
+ sip->sip_session_expires->x_delta > proxy->prefs.session_expires) {
+ x = sip_session_expires_init(x0);
+ x->x_delta = proxy->prefs.session_expires;
+ if (!sip_has_supported(sip->sip_supported, "timer"))
+ require = "timer";
+ }
}
}
@@ -528,6 +559,7 @@
SIPTAG_REQUEST(rq),
SIPTAG_SESSION_EXPIRES(x),
SIPTAG_MIN_SE(min_se),
+ SIPTAG_REQUIRE_STR(require),
TAG_END());
if (t->client == NULL) {
proxy_transaction_destroy(t);
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_proxy.h
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_proxy.h (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_proxy.h Fri Apr 13 10:33:30 2007
@@ -48,6 +48,14 @@
sip_time_t *return_expires,
sip_time_t *return_max_expires);
+void test_proxy_set_session_timer(struct proxy *p,
+ sip_time_t session_expires,
+ sip_time_t min_se);
+
+void test_proxy_get_session_timer(struct proxy *p,
+ sip_time_t *return_session_expires,
+ sip_time_t *return_min_se);
+
SOFIA_END_DECLS
#endif
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_register.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_register.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_register.c Fri Apr 13 10:33:30 2007
@@ -685,6 +685,10 @@
run_a_until(ctx, -1, save_until_final_response);
TEST_1(e = a->events->head);
TEST_E(e->data->e_event, nua_r_unregister);
+ if (e->data->e_status == 100) {
+ TEST_1(e = e->next);
+ TEST_E(e->data->e_event, nua_r_unregister);
+ }
TEST(e->data->e_status, 200);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(!sip->sip_contact);
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_session_timer.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_session_timer.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_session_timer.c Fri Apr 13 10:33:30 2007
@@ -22,7 +22,7 @@
*
*/
-/**@CFILE test_nua_re_invite.c
+/**@CFILE test_session_timer.c
* @brief NUA-8 tests: Session timer, UPDATE
*
* @author Pekka Pessi <Pekka.Pessi at nokia.com>
@@ -40,11 +40,13 @@
#elif HAVE_FUNCTION
#define __func__ __FUNCTION__
#else
-#define __func__ "test_call_hold"
+#define __func__ "test_session_timer"
#endif
/* ======================================================================== */
+static size_t remove_update(void *a, void *message, size_t len);
+
int test_session_timer(struct context *ctx)
{
BEGIN();
@@ -69,22 +71,6 @@
|--INVITE->| |
|<--422----| |
|---ACK--->| |
- | |
- |-------INVITE------>|
- |<-------422---------|
- |--------ACK-------->|
- | |
- |-------INVITE------>|
- |<----100 Trying-----|
- | |
- |<----180 Ringing----|
- | |
- |<------200 OK-------|
- |--------ACK-------->|
- | |
- |<-------BYE---------|
- |-------200 OK-------|
- | |
*/
@@ -94,8 +80,15 @@
a_call->sdp = "m=audio 5008 RTP/AVP 8";
b_call->sdp = "m=audio 5010 RTP/AVP 0 8";
+ /* We negotiate session timer of 6 second */
+ /* Disable session timer from proxy */
+ test_proxy_set_session_timer(ctx->p, 0, 0);
+
nua_set_params(ctx->b.nua,
NUTAG_SESSION_REFRESHER(nua_any_refresher),
+ NUTAG_MIN_SE(1),
+ NUTAG_SESSION_TIMER(6),
+ NTATAG_SIP_T1X64(8000),
TAG_END());
run_b_until(ctx, nua_r_set_params, until_final_response);
@@ -159,23 +152,132 @@
if (print_headings)
printf("TEST NUA-8.1.1: PASSED\n");
+ if (ctx->expensive) {
+ nua_set_hparams(a_call->nh,
+ NUTAG_SUPPORTED("timer"),
+ NUTAG_MIN_SE(1),
+ NUTAG_SESSION_TIMER(5),
+ TAG_END());
+ run_a_until(ctx, nua_r_set_params, until_final_response);
+
+ if (print_headings)
+ printf("TEST NUA-8.1.2: Wait for refresh using INVITE\n");
+
+ run_ab_until(ctx, -1, until_ready, -1, until_ready);
+
+ free_events_in_list(ctx, a->events);
+ free_events_in_list(ctx, b->events);
+
+ if (print_headings)
+ printf("TEST NUA-8.1.2: PASSED\n");
+
+ nua_set_hparams(b_call->nh,
+ NUTAG_UPDATE_REFRESH(1),
+ TAG_END());
+ run_b_until(ctx, nua_r_set_params, until_final_response);
+
+ if (print_headings)
+ printf("TEST NUA-8.1.3: Wait for refresh using UPDATE\n");
+
+ run_ab_until(ctx, -1, until_ready, -1, until_ready);
+
+ TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_update);
+
+ free_events_in_list(ctx, a->events);
+ free_events_in_list(ctx, b->events);
+
+ if (print_headings)
+ printf("TEST NUA-8.1.3: PASSED\n");
+
+ if (ctx->nat) {
+ struct nat_filter *f;
+
+ if (print_headings)
+ printf("TEST NUA-8.1.4: filter UPDATE, wait until session expires\n");
+
+ f = test_nat_add_filter(ctx->nat, remove_update, NULL, nat_inbound);
+ TEST_1(f);
+
+ run_ab_until(ctx, -1, until_terminated, -1, until_terminated);
+
+ TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_bye);
+
+ free_events_in_list(ctx, a->events);
+ free_events_in_list(ctx, b->events);
+
+ nua_handle_destroy(a_call->nh), a_call->nh = NULL;
+ nua_handle_destroy(b_call->nh), b_call->nh = NULL;
+
+ test_nat_remove_filter(ctx->nat, f);
+
+ if (print_headings)
+ printf("TEST NUA-8.1.4: PASSED\n");
+ }
+ }
+
+ if (b_call->nh) {
+ if (print_headings)
+ printf("TEST NUA-8.1.9: Terminate first session timer call\n");
+
+ BYE(b, b_call, b_call->nh, TAG_END());
+ run_ab_until(ctx, -1, until_terminated, -1, until_terminated);
+ free_events_in_list(ctx, a->events);
+ free_events_in_list(ctx, b->events);
+
+ nua_handle_destroy(a_call->nh), a_call->nh = NULL;
+ nua_handle_destroy(b_call->nh), b_call->nh = NULL;
+
+ if (print_headings)
+ printf("TEST NUA-8.1.9: PASSED\n");
+ }
+
+ /*
+ | |
+ |-------INVITE------>|
+ |<-------422---------|
+ |--------ACK-------->|
+ | |
+ |-------INVITE------>|
+ |<----100 Trying-----|
+ | |
+ |<----180 Ringing----|
+ | |
+ |<------200 OK-------|
+ |--------ACK-------->|
+ | |
+ |<-------BYE---------|
+ |-------200 OK-------|
+ | |
+ */
+
if (print_headings)
- printf("TEST NUA-8.1.2: Session timers negotiation\n");
+ printf("TEST NUA-8.2: Session timers negotiation\n");
+
+ test_proxy_set_session_timer(ctx->p, 180, 90);
+
+ nua_set_params(a->nua,
+ NUTAG_SUPPORTED("timer"),
+ TAG_END());
+
+ run_a_until(ctx, nua_r_set_params, until_final_response);
- nua_set_hparams(b_call->nh,
- NUTAG_AUTOANSWER(0),
- NUTAG_MIN_SE(120),
- TAG_END());
+ nua_set_params(b->nua,
+ NUTAG_AUTOANSWER(0),
+ NUTAG_MIN_SE(120),
+ NTATAG_SIP_T1X64(2000),
+ TAG_END());
run_b_until(ctx, nua_r_set_params, until_final_response);
+ TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to),
+ TAG_END()));
INVITE(a, a_call, a_call->nh,
TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
SOATAG_USER_SDP_STR(a_call->sdp),
SIPTAG_SUPPORTED_STR("100rel, timer"),
- NUTAG_SESSION_TIMER(15),
- NUTAG_MIN_SE(5),
+ NUTAG_SESSION_TIMER(4),
+ NUTAG_MIN_SE(3),
TAG_END());
run_ab_until(ctx, -1, until_ready, -1, accept_call);
@@ -252,17 +354,17 @@
free_events_in_list(ctx, b->events);
if (print_headings)
- printf("TEST NUA-8.1: PASSED\n");
+ printf("TEST NUA-8.2: PASSED\n");
if (print_headings)
- printf("TEST NUA-8.2: use UPDATE\n");
+ printf("TEST NUA-8.3: UPDATE with session timer headers\n");
UPDATE(b, b_call, b_call->nh, TAG_END());
run_ab_until(ctx, -1, until_ready, -1, until_ready);
/* Events from B (who sent UPDATE) */
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_state);
- TEST(callstate(e->data->e_tags), nua_callstate_ready); /* READY */
+ TEST(callstate(e->data->e_tags), nua_callstate_calling); /* CALLING */
TEST_1(is_offer_sent(e->data->e_tags));
if (!e->next)
run_b_until(ctx, -1, until_ready);
@@ -313,7 +415,20 @@
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
if (print_headings)
- printf("TEST NUA-8.2: PASSED\n");
+ printf("TEST NUA-8.3: PASSED\n");
END();
}
+
+static
+size_t remove_update(void *a, void *message, size_t len)
+{
+ (void)a;
+
+ if (strncmp("UPDATE ", message, 7) == 0) {
+ return 0;
+ }
+
+ return len;
+}
+
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_simple.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_simple.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/nua/test_simple.c Fri Apr 13 10:33:30 2007
@@ -972,6 +972,7 @@
return ep->flags.bit0 && ep->flags.bit1;
}
+
/* ---------------------------------------------------------------------- */
/* Unsolicited NOTIFY */
@@ -1122,7 +1123,7 @@
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
if (print_headings)
- printf("TEST NUA-11.6: PASSED\n");
+ printf("TEST NUA-11.7: PASSED\n");
END();
}
@@ -1144,6 +1145,155 @@
}
/* ======================================================================== */
+
+int save_until_subscription_terminated(CONDITION_PARAMS);
+int accept_subscription_until_terminated(CONDITION_PARAMS);
+
+/* Timeout subscription */
+int test_subscription_timeout(struct context *ctx)
+{
+ BEGIN();
+
+ struct endpoint *a = &ctx->a, *b = &ctx->b;
+ struct call *a_call = a->call, *b_call = b->call;
+ struct event *e;
+ sip_t const *sip;
+ tagi_t const *n_tags, *r_tags;
+
+ if (print_headings)
+ printf("TEST NUA-11.8: subscribe and wait until subscription times out\n");
+
+ TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
+
+ METHOD(a, a_call, a_call->nh,
+ NUTAG_METHOD("SUBSCRIBE"),
+ NUTAG_URL(b->contact->m_url),
+ SIPTAG_EVENT_STR("presence"),
+ SIPTAG_ACCEPT_STR("application/xpidf, application/pidf+xml"),
+ SIPTAG_EXPIRES_STR("2"),
+ NUTAG_APPL_METHOD("NOTIFY"),
+ NUTAG_DIALOG(2),
+ TAG_END());
+
+ run_ab_until(ctx,
+ -1, save_until_subscription_terminated,
+ -1, accept_subscription_until_terminated);
+
+ /* Client events:
+ nua_method(), nua_i_notify/nua_r_method, nua_i_notify
+ */
+ TEST_1(e = a->events->head);
+ if (e->data->e_event == nua_i_notify) {
+ TEST_E(e->data->e_event, nua_i_notify);
+ TEST_1(sip = sip_object(e->data->e_msg));
+ n_tags = e->data->e_tags;
+ TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_subscribe);
+ r_tags = e->data->e_tags;
+ }
+ else {
+ TEST_E(e->data->e_event, nua_r_method);
+ TEST(e->data->e_status, 202);
+ r_tags = e->data->e_tags;
+ TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_notify);
+ TEST_1(sip = sip_object(e->data->e_msg));
+ n_tags = e->data->e_tags;
+ }
+ TEST_1(sip->sip_event); TEST_S(sip->sip_event->o_type, "presence");
+ TEST_1(sip->sip_content_type);
+ TEST_S(sip->sip_content_type->c_type, "application/pidf+xml");
+ TEST_1(sip->sip_subscription_state);
+ TEST_S(sip->sip_subscription_state->ss_substate, "pending");
+ TEST_1(sip->sip_subscription_state->ss_expires);
+ TEST_1(tl_find(n_tags, nutag_substate));
+ TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_pending);
+
+ TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_notify);
+ n_tags = e->data->e_tags;
+ TEST_1(tl_find(n_tags, nutag_substate));
+ TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_terminated);
+ TEST_1(sip = sip_object(e->data->e_msg));
+ TEST_1(sip->sip_event);
+ TEST_1(sip->sip_subscription_state);
+ TEST_S(sip->sip_subscription_state->ss_substate, "terminated");
+ TEST_1(!sip->sip_subscription_state->ss_expires);
+ TEST_1(!e->next);
+
+ free_events_in_list(ctx, a->events);
+
+ /* Server events: nua_i_subscribe, nua_r_notify */
+ TEST_1(e = b->events->head);
+ TEST_E(e->data->e_event, nua_i_subscribe);
+ TEST_E(e->data->e_status, 100);
+ TEST_1(sip = sip_object(e->data->e_msg));
+
+ TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify);
+ r_tags = e->data->e_tags;
+ TEST_1(tl_find(r_tags, nutag_substate));
+ TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_pending);
+
+ /* Notifier events: 2nd nua_r_notify */
+ TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify);
+ TEST_1(e->data->e_status >= 200);
+ r_tags = e->data->e_tags;
+ TEST_1(tl_find(r_tags, nutag_substate));
+ TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_terminated);
+
+ free_events_in_list(ctx, b->events);
+
+ nua_handle_destroy(a_call->nh), a_call->nh = NULL;
+ nua_handle_destroy(b_call->nh), b_call->nh = NULL;
+
+ if (print_headings)
+ printf("TEST NUA-11.8: PASSED\n");
+
+ END();
+}
+
+int save_until_subscription_terminated(CONDITION_PARAMS)
+{
+ void *with = nua_current_request(nua);
+
+ save_event_in_list(ctx, event, ep, call);
+
+ if (event == nua_i_notify) {
+ if (status < 200)
+ RESPOND(ep, call, nh, SIP_200_OK, NUTAG_WITH(with), TAG_END());
+
+ tags = tl_find(tags, nutag_substate);
+ return tags && tags->t_value == nua_substate_terminated;
+ }
+
+ return 0;
+}
+
+int accept_subscription_until_terminated(CONDITION_PARAMS)
+{
+ void *with = nua_current_request(nua);
+
+ save_event_in_list(ctx, event, ep, call);
+
+ if (event == nua_i_subscribe && status < 200) {
+ RESPOND(ep, call, nh, SIP_202_ACCEPTED,
+ NUTAG_WITH(with),
+ SIPTAG_EXPIRES_STR("360"),
+ TAG_END());
+ NOTIFY(ep, call, nh,
+ SIPTAG_EVENT(sip->sip_event),
+ SIPTAG_CONTENT_TYPE_STR("application/pidf+xml"),
+ SIPTAG_PAYLOAD_STR(presence_closed),
+ NUTAG_SUBSTATE(nua_substate_pending),
+ TAG_END());
+ }
+ else if (event == nua_r_notify) {
+ tags = tl_find(tags, nutag_substate);
+ return tags && tags->t_value == nua_substate_terminated;
+ }
+
+ return 0;
+}
+
+
+/* ======================================================================== */
/* Test simple methods: MESSAGE, PUBLISH, SUBSCRIBE/NOTIFY */
int test_simple(struct context *ctx)
@@ -1154,5 +1304,6 @@
|| test_subscribe_notify(ctx)
|| test_subscribe_notify_graceful(ctx)
|| test_newsub_notify(ctx)
+ || test_subscription_timeout(ctx)
;
}
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/sdp/run_test_sdp
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/sdp/run_test_sdp (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/sdp/run_test_sdp Fri Apr 13 10:33:30 2007
@@ -6,7 +6,8 @@
#
test_sdp="${1:-./test_sdp}"
-tests="${2:-${0%/*}/tests}"
+sdp_path=`dirname $0`
+tests="${2:-${sdp_path}/tests}"
if test -r $tests/message-1.sdp ; then
@@ -20,4 +21,3 @@
echo "sdp run-tests: no tests found in $tests, skipping."
exit 77
fi
-
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/sip/sip_feature.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/sip/sip_feature.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/sip/sip_feature.c Fri Apr 13 10:33:30 2007
@@ -336,7 +336,7 @@
return msg_list_e(b, bsiz, h, f);
}
-/** Check if required feature is supported.
+/** Check if required feature is not supported.
*
* @retval NULL if all the required features are supported
* @retval pointer to a @Unsupported header or
@@ -351,7 +351,7 @@
}
-/** Check if required feature is supported.
+/** Check if required feature is not supported.
*
* @retval NULL if all the required features are supported
* @retval pointer to a @Unsupported header or
@@ -370,7 +370,7 @@
}
-/** Ensure that required features are supported.
+/** Check if required features are not supported.
*
* The supported features can be listed in @Supported, @Require or
* @ProxyRequire headers (in @a supported, @a by_require, or @a
Modified: freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/sip/torture_sip.c
==============================================================================
--- freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/sip/torture_sip.c (original)
+++ freeswitch/branches/mikej/sofiasip-upgrade/libs/sofia-sip/libsofia-sip-ua/sip/torture_sip.c Fri Apr 13 10:33:30 2007
@@ -354,7 +354,7 @@
su_home_t home[1] = { SU_HOME_INIT(home) };
char const *display;
url_t url[1];
- char const * const *params;
+ msg_param_t const *params;
char const *comment;
char const na[] = "Raaka Arska <tel:+358501970>;param=1;humppa (test) ";
char const na2[] = "tel:+358501970;param=1;humppa (test) ";
@@ -744,8 +744,6 @@
}
END();
-
- return 0;
}
msg_t *read_message(int flags, char const buffer[])
More information about the Freeswitch-svn
mailing list