Commit 5874da79 authored by Simon Morlat's avatar Simon Morlat

client transaction in progress

parent 4735a3d6
......@@ -56,7 +56,7 @@ struct belle_sip_response_event{
belle_sip_provider_t *source;
belle_sip_client_transaction_t *client_transaction;
belle_sip_dialog_t *dialog;
belle_sip_request_t *response;
belle_sip_response_t *response;
};
struct belle_sip_timeout_event{
......
......@@ -42,7 +42,7 @@ belle_sip_request_t* belle_sip_request_parse(const char* raw);
belle_sip_uri_t* belle_sip_request_get_uri(belle_sip_request_t* request);
void belle_sip_request_set_uri(belle_sip_request_t* request,belle_sip_uri_t* uri);
const char* belle_sip_request_get_method(belle_sip_request_t* request);
const char* belle_sip_request_get_method(const belle_sip_request_t* request);
void belle_sip_request_set_method(belle_sip_request_t* request,const char* method);
int belle_sip_message_is_response(belle_sip_message_t *msg);
......
......@@ -74,7 +74,8 @@ struct belle_sip_source{
int index; /* index in pollfd table */
belle_sip_source_func_t notify;
belle_sip_source_remove_callback_t on_remove;
int cancelled;
int cancelled:1;
int expired:1;
};
void belle_sip_fd_source_init(belle_sip_source_t *s, belle_sip_source_func_t func, void *data, int fd, unsigned int events, unsigned int timeout_value_ms);
......
......@@ -119,6 +119,9 @@ unsigned long belle_sip_main_loop_add_timeout(belle_sip_main_loop_t *ml, belle_s
}
void belle_sip_source_set_timeout(belle_sip_source_t *s, unsigned int value_ms){
if (!s->expired){
s->expire_ms=belle_sip_time_ms()+value_ms;
}
s->timeout=value_ms;
}
......@@ -222,6 +225,7 @@ void belle_sip_main_loop_iterate(belle_sip_main_loop_t *ml){
}
}
if (revents!=0 || (s->timeout>0 && cur>=s->expire_ms)){
s->expired=TRUE;
ret=s->notify(s->data,revents);
if (ret==0){
/*this source needs to be removed*/
......@@ -229,6 +233,7 @@ void belle_sip_main_loop_iterate(belle_sip_main_loop_t *ml){
}else if (revents==0){
/*timeout needs to be started again */
s->expire_ms+=s->timeout;
s->expired=FALSE;
}
}
}else belle_sip_main_loop_remove_source(ml,s);
......
......@@ -82,9 +82,15 @@ belle_sip_uri_t * belle_sip_request_get_uri(belle_sip_request_t *request){
return NULL;
}
const char * belle_sip_request_get_method(const belle_sip_request_t *req){
return NULL;
}
void belle_sip_request_set_method(belle_sip_request_t* request,const char* method) {
}
int belle_sip_message_is_request(belle_sip_message_t *msg){
return 0;
}
......
......@@ -29,7 +29,9 @@ struct belle_sip_transaction{
belle_sip_transaction_state_t state;
belle_sip_sender_task_t *stask;
uint64_t start_time;
int is_reliable;
int is_reliable:1;
int is_server:1;
int is_invite:1;
void *appdata;
};
......@@ -79,7 +81,11 @@ belle_sip_transaction_state_t belle_sip_transaction_get_state(const belle_sip_tr
}
void belle_sip_transaction_terminate(belle_sip_transaction_t *t){
belle_sip_transaction_terminated_event_t ev;
ev.source=t->provider;
ev.transaction=(belle_sip_transaction_t*)t;
ev.is_server_transaction=t->is_server;
BELLE_SIP_PROVIDER_INVOKE_LISTENERS(t->provider,process_transaction_terminated,&ev);
}
belle_sip_request_t *belle_sip_transaction_get_request(belle_sip_transaction_t *t){
......@@ -127,14 +133,39 @@ belle_sip_request_t * belle_sip_client_transaction_create_cancel(belle_sip_clien
static int on_client_transaction_timer(void *data, unsigned int revents){
belle_sip_client_transaction_t *t=(belle_sip_client_transaction_t*)data;
const belle_sip_timer_config_t *tc=belle_sip_stack_get_timer_config (belle_sip_provider_get_sip_stack (t->base.provider));
if (t->base.state==BELLE_SIP_TRANSACTION_TRYING){
belle_sip_sender_task_send(t->base.stask);
t->interval=MIN(t->interval*2,tc->T2);
belle_sip_source_set_timeout(t->timer,t->interval);
switch(t->base.state){
case BELLE_SIP_TRANSACTION_TRYING: /*NON INVITE*/
belle_sip_sender_task_send(t->base.stask);
t->interval=MIN(t->interval*2,tc->T2);
belle_sip_source_set_timeout(t->timer,t->interval);
break;
case BELLE_SIP_TRANSACTION_CALLING: /*INVITES*/
belle_sip_sender_task_send(t->base.stask);
t->interval=t->interval*2;
belle_sip_source_set_timeout(t->timer,t->interval);
break;
case BELLE_SIP_TRANSACTION_PROCEEDING:
if (!t->base.is_invite){
belle_sip_sender_task_send(t->base.stask);
t->interval=tc->T2;
belle_sip_source_set_timeout(t->timer,t->interval);
}
break;
case BELLE_SIP_TRANSACTION_COMPLETED:
belle_sip_transaction_terminate((belle_sip_transaction_t*)t);
return BELLE_SIP_STOP;
break;
default:
belle_sip_error("Unexpected transaction state %i while in timer callback",t->base.state);
}
if (belle_sip_time_ms()>=t->timer_F){
/*report the timeout */
belle_sip_timeout_event_t ev;
ev.source=t->base.provider;
ev.transaction=&t->base;
ev.is_server_transaction=FALSE;
BELLE_SIP_PROVIDER_INVOKE_LISTENERS(t->base.provider,process_timeout,&ev);
belle_sip_transaction_terminate((belle_sip_transaction_t*)t);
return BELLE_SIP_STOP;
}
......@@ -146,7 +177,11 @@ static void client_transaction_cb(belle_sip_sender_task_t *task, void *data, int
const belle_sip_timer_config_t *tc=belle_sip_stack_get_timer_config (belle_sip_provider_get_sip_stack (t->base.provider));
if (retcode==0){
t->base.is_reliable=belle_sip_sender_task_is_reliable(task);
t->base.state=BELLE_SIP_TRANSACTION_TRYING;
if (t->base.is_invite){
t->base.state=BELLE_SIP_TRANSACTION_CALLING;
}else{
t->base.state=BELLE_SIP_TRANSACTION_TRYING;
}
t->base.start_time=belle_sip_time_ms();
t->timer_F=t->base.start_time+(tc->T1*64);
if (!t->base.is_reliable){
......@@ -156,11 +191,8 @@ static void client_transaction_cb(belle_sip_sender_task_t *task, void *data, int
t->timer=transaction_create_timer(&t->base,on_client_transaction_timer,tc->T1*64);
}
}else{
belle_sip_transaction_terminated_event_t ev;
ev.source=t->base.provider;
ev.transaction=(belle_sip_transaction_t*)t;
ev.is_server_transaction=FALSE;
BELLE_SIP_PROVIDER_INVOKE_LISTENERS(t->base.provider,process_transaction_terminated,&ev);
/* transport layer error*/
belle_sip_transaction_terminate(&t->base);
}
}
......@@ -170,12 +202,73 @@ void belle_sip_client_transaction_send_request(belle_sip_client_transaction_t *t
belle_sip_sender_task_send(t->base.stask);
}
/*called by the transport layer when a response is received */
void belle_sip_client_transaction_add_response(belle_sip_client_transaction_t *t, belle_sip_response_t *resp){
static void notify_response(belle_sip_client_transaction_t *t, belle_sip_response_t *resp){
belle_sip_provider_t *prov=t->base.provider;
belle_sip_response_event_t ev;
ev.source=prov;
ev.client_transaction=t;
ev.dialog=NULL; /*TODO: FIND IT */
ev.response=resp;
BELLE_SIP_PROVIDER_INVOKE_LISTENERS(prov,process_response_event,&ev);
}
static void handle_invite_response(belle_sip_client_transaction_t *t, belle_sip_response_t *resp){
int code=belle_sip_response_get_status_code(resp);
if (code>=100 && code<200){
switch(t->base.state){
case BELLE_SIP_TRANSACTION_CALLING:
if (!t->base.is_reliable){
/* we must stop retransmissions, then program the timer B/F only*/
belle_sip_source_set_timeout(t->timer,t->timer_F-belle_sip_time_ms());
}
t->base.state=BELLE_SIP_TRANSACTION_PROCEEDING;
case BELLE_SIP_TRANSACTION_PROCEEDING:
if (t->base.prov_response!=NULL){
belle_sip_object_unref(t->base.prov_response);
}
t->base.prov_response=(belle_sip_response_t*)belle_sip_object_ref(resp);
notify_response(t,resp);
break;
default:
belle_sip_warning("Unexpected provisional response while transaction in state %i",t->base.state);
}
}else if (code>=300){
switch(t->base.state){
case BELLE_SIP_TRANSACTION_CALLING:
case BELLE_SIP_TRANSACTION_PROCEEDING:
t->base.state=BELLE_SIP_TRANSACTION_COMPLETED;
t->base.final_response=(belle_sip_response_t*)belle_sip_object_ref(resp);
notify_response(t,resp);
/*start timer D */
belle_sip_source_set_timeout(t->timer,32000);
break;
default:
belle_sip_warning("Unexpected final response while transaction in state %i",t->base.state);
}
}else if (code>=200){
switch(t->base.state){
case BELLE_SIP_TRANSACTION_CALLING:
case BELLE_SIP_TRANSACTION_PROCEEDING:
belle_sip_transaction_terminate(&t->base);
break;
default:
belle_sip_warning("Unexpected final response while transaction in state %i",t->base.state);
}
}
}
static void handle_non_invite_response(belle_sip_client_transaction_t *t, belle_sip_response_t *resp){
int code=belle_sip_response_get_status_code(resp);
const belle_sip_timer_config_t *tc=belle_sip_stack_get_timer_config (belle_sip_provider_get_sip_stack (t->base.provider));
if (code>=100 && code<200){
switch(t->base.state){
case BELLE_SIP_TRANSACTION_CALLING:
if (!t->base.is_reliable){
/* we must stop retransmissions, then program the timer B/F only*/
belle_sip_source_set_timeout(t->timer,t->timer_F-belle_sip_time_ms());
}
case BELLE_SIP_TRANSACTION_TRYING:
case BELLE_SIP_TRANSACTION_PROCEEDING:
t->base.state=BELLE_SIP_TRANSACTION_PROCEEDING;
......@@ -183,6 +276,7 @@ void belle_sip_client_transaction_add_response(belle_sip_client_transaction_t *t
belle_sip_object_unref(t->base.prov_response);
}
t->base.prov_response=(belle_sip_response_t*)belle_sip_object_ref(resp);
notify_response(t,resp);
break;
default:
belle_sip_warning("Unexpected provisional response while transaction in state %i",t->base.state);
......@@ -193,6 +287,8 @@ void belle_sip_client_transaction_add_response(belle_sip_client_transaction_t *t
case BELLE_SIP_TRANSACTION_PROCEEDING:
t->base.state=BELLE_SIP_TRANSACTION_COMPLETED;
t->base.final_response=(belle_sip_response_t*)belle_sip_object_ref(resp);
notify_response(t,resp);
belle_sip_source_set_timeout(t->timer,tc->T4);
break;
default:
belle_sip_warning("Unexpected final response while transaction in state %i",t->base.state);
......@@ -200,6 +296,12 @@ void belle_sip_client_transaction_add_response(belle_sip_client_transaction_t *t
}
}
/*called by the transport layer when a response is received */
void belle_sip_client_transaction_add_response(belle_sip_client_transaction_t *t, belle_sip_response_t *resp){
if (t->base.is_invite) handle_invite_response (t,resp);
else handle_non_invite_response(t, resp);
}
static void client_transaction_destroy(belle_sip_client_transaction_t *t ){
transaction_destroy((belle_sip_transaction_t*)t);
}
......@@ -208,6 +310,8 @@ static void client_transaction_destroy(belle_sip_client_transaction_t *t ){
belle_sip_client_transaction_t * belle_sip_client_transaction_new(belle_sip_provider_t *prov, belle_sip_request_t *req){
belle_sip_client_transaction_t *t=belle_sip_object_new(belle_sip_client_transaction_t,(belle_sip_object_destroy_t)client_transaction_destroy);
belle_sip_transaction_init((belle_sip_transaction_t*)t,prov,req);
if (strcmp(belle_sip_request_get_method(req),"INVITE")==0)
t->base.is_invite=TRUE;
return t;
}
......
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