static void nua_client_request_destroy(nua_client_request_t *cr);
static int nua_client_init_request0(nua_client_request_t *cr);
static int nua_client_request_try(nua_client_request_t *cr);
-static int nua_client_request_sendmsg(nua_client_request_t *cr,
- msg_t *msg, sip_t *sip);
+static int nua_client_request_sendmsg(nua_client_request_t *cr);
static void nua_client_restart_after(su_root_magic_t *magic,
su_timer_t *timer,
nua_client_request_t *cr);
(sip_header_t *)sip->sip_from) < 0) {
return nua_client_return(cr, NUA_ERROR_AT(__FILE__, __LINE__), msg);
}
-
- 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),
- SIPTAG_FROM(sip->sip_from),
- SIPTAG_TO(sip->sip_to),
- SIPTAG_CSEQ(sip->sip_cseq),
- TAG_END());
- if (!ds->ds_leg)
- return nua_client_return(cr, NUA_ERROR_AT(__FILE__, __LINE__), msg);
-
- if (!sip->sip_from->a_tag &&
- sip_from_tag(msg_home(msg), sip->sip_from,
- nta_leg_tag(ds->ds_leg, NULL)) < 0)
- return nua_client_return(cr, NUA_ERROR_AT(__FILE__, __LINE__), msg);
- }
}
else {
if (ds->ds_route)
if (nua_client_request_queue(cr))
return 0;
+
if (nua_dialog_is_reporting(cr->cr_owner->nh_ds))
return 0;
+
return nua_client_request_try(cr);
}
return 0;
}
-/** Create a request message and send it.
+/** Send a request message.
*
* If an error occurs, send error event to the application.
*
static
int nua_client_request_try(nua_client_request_t *cr)
{
- int error = -1;
- msg_t *msg = msg_copy(cr->cr_msg);
- sip_t *sip = sip_object(msg);
-
- cr->cr_answer_recv = 0, cr->cr_offer_sent = 0;
- cr->cr_offer_recv = 0, cr->cr_answer_sent = 0;
-
- if (msg && sip) {
- error = nua_client_request_sendmsg(cr, msg, sip);
- if (!error)
- return 0;
-
- if (error == -1)
- msg_destroy(msg);
- }
+ int error = nua_client_request_sendmsg(cr);
if (error < 0)
error = nua_client_response(cr, NUA_ERROR_AT(__FILE__, __LINE__), NULL);
- assert(error > 0);
return error;
}
*
* @retval 0 if request is pending
* @retval >=1 if error event has been sent
- * @retval -1 if error occurred but event has not been sent,
- and @a msg has not been destroyed
- * @retval -2 if error occurred, event has not been sent,
- * but @a msg has been destroyed
+ * @retval < 0 if no error event has been sent
*/
static
-int nua_client_request_sendmsg(nua_client_request_t *cr, msg_t *msg, sip_t *sip)
+int nua_client_request_sendmsg(nua_client_request_t *cr)
{
nua_handle_t *nh = cr->cr_owner;
nua_dialog_state_t *ds = nh->nh_ds;
char const *name = cr->cr_method_name;
url_string_t const *url = (url_string_t *)cr->cr_target;
nta_leg_t *leg;
+ msg_t *msg;
+ sip_t *sip;
+ int error;
assert(cr->cr_orq == NULL);
+ cr->cr_offer_sent = cr->cr_answer_recv = 0;
+ cr->cr_offer_recv = cr->cr_answer_sent = 0;
+
+ if (!ds->ds_leg && cr->cr_dialog) {
+ ds->ds_leg = nta_leg_tcreate(nh->nh_nua->nua_nta,
+ nua_stack_process_request, nh,
+ SIPTAG_CALL_ID(cr->cr_sip->sip_call_id),
+ SIPTAG_FROM(cr->cr_sip->sip_from),
+ SIPTAG_TO(cr->cr_sip->sip_to),
+ SIPTAG_CSEQ(cr->cr_sip->sip_cseq),
+ TAG_END());
+ if (!ds->ds_leg)
+ return -1;
+ }
+
+ if (cr->cr_sip->sip_from && ds->ds_leg) {
+ if (cr->cr_sip->sip_from->a_tag == NULL) {
+ if (sip_from_tag(msg_home(cr->cr_msg), cr->cr_sip->sip_from,
+ nta_leg_tag(ds->ds_leg, NULL)) < 0) {
+ return -1;
+ }
+ }
+ }
+
cr->cr_retry_count++;
if (ds->ds_leg)
else
leg = nh->nh_nua->nua_dhandle->nh_ds->ds_leg; /* Default leg */
+ msg = msg_copy(cr->cr_msg), sip = sip_object(msg);
+
+ if (msg == NULL)
+ return -1;
+
if (nua_dialog_is_established(ds)) {
while (sip->sip_route)
sip_route_remove(msg, sip);
* generated based on the dialog information and added to the request.
* If the dialog has a route, it is added to the request, too.
*/
- if (nta_msg_request_complete(msg, leg, method, name, url) < 0)
+ if (nta_msg_request_complete(msg, leg, method, name, url) < 0) {
+ msg_destroy(msg);
return -1;
+ }
/**@MaxForwards header (with default value set by NTATAG_MAX_FORWARDS()) is
* also added now, if it does not exist.
cr->cr_contactize &&
!cr->cr_has_contact &&
!ds->ds_ltarget,
- !ds->ds_route) < 0)
+ !ds->ds_route) < 0) {
+ msg_destroy(msg);
return -1;
+ }
}
cr->cr_wait_for_cred = 0;
if (cr->cr_methods->crm_send)
- return cr->cr_methods->crm_send(cr, msg, sip, NULL);
+ error = cr->cr_methods->crm_send(cr, msg, sip, NULL);
+ else
+ error = nua_base_client_request(cr, msg, sip, NULL);
- return nua_base_client_request(cr, msg, sip, NULL);
+ if (error != 0 && error != -2)
+ msg_destroy(msg);
+
+ return error;
}
/**Add tags to request message and send it,
}
/** Callback for nta client transaction */
-int nua_client_orq_response(nua_client_request_t *cr,
- nta_outgoing_t *orq,
- sip_t const *sip)
+int
+nua_client_orq_response(nua_client_request_t *cr,
+ nta_outgoing_t *orq,
+ sip_t const *sip)
{
int status;
char const *phrase;
int status, char const *phrase)
{
nua_handle_t *nh = cr->cr_owner;
- nua_dialog_state_t *ds = nh->nh_ds;
nta_outgoing_t *orq;
int error = -1, terminated, graceful;
- msg_t *msg = NULL;
- sip_t *sip = NULL;
if (cr->cr_retry_count > NH_PGET(nh, retry_count))
return 0;
orq = cr->cr_orq, cr->cr_orq = NULL; assert(orq);
terminated = cr->cr_terminated, cr->cr_terminated = 0;
graceful = cr->cr_graceful, cr->cr_graceful = 0;
- cr->cr_offer_sent = cr->cr_answer_recv = 0;
- cr->cr_offer_recv = cr->cr_answer_sent = 0;
-
- if (!ds->ds_leg && cr->cr_dialog) {
- sip_t const *sip = cr->cr_sip;
- ds->ds_leg = nta_leg_tcreate(nh->nh_nua->nua_nta,
- nua_stack_process_request, nh,
- SIPTAG_CALL_ID(sip->sip_call_id),
- SIPTAG_FROM(sip->sip_from),
- SIPTAG_TO(sip->sip_to),
- SIPTAG_CSEQ(sip->sip_cseq),
- TAG_END());
- }
- if (ds->ds_leg || !cr->cr_dialog) {
- msg = msg_copy(cr->cr_msg);
- sip = sip_object(msg);
- }
-
- if (msg && sip) {
- cr->cr_restarting = 1;
- error = nua_client_request_sendmsg(cr, msg, sip);
- cr->cr_restarting = 0;
- if (error !=0 && error != -2)
- msg_destroy(msg);
- }
+ cr->cr_restarting = 1;
+ error = nua_client_request_sendmsg(cr);
+ cr->cr_restarting = 0;
if (error) {
cr->cr_graceful = graceful;
#include <limits.h>
#include <time.h>
+char const *s2_tester = "s2_tester";
+int s2_start_stop;
+
/* -- Module types ------------------------------------------------------ */
struct tp_magic_s
return retval;
}
+int s2_check_substate(struct event *e, enum nua_substate state)
+{
+ int retval = 0;
+ tagi_t const *tagi;
+
+ tagi = tl_find(e->data->e_tags, nutag_substate);
+ if (tagi) {
+ retval = (tag_value_t)state == tagi->t_value;
+ }
+
+ return retval;
+}
+
static void
s2_nua_callback(nua_event_t event,
int status, char const *phrase,
return m != NULL;
}
+void
+s2_save_uas_dialog(struct dialog *d, sip_t *sip)
+{
+ if (d && !d->local) {
+ assert(sip->sip_request);
+ d->local = sip_from_dup(d->home, sip->sip_to);
+ if (d->local->a_tag == NULL)
+ sip_from_tag(d->home, d->local, s2_generate_tag(d->home));
+ d->remote = sip_to_dup(d->home, sip->sip_from);
+ d->call_id = sip_call_id_dup(d->home, sip->sip_call_id);
+ d->rseq = sip->sip_cseq->cs_seq;
+ /* d->route = sip_route_dup(d->home, sip->sip_record_route); */
+ d->target = sip_contact_dup(d->home, sip->sip_contact);
+ }
+}
+
struct message *
s2_respond_to(struct message *m, struct dialog *d,
int status, char const *phrase,
assert(m); assert(m->msg); assert(m->tport);
assert(100 <= status && status < 700);
+ s2_save_uas_dialog(d, m->sip);
+
ta_start(ta, tag, value);
reply = s2_msg(0); sip = sip_object(reply); home = msg_home(reply);
}
}
- if (d && !d->local) {
- d->local = sip_from_dup(d->home, sip->sip_to);
- d->remote = sip_to_dup(d->home, sip->sip_from);
- d->call_id = sip_call_id_dup(d->home, sip->sip_call_id);
- d->rseq = sip->sip_cseq->cs_seq;
- /* d->route = sip_route_dup(d->home, sip->sip_record_route); */
- d->target = sip_contact_dup(d->home, m->sip->sip_contact);
+ if (d && !d->contact) {
d->contact = sip_contact_dup(d->home, sip->sip_contact);
}
char const *description)
{
_s2case = number;
+
+ if (s2_start_stop)
+ printf("%s - starting %s %s\n", s2_tester, number, title);
}
/* ---------------------------------------------------------------------- */
}};
/** Basic setup for test cases */
-void s2_setup_base(char const *hostname)
+void s2_setup_base(char const *label, char const *hostname)
{
assert(s2 == NULL);
+ if (s2_start_stop > 1) {
+ printf("%s - setup %s test case\n", s2_tester, label ? label : "next");
+ }
+
su_init();
s2 = su_home_new(sizeof *s2);
s2->hostname = hostname;
s2->tid = (unsigned long)time(NULL) * 510633671UL;
+
}
SOFIAPUBVAR su_log_t nua_log[];
va_end(va0);
}
+static char const *s2_teardown_label = NULL;
+
+void
+s2_teardown_started(char const *label)
+{
+ if (!s2_teardown_label) {
+ s2_teardown_label = label;
+ if (s2_start_stop > 1) {
+ printf("%s - tearing down %s test case\n", s2_tester, label);
+ }
+ }
+}
+
void
s2_teardown(void)
{
s2 = NULL;
su_deinit();
+
+ if (s2_start_stop > 1) {
+ printf("%s - %s test case tore down\n", s2_tester,
+ s2_teardown_label ? s2_teardown_label : "previous");
+ }
+
+ s2_teardown_label = NULL;
}
/* ====================================================================== */
#include <sofia-sip/sresolv.h>
-nua_t *s2_nua_setup(tag_type_t tag, tag_value_t value, ...)
+nua_t *s2_nua_setup(char const *label,
+ tag_type_t tag, tag_value_t value, ...)
{
ta_list ta;
- s2_setup_base(NULL);
+ s2_setup_base(label, NULL);
s2_setup_dns();
s2_setup_logs(0);
s2->registration->nh = NULL;
}
}
-
msg_t *invite; /* latest invite sent */
};
+extern char const *s2_tester;
+extern int s2_start_stop;
extern struct tester *s2;
extern tp_stack_class_t const s2_stack[1];
struct message *s2_wait_for_request(sip_method_t method, char const *name);
int s2_check_request(sip_method_t method, char const *name);
+int s2_check_substate(struct event *e, enum nua_substate state);
+
#define SIP_METHOD_UNKNOWN sip_method_unknown, NULL
+void s2_save_uas_dialog(struct dialog *d, sip_t *sip);
+
struct message *s2_respond_to(struct message *m, struct dialog *d,
int status, char const *phrase,
tag_type_t tag, tag_value_t value, ...);
void s2_flush_all(void);
-void s2_setup_base(char const *hostname);
+void s2_setup_base(char const *label, char const *hostname);
void s2_setup_logs(int level);
void s2_setup_tport(char const * const *protocols,
tag_type_t tag, tag_value_t value, ...);
void s2_teardown(void);
-nua_t *s2_nua_setup(tag_type_t tag, tag_value_t value, ...);
-void s2_nua_teardown(void);
+nua_t *s2_nua_setup(char const *label, tag_type_t tag, tag_value_t value, ...);
+void s2_teardown_started(char const *label);
+void s2_nua_teardown(void);
void s2_register_setup(void);
void s2_register_teardown(void);