Commit 0285a4fb authored by Ghislain MARY's avatar Ghislain MARY

Merge branch 'dev_rat'

parents d0b541a4 c74b3796
......@@ -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;
......@@ -843,6 +844,8 @@ int belle_sip_dialog_update(belle_sip_dialog_t *obj,belle_sip_transaction_t* tra
void belle_sip_dialog_check_ack_sent(belle_sip_dialog_t*obj);
int belle_sip_dialog_handle_ack(belle_sip_dialog_t *obj, belle_sip_request_t *ack);
void belle_sip_dialog_queue_client_transaction(belle_sip_dialog_t *dialog, belle_sip_client_transaction_t *tr);
void belle_sip_dialog_stop_200Ok_retrans(belle_sip_dialog_t *obj);
/*
belle_sip_response_t
......
......@@ -19,7 +19,6 @@
#include "belle_sip_internal.h"
static void belle_sip_dialog_init_200Ok_retrans(belle_sip_dialog_t *obj, belle_sip_response_t *resp);
static void belle_sip_dialog_stop_200Ok_retrans(belle_sip_dialog_t *obj);
static int belle_sip_dialog_handle_200Ok(belle_sip_dialog_t *obj, belle_sip_response_t *msg);
static void belle_sip_dialog_process_queue(belle_sip_dialog_t* dialog);
static belle_sip_request_t *create_request(belle_sip_dialog_t *obj, const char *method, int full);
......@@ -368,7 +367,7 @@ static void belle_sip_dialog_init_200Ok_retrans(belle_sip_dialog_t *obj, belle_s
obj->last_200Ok=(belle_sip_response_t*)belle_sip_object_ref(resp);
}
static void belle_sip_dialog_stop_200Ok_retrans(belle_sip_dialog_t *obj){
void belle_sip_dialog_stop_200Ok_retrans(belle_sip_dialog_t *obj){
belle_sip_main_loop_t *ml=obj->provider->stack->ml;
if (obj->timer_200Ok){
belle_sip_main_loop_remove_source(ml,obj->timer_200Ok);
......@@ -413,6 +412,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
* */
......@@ -514,8 +530,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 +1100,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);
......
......@@ -132,6 +132,13 @@ static void belle_sip_provider_dispatch_request(belle_sip_provider_t* prov, bell
/* Should we limit to ACK ? */
/*Search for a dialog if exist */
if (strcmp("CANCEL",method) == 0) {
/* Call leg does not exist */
belle_sip_server_transaction_t *tr = belle_sip_provider_create_server_transaction(prov, req);
belle_sip_server_transaction_send_response(tr, belle_sip_response_create_from_request(req, 481));
return;
}
ev.dialog=belle_sip_provider_find_dialog_from_message(prov,(belle_sip_message_t*)req,1/*request=uas*/);
if (ev.dialog){
if (strcmp("ACK",method)==0){
......@@ -139,6 +146,8 @@ static void belle_sip_provider_dispatch_request(belle_sip_provider_t* prov, bell
/*absorbed ACK retransmission, ignore */
return;
}
}else if ((strcmp("INVITE",method)==0)&&(ev.dialog->needs_ack)){
belle_sip_dialog_stop_200Ok_retrans(ev.dialog);
}else if (!belle_sip_dialog_is_authorized_transaction(ev.dialog,method)){
belle_sip_server_transaction_t *tr=belle_sip_provider_create_server_transaction(prov,req);
belle_sip_server_transaction_send_response(tr,
......
......@@ -61,6 +61,11 @@ static void belle_sip_transaction_init(belle_sip_transaction_t *t, belle_sip_pro
}
static void transaction_destroy(belle_sip_transaction_t *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;
}
if (t->request) belle_sip_object_unref(t->request);
if (t->last_response) belle_sip_object_unref(t->last_response);
if (t->channel) belle_sip_object_unref(t->channel);
......@@ -78,9 +83,21 @@ 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 int client_transaction_on_call_repair_timer(belle_sip_transaction_t *t) {
belle_sip_transaction_terminate(t);
belle_sip_object_unref(t);
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;
const belle_sip_timer_config_t *timercfg;
belle_sip_transaction_state_t tr_state=belle_sip_transaction_get_state((belle_sip_transaction_t*)t);
belle_sip_message("transaction [%p] channel state changed to [%s]"
......@@ -106,11 +123,30 @@ static void on_channel_state_changed(belle_sip_channel_listener_t *l, belle_sip_
&& tr_state!=BELLE_SIP_TRANSACTION_TERMINATED) {
BELLE_SIP_PROVIDER_INVOKE_LISTENERS_FOR_TRANSACTION(((belle_sip_transaction_t*)t),process_io_error,&ev);
}
if (t->timed_out)
if (t->timed_out) {
notify_timeout((belle_sip_transaction_t*)t);
} else {
if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(t, belle_sip_ist_t) || BELLE_SIP_OBJECT_IS_INSTANCE_OF(t, belle_sip_ict_t)) {
timercfg = belle_sip_transaction_get_timer_config(t);
if (t->call_repair_timer) {
belle_sip_transaction_stop_timer(t, t->call_repair_timer);
belle_sip_object_unref(t->call_repair_timer);
}
}
}
belle_sip_transaction_terminate(t);
if (!t->timed_out && BELLE_SIP_OBJECT_IS_INSTANCE_OF(t, belle_sip_ist_t)) {
t->call_repair_timer = belle_sip_timeout_source_new((belle_sip_source_func_t)server_transaction_on_call_repair_timer, t, 32 * timercfg->T1);
belle_sip_transaction_start_timer(t, t->call_repair_timer);
} else if (!t->timed_out && BELLE_SIP_OBJECT_IS_INSTANCE_OF(t, belle_sip_ict_t)) {
t->call_repair_timer = belle_sip_timeout_source_new((belle_sip_source_func_t)client_transaction_on_call_repair_timer, t, 32 * timercfg->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 +224,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 +313,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);
......@@ -353,8 +394,8 @@ belle_sip_request_t * belle_sip_client_transaction_create_cancel(belle_sip_clien
belle_sip_error("belle_sip_client_transaction_create_cancel() cannot be used for ACK or non-INVITE transactions.");
return NULL;
}
if (t->base.state!=BELLE_SIP_TRANSACTION_PROCEEDING){
belle_sip_error("belle_sip_client_transaction_create_cancel() can only be used in state BELLE_SIP_TRANSACTION_PROCEEDING"
if ((t->base.state != BELLE_SIP_TRANSACTION_PROCEEDING) && (t->base.state != BELLE_SIP_TRANSACTION_CALLING)) {
belle_sip_error("belle_sip_client_transaction_create_cancel() can only be used in state PROCEEDING or CALLING"
" but current transaction state is %s",belle_sip_transaction_state_to_string(t->base.state));
return NULL;
}
......
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