Commit 8b9b4fa4 authored by Ghislain MARY's avatar Ghislain MARY
Browse files

Improve update of the remote target of a dialog + add timer to send 503...

Improve update of the remote target of a dialog + add timer to send 503 response to a dialog for which the dialog was broken if the call does not get repaired.
parent ca6c4f2f
......@@ -651,6 +651,7 @@ struct belle_sip_transaction{
belle_sip_response_t *last_response;
belle_sip_channel_t *channel;
belle_sip_dialog_t *dialog;
belle_sip_source_t *call_repair_timer;
char *branch_id;
belle_sip_transaction_state_t state;
void *appdata;
......
......@@ -409,6 +409,23 @@ static int belle_sip_dialog_should_terminate_by_notify(belle_sip_dialog_t *obj,
return should_terminate;
}
static void belle_sip_dialog_update_remote_target(belle_sip_dialog_t *obj, belle_sip_header_contact_t *ct) {
int remote_target_changed = FALSE;
if (obj->remote_target) {
belle_sip_uri_t *remote_target_uri = belle_sip_header_address_get_uri(obj->remote_target);
belle_sip_uri_t *ct_uri = belle_sip_header_address_get_uri((belle_sip_header_address_t *)ct);
remote_target_changed = !belle_sip_uri_equals(remote_target_uri, ct_uri);
belle_sip_object_unref(obj->remote_target);
}
obj->remote_target=(belle_sip_header_address_t*)belle_sip_object_ref(ct);
if (remote_target_changed) {
belle_sip_message("Dialog [%p]: remote target changed", obj);
if (obj->last_out_ack) {
belle_sip_request_set_uri(BELLE_SIP_REQUEST(obj->last_out_ack), belle_sip_header_address_get_uri(obj->remote_target));
}
}
}
/*
* return 0 if message should be delivered to the next listener, otherwise, its a retransmision, just keep it
* */
......@@ -510,8 +527,7 @@ int belle_sip_dialog_update(belle_sip_dialog_t *obj, belle_sip_transaction_t* tr
ct=belle_sip_message_get_header_by_type(resp,belle_sip_header_contact_t);
}
if (ct){
belle_sip_object_unref(obj->remote_target);
obj->remote_target=(belle_sip_header_address_t*)belle_sip_object_ref(ct);
belle_sip_dialog_update_remote_target(obj, ct);
}
}
......@@ -1085,7 +1101,7 @@ void belle_sip_dialog_queue_client_transaction(belle_sip_dialog_t *dialog, belle
static void _belle_sip_dialog_process_queue(belle_sip_dialog_t* dialog){
belle_sip_client_transaction_t *tr=NULL;
if (dialog->state==BELLE_SIP_DIALOG_TERMINATED || belle_sip_dialog_request_pending(dialog) || dialog->needs_ack) goto end;
if (dialog->state==BELLE_SIP_DIALOG_TERMINATED || belle_sip_dialog_request_pending(dialog)) goto end;
dialog->queued_ct=belle_sip_list_pop_front(dialog->queued_ct,(void**)&tr);
if (tr){
......
......@@ -78,6 +78,7 @@ static belle_sip_request_t *make_ack(belle_sip_ict_t *obj, belle_sip_response_t
return obj->ack;
}
/* Timer D: Wait time for response retransmits */
static int ict_on_timer_D(belle_sip_ict_t *obj){
belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;
if (base->state==BELLE_SIP_TRANSACTION_COMPLETED){
......@@ -86,6 +87,7 @@ static int ict_on_timer_D(belle_sip_ict_t *obj){
return BELLE_SIP_STOP;
}
/* Timer M: Wait time for retransmission of 2xx to INVITE or additional 2xx from other branches of a forked INVITE */
static int ict_on_timer_M(belle_sip_ict_t *obj){
belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;
if (base->state==BELLE_SIP_TRANSACTION_ACCEPTED){
......@@ -134,6 +136,7 @@ static void ict_on_response(belle_sip_ict_t *obj, belle_sip_response_t *resp){
}
}
/* Timer A: INVITE request retransmit interval, for UDP only */
static int ict_on_timer_A(belle_sip_ict_t *obj){
belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;
......@@ -153,6 +156,7 @@ static int ict_on_timer_A(belle_sip_ict_t *obj){
return BELLE_SIP_CONTINUE;
}
/* Timer B: INVITE transaction timeout timer */
static int ict_on_timer_B(belle_sip_ict_t *obj){
belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;
switch (base->state){
......
......@@ -51,6 +51,7 @@ static void ist_destroy(belle_sip_ist_t *obj){
ist_on_terminate(obj);
}
/* Timer G: INVITE response retransmit interval */
static int ist_on_timer_G(belle_sip_ist_t *obj){
belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;
if (base->state==BELLE_SIP_TRANSACTION_COMPLETED){
......@@ -64,21 +65,24 @@ static int ist_on_timer_G(belle_sip_ist_t *obj){
return BELLE_SIP_STOP;
}
/* Timer H: Wait time for ACK receipt */
static int ist_on_timer_H(belle_sip_ist_t *obj){
belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;
if (base->state==BELLE_SIP_TRANSACTION_COMPLETED){
belle_sip_transaction_terminate(base);
/*FIXME: no ACK was received, should report the faillure */
/*FIXME: no ACK was received, should report the failure */
}
return BELLE_SIP_STOP;
}
/* Timer I: Wait time for ACK retransmits */
static int ist_on_timer_I(belle_sip_ist_t *obj){
belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;
belle_sip_transaction_terminate(base);
return BELLE_SIP_STOP;
}
/* Timer L: Wait time for accepted INVITE request retransmits */
static int ist_on_timer_L(belle_sip_ist_t *obj){
belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj;
belle_sip_transaction_terminate(base);
......
......@@ -78,6 +78,11 @@ static void notify_timeout(belle_sip_transaction_t *t){
BELLE_SIP_PROVIDER_INVOKE_LISTENERS_FOR_TRANSACTION(t,process_timeout,&ev);
}
static int server_transaction_on_call_repair_timer(belle_sip_transaction_t *t) {
belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(t), belle_sip_response_create_from_request(t->request, 503));
return BELLE_SIP_STOP;
}
static void on_channel_state_changed(belle_sip_channel_listener_t *l, belle_sip_channel_t *chan, belle_sip_channel_state_t state){
belle_sip_transaction_t *t=(belle_sip_transaction_t*)l;
belle_sip_io_error_event_t ev;
......@@ -109,8 +114,18 @@ static void on_channel_state_changed(belle_sip_channel_listener_t *l, belle_sip_
if (t->timed_out)
notify_timeout((belle_sip_transaction_t*)t);
belle_sip_transaction_terminate(t);
belle_sip_object_unref(t);
if (t->dialog && (belle_sip_dialog_get_state(t->dialog) == BELLE_SIP_DIALOG_EARLY)) {
if (!t->timed_out && BELLE_SIP_OBJECT_IS_INSTANCE_OF(t, belle_sip_server_transaction_t)) {
const belle_sip_timer_config_t *cfg = belle_sip_transaction_get_timer_config(t);
t->call_repair_timer = belle_sip_timeout_source_new((belle_sip_source_func_t)server_transaction_on_call_repair_timer, t, 32 * cfg->T1);
belle_sip_transaction_start_timer(t, t->call_repair_timer);
}
} else {
belle_sip_transaction_terminate(t);
belle_sip_object_unref(t);
}
belle_sip_object_unref(((belle_sip_transaction_t*)t)->channel);
((belle_sip_transaction_t*)t)->channel = NULL;
break;
default:
/*ignored*/
......@@ -188,6 +203,11 @@ void belle_sip_transaction_terminate(belle_sip_transaction_t *t){
BELLE_SIP_OBJECT_VPTR(t,belle_sip_transaction_t)->on_terminate(t);
belle_sip_provider_set_transaction_terminated(t->provider,t);
}
if (t->call_repair_timer) {
belle_sip_transaction_stop_timer(t, t->call_repair_timer);
belle_sip_object_unref(t->call_repair_timer);
t->call_repair_timer = NULL;
}
}
belle_sip_request_t *belle_sip_transaction_get_request(const belle_sip_transaction_t *t){
......@@ -272,7 +292,7 @@ void belle_sip_server_transaction_send_response(belle_sip_server_transaction_t *
int status_code;
belle_sip_object_ref(resp);
if (!base->last_response){
if (!base->last_response || !base->channel){
belle_sip_hop_t* hop=belle_sip_response_get_return_hop(resp);
base->channel=belle_sip_provider_get_channel(base->provider,hop);
belle_sip_object_unref(hop);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment