Commit 50052922 authored by Simon Morlat's avatar Simon Morlat

rework sender_task, finalize client transaction

parent 5874da79
......@@ -42,7 +42,7 @@ 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_request_t *belle_sip_transaction_get_request(belle_sip_transaction_t *t);
void belle_sip_server_transaction_send_response(belle_sip_server_transaction_t *t);
void belle_sip_server_transaction_send_response(belle_sip_server_transaction_t *t, belle_sip_response_t *resp);
belle_sip_request_t * belle_sip_client_transaction_create_cancel(belle_sip_client_transaction_t *t);
void belle_sip_client_transaction_send_request(belle_sip_client_transaction_t *t);
......
......@@ -82,6 +82,8 @@ void belle_sip_fd_source_init(belle_sip_source_t *s, belle_sip_source_func_t fun
#define belle_list_next(elem) ((elem)->next)
/* include private headers */
#include "sender_task.h"
#ifdef __cplusplus
extern "C"{
......@@ -406,6 +408,7 @@ struct belle_sip_provider{
};
belle_sip_provider_t *belle_sip_provider_new(belle_sip_stack_t *s, belle_sip_listening_point_t *lp);
void belle_sip_provider_set_transaction_terminated(belle_sip_provider_t *p, belle_sip_transaction_t *t);
typedef struct listener_ctx{
belle_sip_listener_t *listener;
......@@ -425,6 +428,25 @@ typedef struct listener_ctx{
belle_sip_transaction_t
*/
struct belle_sip_transaction{
belle_sip_object_t base;
belle_sip_provider_t *provider; /*the provider that created this transaction */
belle_sip_request_t *request;
belle_sip_response_t *prov_response;
belle_sip_response_t *final_response;
char *branch_id;
belle_sip_transaction_state_t state;
belle_sip_sender_task_t *stask;
uint64_t start_time;
belle_sip_source_t *timer;
int interval;
int is_reliable:1;
int is_server:1;
int is_invite:1;
void *appdata;
};
belle_sip_client_transaction_t * belle_sip_client_transaction_new(belle_sip_provider_t *prov,belle_sip_request_t *req);
belle_sip_server_transaction_t * belle_sip_server_transaction_new(belle_sip_provider_t *prov,belle_sip_request_t *req);
void belle_sip_client_transaction_add_response(belle_sip_client_transaction_t *t, belle_sip_response_t *resp);
......
......@@ -92,14 +92,24 @@ static void sender_task_cb(belle_sip_sender_task_t *t, void *data, int retcode){
void belle_sip_provider_send_request(belle_sip_provider_t *p, belle_sip_request_t *req){
belle_sip_sender_task_t *task;
task=belle_sip_sender_task_new(p, BELLE_SIP_MESSAGE(req), sender_task_cb, NULL);
belle_sip_sender_task_send(task);
task=belle_sip_sender_task_new(p, sender_task_cb, NULL);
belle_sip_sender_task_send(task,BELLE_SIP_MESSAGE(req));
}
void belle_sip_provider_send_response(belle_sip_provider_t *p, belle_sip_response_t *resp){
belle_sip_sender_task_t *task;
task=belle_sip_sender_task_new(p, BELLE_SIP_MESSAGE(resp), sender_task_cb, NULL);
belle_sip_sender_task_send(task);
task=belle_sip_sender_task_new(p, sender_task_cb, NULL);
belle_sip_sender_task_send(task,BELLE_SIP_MESSAGE(resp));
}
/*private provider API*/
void belle_sip_provider_set_transaction_terminated(belle_sip_provider_t *p, belle_sip_transaction_t *t){
belle_sip_transaction_terminated_event_t ev;
ev.source=p;
ev.transaction=t;
ev.is_server_transaction=t->is_server;
BELLE_SIP_PROVIDER_INVOKE_LISTENERS(p,process_transaction_terminated,&ev);
}
......@@ -29,10 +29,10 @@ static void belle_sip_sender_task_uninit(belle_sip_sender_task_t *t){
if (t->resolver_id>0) belle_sip_main_loop_cancel_source (stack->ml,t->resolver_id);
}
belle_sip_sender_task_t * belle_sip_sender_task_new(belle_sip_provider_t *provider, belle_sip_message_t *msg, belle_sip_sender_task_callback_t cb, void *data){
belle_sip_sender_task_t * belle_sip_sender_task_new(belle_sip_provider_t *provider, belle_sip_sender_task_callback_t cb, void *data){
belle_sip_sender_task_t *t=belle_sip_object_new(belle_sip_sender_task_t,belle_sip_sender_task_uninit);
t->provider=provider;
t->message=(belle_sip_message_t*)belle_sip_object_ref(msg);
t->message=NULL;
t->cb=cb;
t->cb_data=data;
return t;
......@@ -60,6 +60,8 @@ static int retry_send(belle_sip_sender_task_t *t, unsigned int revents){
static void sender_task_send(belle_sip_sender_task_t *t){
int err;
if (t->buf==NULL)
t->buf=belle_sip_message_to_string(t->message);
err=do_send(t);
if (err==-EWOULDBLOCK){
belle_sip_stack_t *stack=belle_sip_provider_get_sip_stack(t->provider);
......@@ -81,7 +83,7 @@ static void sender_task_find_channel_and_send(belle_sip_sender_task_t *t){
belle_sip_channel_t *chan=belle_sip_listening_point_find_output_channel (lp,t->dest);
if (chan==NULL) goto error;
t->channel=(belle_sip_channel_t*)belle_sip_object_ref(chan);
t->buf=belle_sip_message_to_string(t->message);
sender_task_send(t);
}
return;
......@@ -106,12 +108,22 @@ static void sender_task_res_done(void *data, const char *name, struct addrinfo *
}
}
void belle_sip_sender_task_send(belle_sip_sender_task_t *t){
void belle_sip_sender_task_send(belle_sip_sender_task_t *t, belle_sip_message_t *msg){
belle_sip_stack_t *stack=belle_sip_provider_get_sip_stack(t->provider);
if (t->buf!=NULL){
/*retransmission, everything already done*/
if (t->message!=NULL && t->message!=msg && msg!=NULL){
belle_sip_object_unref(t->message);
t->message=NULL;
belle_sip_free(t->buf);
t->buf=NULL;
}
if (t->message==NULL){
t->message=(belle_sip_message_t*)belle_sip_object_ref(msg);
}
if (t->channel){
/*retransmission or new response to be sent, everything already done for setting up the transport*/
sender_task_send(t);
return;
}
if (belle_sip_message_is_request(t->message)){
belle_sip_stack_get_next_hop(stack,BELLE_SIP_REQUEST(t->message),&t->hop);
......
......@@ -41,9 +41,9 @@ typedef struct belle_sip_sender_task belle_sip_sender_task_t;
belle_sip_sender_task_t * belle_sip_sender_task_new(belle_sip_provider_t *provider, belle_sip_message_t *msg, belle_sip_sender_task_callback_t cb, void *data);
belle_sip_sender_task_t * belle_sip_sender_task_new(belle_sip_provider_t *provider, belle_sip_sender_task_callback_t cb, void *data);
void belle_sip_sender_task_send(belle_sip_sender_task_t *task);
void belle_sip_sender_task_send(belle_sip_sender_task_t *task, belle_sip_message_t *msg);
/*you can only call that after send has been called once */
int belle_sip_sender_task_is_reliable(belle_sip_sender_task_t *task);
......
......@@ -19,21 +19,6 @@
#include "belle_sip_internal.h"
#include "sender_task.h"
struct belle_sip_transaction{
belle_sip_object_t base;
belle_sip_provider_t *provider; /*the provider that created this transaction */
belle_sip_request_t *request;
belle_sip_response_t *prov_response;
belle_sip_response_t *final_response;
char *branch_id;
belle_sip_transaction_state_t state;
belle_sip_sender_task_t *stask;
uint64_t start_time;
int is_reliable:1;
int is_server:1;
int is_invite:1;
void *appdata;
};
static belle_sip_source_t * transaction_create_timer(belle_sip_transaction_t *t, belle_sip_source_func_t func, unsigned int time_ms){
......@@ -43,12 +28,13 @@ static belle_sip_source_t * transaction_create_timer(belle_sip_transaction_t *t,
return s;
}
/*
static void transaction_remove_timeout(belle_sip_transaction_t *t, unsigned long id){
static void transaction_delete_timer(belle_sip_transaction_t *t, belle_sip_source_t *s){
belle_sip_stack_t *stack=belle_sip_provider_get_sip_stack(t->provider);
belle_sip_main_loop_cancel_source (stack->ml,id);
belle_sip_main_loop_cancel_source (stack->ml,s->id);
belle_sip_object_unref(s);
}
*/
static void belle_sip_transaction_init(belle_sip_transaction_t *t, belle_sip_provider_t *prov, belle_sip_request_t *req){
belle_sip_object_init_type(t,belle_sip_transaction_t);
......@@ -81,11 +67,12 @@ 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);
t->state=BELLE_SIP_TRANSACTION_TERMINATED;
if (t->timer){
transaction_delete_timer(t,t->timer);
t->timer=NULL;
}
belle_sip_provider_set_transaction_terminated(t->provider,t);
}
belle_sip_request_t *belle_sip_transaction_get_request(belle_sip_transaction_t *t){
......@@ -93,14 +80,31 @@ belle_sip_request_t *belle_sip_transaction_get_request(belle_sip_transaction_t *
}
/*
Server transaction
*
*
* Server transaction
*
*
*/
struct belle_sip_server_transaction{
belle_sip_transaction_t base;
};
void belle_sip_server_transaction_send_response(belle_sip_server_transaction_t *t){
static void server_transaction_send_cb(belle_sip_sender_task_t *st, void *data, int retcode){
belle_sip_server_transaction_t *t=(belle_sip_server_transaction_t *)data;
if (retcode==0){
}else{
/*the provider is notified of the error by the sender_task, we just need to terminate the transaction*/
belle_sip_transaction_terminate(&t->base);
}
}
void belle_sip_server_transaction_send_response(belle_sip_server_transaction_t *t, belle_sip_response_t *resp){
if (t->base.stask==NULL){
t->base.stask=belle_sip_sender_task_new(t->base.provider,server_transaction_send_cb,t);
}
belle_sip_sender_task_send(t->base.stask,BELLE_SIP_MESSAGE(resp));
}
static void server_transaction_destroy(belle_sip_server_transaction_t *t){
......@@ -114,13 +118,15 @@ belle_sip_server_transaction_t * belle_sip_server_transaction_new(belle_sip_prov
}
/*
Client transaction
*
*
* Client transaction
*
*
*/
struct belle_sip_client_transaction{
belle_sip_transaction_t base;
belle_sip_source_t *timer;
int interval;
uint64_t timer_F;
uint64_t timer_E;
uint64_t timer_K;
......@@ -136,20 +142,20 @@ static int on_client_transaction_timer(void *data, unsigned int revents){
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);
belle_sip_sender_task_send(t->base.stask,NULL);
t->base.interval=MIN(t->base.interval*2,tc->T2);
belle_sip_source_set_timeout(t->base.timer,t->base.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);
belle_sip_sender_task_send(t->base.stask,NULL);
t->base.interval=t->base.interval*2;
belle_sip_source_set_timeout(t->base.timer,t->base.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);
belle_sip_sender_task_send(t->base.stask,NULL);
t->base.interval=tc->T2;
belle_sip_source_set_timeout(t->base.timer,t->base.interval);
}
break;
case BELLE_SIP_TRANSACTION_COMPLETED:
......@@ -185,10 +191,10 @@ static void client_transaction_cb(belle_sip_sender_task_t *task, void *data, int
t->base.start_time=belle_sip_time_ms();
t->timer_F=t->base.start_time+(tc->T1*64);
if (!t->base.is_reliable){
t->interval=tc->T1;
t->timer=transaction_create_timer(&t->base,on_client_transaction_timer,tc->T1);
t->base.interval=tc->T1;
t->base.timer=transaction_create_timer(&t->base,on_client_transaction_timer,tc->T1);
}else{
t->timer=transaction_create_timer(&t->base,on_client_transaction_timer,tc->T1*64);
t->base.timer=transaction_create_timer(&t->base,on_client_transaction_timer,tc->T1*64);
}
}else{
/* transport layer error*/
......@@ -198,8 +204,8 @@ static void client_transaction_cb(belle_sip_sender_task_t *task, void *data, int
void belle_sip_client_transaction_send_request(belle_sip_client_transaction_t *t){
t->base.stask=belle_sip_sender_task_new(t->base.provider,BELLE_SIP_MESSAGE(t->base.request),client_transaction_cb,t);
belle_sip_sender_task_send(t->base.stask);
t->base.stask=belle_sip_sender_task_new(t->base.provider,client_transaction_cb,t);
belle_sip_sender_task_send(t->base.stask,BELLE_SIP_MESSAGE(t->base.request));
}
static void notify_response(belle_sip_client_transaction_t *t, belle_sip_response_t *resp){
......@@ -220,7 +226,7 @@ static void handle_invite_response(belle_sip_client_transaction_t *t, belle_sip_
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());
belle_sip_source_set_timeout(t->base.timer,t->timer_F-belle_sip_time_ms());
}
t->base.state=BELLE_SIP_TRANSACTION_PROCEEDING;
case BELLE_SIP_TRANSACTION_PROCEEDING:
......@@ -241,7 +247,7 @@ static void handle_invite_response(belle_sip_client_transaction_t *t, belle_sip_
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);
belle_sip_source_set_timeout(t->base.timer,32000);
break;
default:
belle_sip_warning("Unexpected final response while transaction in state %i",t->base.state);
......@@ -250,6 +256,7 @@ static void handle_invite_response(belle_sip_client_transaction_t *t, belle_sip_
switch(t->base.state){
case BELLE_SIP_TRANSACTION_CALLING:
case BELLE_SIP_TRANSACTION_PROCEEDING:
notify_response(t,resp);
belle_sip_transaction_terminate(&t->base);
break;
default:
......@@ -267,7 +274,7 @@ static void handle_non_invite_response(belle_sip_client_transaction_t *t, belle_
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());
belle_sip_source_set_timeout(t->base.timer,t->timer_F-belle_sip_time_ms());
}
case BELLE_SIP_TRANSACTION_TRYING:
case BELLE_SIP_TRANSACTION_PROCEEDING:
......@@ -288,7 +295,7 @@ static void handle_non_invite_response(belle_sip_client_transaction_t *t, belle_
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);
belle_sip_source_set_timeout(t->base.timer,tc->T4);
break;
default:
belle_sip_warning("Unexpected final response while transaction in state %i",t->base.state);
......
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