Commit 4735a3d6 authored by Simon Morlat's avatar Simon Morlat

transactions in progress

parent e115c36b
......@@ -68,6 +68,7 @@ unsigned long belle_sip_main_loop_add_timeout(belle_sip_main_loop_t *ml, belle_s
**/
belle_sip_source_t * belle_sip_timeout_source_new(belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms);
void belle_sip_source_set_timeout(belle_sip_source_t *s, unsigned int value_ms);
belle_sip_source_t * belle_sip_fd_source_new(belle_sip_source_func_t func, void *data, int fd, unsigned int events, unsigned int timeout_value_ms);
......
......@@ -58,6 +58,8 @@ void belle_sip_message_add_header(belle_sip_message_t *msg, belle_sip_header_t*
char *belle_sip_message_to_string(belle_sip_message_t *msg);
int belle_sip_response_get_status_code(const belle_sip_response_t *response);
BELLE_SIP_END_DECLS
#endif
......
......@@ -356,6 +356,17 @@ struct _belle_sip_parameters {
void belle_sip_parameters_init(belle_sip_parameters_t *obj);
void belle_sip_parameters_destroy(belle_sip_parameters_t* params);
/*
* Listening points and channels
*/
struct belle_sip_channel{
belle_sip_object_t base;
belle_sip_listening_point_t *lp; /* the listening point this channel belongs */
struct addrinfo peer;
struct sockaddr_storage peer_addr;
};
typedef struct belle_sip_udp_listening_point belle_sip_udp_listening_point_t;
#define BELLE_SIP_LISTENING_POINT(obj) BELLE_SIP_CAST(obj,belle_sip_listening_point_t)
......@@ -415,6 +426,7 @@ typedef struct listener_ctx{
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);
/*
belle_sip_response_t
......
......@@ -118,6 +118,10 @@ unsigned long belle_sip_main_loop_add_timeout(belle_sip_main_loop_t *ml, belle_s
return s->id;
}
void belle_sip_source_set_timeout(belle_sip_source_t *s, unsigned int value_ms){
s->timeout=value_ms;
}
static int match_source_id(const void *s, const void *pid){
if ( ((belle_sip_source_t*)s)->id==(unsigned long)pid){
return 0;
......
......@@ -29,12 +29,7 @@
Channels: udp
*/
struct belle_sip_channel{
belle_sip_object_t base;
belle_sip_listening_point_t *lp; /* the listening point this channel belongs */
struct addrinfo peer;
struct sockaddr_storage peer_addr;
};
typedef struct belle_sip_channel_vptr{
int (*channel_send)(belle_sip_channel_t *obj, const void *buf, size_t buflen);
......
......@@ -100,6 +100,11 @@ belle_sip_header_t *belle_sip_message_get_header(belle_sip_message_t *msg, const
return NULL;
}
char *belle_sip_message_to_string(belle_sip_message_t *msg){
return NULL;
}
void belle_sip_response_get_return_hop(belle_sip_response_t *msg, belle_sip_hop_t *hop){
belle_sip_header_via_t *via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header(BELLE_SIP_MESSAGE(msg),"via"));
hop->transport=belle_sip_header_via_get_protocol(via);
......@@ -111,6 +116,7 @@ void belle_sip_response_get_return_hop(belle_sip_response_t *msg, belle_sip_hop_
hop->port=belle_sip_header_via_get_listening_port(via);
}
char *belle_sip_message_to_string(belle_sip_message_t *msg){
return NULL;
int belle_sip_response_get_status_code(const belle_sip_response_t *response){
return 0;
}
......@@ -122,4 +122,7 @@ void belle_sip_sender_task_send(belle_sip_sender_task_t *t){
}
}
int belle_sip_sender_task_is_reliable(belle_sip_sender_task_t *task){
if (task->channel==NULL) belle_sip_fatal("The transport isn't known yet");
return belle_sip_listening_point_is_reliable(task->channel->lp);
}
......@@ -45,6 +45,9 @@ belle_sip_sender_task_t * belle_sip_sender_task_new(belle_sip_provider_t *provid
void belle_sip_sender_task_send(belle_sip_sender_task_t *task);
/*you can only call that after send has been called once */
int belle_sip_sender_task_is_reliable(belle_sip_sender_task_t *task);
#endif
......@@ -23,16 +23,22 @@ 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;
void *appdata;
};
static unsigned long transaction_add_timeout(belle_sip_transaction_t *t, belle_sip_source_func_t func, unsigned int time_ms){
static belle_sip_source_t * transaction_create_timer(belle_sip_transaction_t *t, belle_sip_source_func_t func, unsigned int time_ms){
belle_sip_stack_t *stack=belle_sip_provider_get_sip_stack(t->provider);
return belle_sip_main_loop_add_timeout (stack->ml,func,t,time_ms);
belle_sip_source_t *s=belle_sip_timeout_source_new (func,t,time_ms);
belle_sip_main_loop_add_source(stack->ml,s);
return s;
}
/*
......@@ -51,6 +57,8 @@ 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->request) belle_sip_object_unref(t->request);
if (t->prov_response) belle_sip_object_unref(t->prov_response);
if (t->final_response) belle_sip_object_unref(t->final_response);
if (t->stask) belle_sip_object_unref(t->stask);
}
......@@ -105,10 +113,11 @@ belle_sip_server_transaction_t * belle_sip_server_transaction_new(belle_sip_prov
struct belle_sip_client_transaction{
belle_sip_transaction_t base;
unsigned long timer_id;
uint64_t start_time;
uint64_t time_F;
uint64_t time_E;
belle_sip_source_t *timer;
int interval;
uint64_t timer_F;
uint64_t timer_E;
uint64_t timer_K;
};
belle_sip_request_t * belle_sip_client_transaction_create_cancel(belle_sip_client_transaction_t *t){
......@@ -116,6 +125,19 @@ 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);
}
if (belle_sip_time_ms()>=t->timer_F){
belle_sip_transaction_terminate((belle_sip_transaction_t*)t);
return BELLE_SIP_STOP;
}
return BELLE_SIP_CONTINUE;
}
......@@ -123,8 +145,16 @@ static void client_transaction_cb(belle_sip_sender_task_t *task, void *data, int
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 (retcode==0){
t->base.is_reliable=belle_sip_sender_task_is_reliable(task);
t->base.state=BELLE_SIP_TRANSACTION_TRYING;
t->timer_id=transaction_add_timeout(&t->base,on_client_transaction_timer,tc->T1);
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);
}else{
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;
......@@ -140,6 +170,36 @@ 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){
int code=belle_sip_response_get_status_code(resp);
if (code>=100 && code<200){
switch(t->base.state){
case BELLE_SIP_TRANSACTION_TRYING:
case BELLE_SIP_TRANSACTION_PROCEEDING:
t->base.state=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);
break;
default:
belle_sip_warning("Unexpected provisional response while transaction in state %i",t->base.state);
}
}else if (code>=200){
switch(t->base.state){
case BELLE_SIP_TRANSACTION_TRYING:
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);
break;
default:
belle_sip_warning("Unexpected final response while transaction in state %i",t->base.state);
}
}
}
static void client_transaction_destroy(belle_sip_client_transaction_t *t ){
transaction_destroy((belle_sip_transaction_t*)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