Commit 2e7d9876 authored by Simon Morlat's avatar Simon Morlat

implement automatic cleanup of inactive channels

parent 43ad4169
......@@ -22,10 +22,10 @@
BELLE_SIP_BEGIN_DECLS
const char *belle_sip_listening_point_get_ip_address(const belle_sip_listening_point_t *lp);
int belle_sip_listening_point_get_port(const belle_sip_listening_point_t *lp);
BELLESIP_EXPORT const char *belle_sip_listening_point_get_ip_address(const belle_sip_listening_point_t *lp);
BELLESIP_EXPORT int belle_sip_listening_point_get_port(const belle_sip_listening_point_t *lp);
BELLESIP_EXPORT const char *belle_sip_listening_point_get_transport(const belle_sip_listening_point_t *lp);
const char *belle_sip_listening_point_get_ip_address(const belle_sip_listening_point_t *lp);
BELLESIP_EXPORT const char *belle_sip_listening_point_get_ip_address(const belle_sip_listening_point_t *lp);
/*
* set keep alive frequency in ms
* @param lp object
......@@ -38,7 +38,7 @@ BELLESIP_EXPORT void belle_sip_listening_point_set_keep_alive(belle_sip_listenin
* @param lp object
* @return keep alive period in ms. Values <=0 disable keep alive
* */
int belle_sip_listening_point_get_keep_alive(const belle_sip_listening_point_t *lp);
BELLESIP_EXPORT int belle_sip_listening_point_get_keep_alive(const belle_sip_listening_point_t *lp);
......@@ -47,8 +47,16 @@ int belle_sip_listening_point_get_keep_alive(const belle_sip_listening_point_t *
* @return IP/port/transport as an URI
*/
BELLESIP_EXPORT const belle_sip_uri_t* belle_sip_listening_point_get_uri(const belle_sip_listening_point_t *ip);
int belle_sip_listening_point_is_reliable(const belle_sip_listening_point_t *lp);
void belle_sip_listening_point_clean_channels(belle_sip_listening_point_t *lp);
BELLESIP_EXPORT int belle_sip_listening_point_is_reliable(const belle_sip_listening_point_t *lp);
/**
* Clean (close) all channels (connection) managed by this listening point.
**/
BELLESIP_EXPORT void belle_sip_listening_point_clean_channels(belle_sip_listening_point_t *lp);
/**
* Get the number of channels managed by this listening point.
**/
BELLESIP_EXPORT int belle_sip_listening_point_get_channel_count(const belle_sip_listening_point_t *lp);
BELLESIP_EXPORT int belle_sip_listening_point_get_well_known_port(const char *transport);
BELLE_SIP_END_DECLS
......
......@@ -76,6 +76,15 @@ BELLESIP_EXPORT void belle_sip_stack_set_resolver_tx_delay(belle_sip_stack_t *st
**/
BELLESIP_EXPORT void belle_sip_stack_set_resolver_send_error(belle_sip_stack_t *stack, int send_error);
/**
* Returns the time interval in seconds after which a connection must be closed when inactive.
**/
BELLESIP_EXPORT int belle_sip_stack_get_inactive_transport_timeout(const belle_sip_stack_t *stack);
/**
* Sets the time interval in seconds after which a connection must be closed when inactive.
**/
BELLESIP_EXPORT void belle_sip_stack_set_inactive_transport_timeout(belle_sip_stack_t *stack, int seconds);
void belle_sip_stack_push_pool(belle_sip_stack_t *stack);
......
......@@ -471,6 +471,7 @@ struct belle_sip_stack{
belle_sip_main_loop_t *ml;
belle_sip_timer_config_t timer_config;
int transport_timeout;
int inactive_transport_timeout;
int dns_timeout;
int tx_delay; /*used to simulate network transmission delay, for tests*/
int send_error; /* used to simulate network error. if <0, channel_send will return this value*/
......
......@@ -58,7 +58,11 @@ static void belle_sip_channel_destroy(belle_sip_channel_t *obj){
if (obj->local_ip) belle_sip_free(obj->local_ip);
obj->listeners=for_each_weak_unref_free(obj->listeners,(belle_sip_object_destroy_notify_t)belle_sip_channel_remove_listener,obj);
if (obj->resolver_id) belle_sip_resolve_cancel(belle_sip_stack_get_main_loop(obj->stack),obj->resolver_id);
belle_sip_message("channel [%p] destroyed",obj);
if (obj->inactivity_timer){
belle_sip_main_loop_remove_source(obj->stack->ml,obj->inactivity_timer);
belle_sip_object_unref(obj->inactivity_timer);
}
belle_sip_message("Channel [%p] destroyed",obj);
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_channel_t);
......@@ -72,6 +76,7 @@ BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_channel_t)=
NULL, /*marshall*/
}
};
static void fix_incoming_via(belle_sip_request_t *msg, const struct addrinfo* origin){
char received[NI_MAXHOST];
char rport[NI_MAXSERV];
......@@ -96,6 +101,7 @@ static void fix_incoming_via(belle_sip_request_t *msg, const struct addrinfo* or
}
}
}
static int get_message_start_pos(char *buff, size_t bufflen) {
/*FIXME still to optimize an better tested, specially REQUEST PATH and error path*/
int i;
......@@ -126,6 +132,7 @@ static void belle_sip_channel_input_stream_reset(belle_sip_channel_input_stream_
input_stream->state=WAITING_MESSAGE_START;
input_stream->msg=NULL;
}
static size_t belle_sip_channel_input_stream_get_buff_length(belle_sip_channel_input_stream_t* input_stream) {
return MAX_CHANNEL_BUFF_SIZE - (input_stream->write_ptr-input_stream->buff);
}
......@@ -155,8 +162,6 @@ int belle_sip_channel_process_data(belle_sip_channel_t *obj,unsigned int revents
num=-1; /*to trigger an error*/
}
if (num>0){
if (obj->input_stream.state == WAITING_MESSAGE_START) {
/*search for request*/
if ((offset=get_message_start_pos(obj->input_stream.read_ptr,num)) >=0 ) {
......@@ -247,6 +252,30 @@ int belle_sip_channel_process_data(belle_sip_channel_t *obj,unsigned int revents
return BELLE_SIP_CONTINUE;
}
static int channel_inactive_timeout(void *data, unsigned int event){
belle_sip_channel_t *obj=(belle_sip_channel_t *)data;
channel_set_state(obj,BELLE_SIP_CHANNEL_DISCONNECTED);
belle_sip_channel_close(obj);
return BELLE_SIP_STOP;
}
static void update_inactivity_timer(belle_sip_channel_t *obj){
int inactive_timeout=belle_sip_stack_get_inactive_transport_timeout(obj->stack)*1000;
if (inactive_timeout>0){
if (!obj->inactivity_timer ){
obj->inactivity_timer=belle_sip_main_loop_create_timeout(obj->stack->ml,channel_inactive_timeout,obj,inactive_timeout,"Channel inactivity timer");
}else{
/*restart the timer for new period*/
belle_sip_source_set_timeout(obj->inactivity_timer,inactive_timeout);
}
}else{
if (obj->inactivity_timer){
belle_sip_main_loop_remove_source(obj->stack->ml,obj->inactivity_timer);
belle_sip_object_unref(obj->inactivity_timer);
obj->inactivity_timer=NULL;
}
}
}
void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_stack_t *stack,const char *bindip,int localport,const char *peername, int peer_port){
obj->peer_name=belle_sip_strdup(peername);
......@@ -257,6 +286,7 @@ void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_stack_t *stack,c
obj->local_port=localport;
obj->recv_error=1;/*not set*/
belle_sip_channel_input_stream_reset(&obj->input_stream);
update_inactivity_timer(obj);
}
void belle_sip_channel_init_with_addr(belle_sip_channel_t *obj, belle_sip_stack_t *stack, const struct sockaddr *peer_addr, socklen_t addrlen){
......@@ -326,11 +356,15 @@ const char * belle_sip_channel_get_transport_name(const belle_sip_channel_t *obj
return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->transport;
}
int belle_sip_channel_send(belle_sip_channel_t *obj, const void *buf, size_t buflen){
update_inactivity_timer(obj);
return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->channel_send(obj,buf,buflen);
}
int belle_sip_channel_recv(belle_sip_channel_t *obj, void *buf, size_t buflen){
update_inactivity_timer(obj);
return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->channel_recv(obj,buf,buflen);
}
......@@ -541,7 +575,6 @@ int belle_sip_channel_queue_message(belle_sip_channel_t *obj, belle_sip_message_
void belle_sip_channel_force_close(belle_sip_channel_t *obj){
obj->force_close=1;
/*first, every existing channel must be set to error*/
channel_set_state(obj,BELLE_SIP_CHANNEL_DISCONNECTED);
belle_sip_channel_close(obj);
}
......
......@@ -87,6 +87,7 @@ struct belle_sip_channel{
belle_sip_list_t *outgoing_messages;
belle_sip_list_t* incoming_messages;
belle_sip_channel_input_stream_t input_stream;
belle_sip_source_t *inactivity_timer;
unsigned int recv_error:1; /* used to simulate network error. if <=0, channel_recv will return this value*/
unsigned int force_close:1; /* used to simulate network error. if <=0, channel_recv will return this value*/
};
......
......@@ -76,6 +76,9 @@ void belle_sip_listening_point_clean_channels(belle_sip_listening_point_t *lp){
lp->channels=belle_sip_list_free_with_data(lp->channels,(void (*)(void*))belle_sip_object_unref);
}
int belle_sip_listening_point_get_channel_count(const belle_sip_listening_point_t *lp){
return belle_sip_list_size(lp->channels);
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_listening_point_t);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_listening_point_t)={
......
......@@ -74,6 +74,7 @@ belle_sip_stack_t * belle_sip_stack_new(const char *properties){
stack->timer_config.T4=5000;
stack->transport_timeout=30000;
stack->dns_timeout=15000;
stack->inactive_transport_timeout=3600; /*one hour*/
return stack;
}
......@@ -165,3 +166,10 @@ const char* belle_sip_version_to_string() {
return PACKAGE_VERSION;
}
int belle_sip_stack_get_inactive_transport_timeout(const belle_sip_stack_t *stack){
return stack->inactive_transport_timeout;
}
void belle_sip_stack_set_inactive_transport_timeout(belle_sip_stack_t *stack, int seconds){
stack->inactive_transport_timeout=seconds;
}
......@@ -375,6 +375,18 @@ static void test_register_authenticate(void) {
belle_sip_object_unref(reg);
}
static void test_register_channel_inactive(void){
belle_sip_listening_point_t *lp=belle_sip_provider_get_listening_point(prov,"TCP");
CU_ASSERT_PTR_NOT_NULL_FATAL(lp);
belle_sip_stack_set_inactive_transport_timeout(stack,5);
belle_sip_listening_point_clean_channels(lp);
CU_ASSERT_EQUAL(belle_sip_listening_point_get_channel_count(lp),0);
register_test("tcp",1);
CU_ASSERT_EQUAL(belle_sip_listening_point_get_channel_count(lp),1);
belle_sip_stack_sleep(stack,5000);
CU_ASSERT_EQUAL(belle_sip_listening_point_get_channel_count(lp),0);
belle_sip_stack_set_inactive_transport_timeout(stack,3600);
}
test_t register_tests[] = {
{ "Stateful UDP", stateful_register_udp },
......@@ -388,7 +400,8 @@ test_t register_tests[] = {
{ "Stateless TCP", stateless_register_tcp },
{ "Stateless TLS", stateless_register_tls },
{ "Bad TCP request", test_bad_request },
{ "Authenticate", test_register_authenticate }
{ "Authenticate", test_register_authenticate },
{ "Channel inactive", test_register_channel_inactive }
};
test_suite_t register_test_suite = {
......
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