Commit 3e3d151c authored by Simon Morlat's avatar Simon Morlat

fix many many memory leaks,

document object memory management.
parent f49abc96
......@@ -80,6 +80,7 @@ struct belle_sip_listener_callbacks{
void (*process_timeout)(void *user_ctx, const belle_sip_timeout_event_t *event);
void (*process_transaction_terminated)(void *user_ctx, const belle_sip_transaction_terminated_event_t *event);
void (*process_auth_requested)(void *user_ctx, belle_sip_auth_event_t *auth_event);
void (*listener_destroyed)(void *user_ctx);
};
typedef struct belle_sip_listener_callbacks belle_sip_listener_callbacks_t;
......
......@@ -74,8 +74,38 @@ typedef unsigned int belle_sip_type_id_t;
* It is the base class for all belle sip non trivial objects.
* It owns a reference count which allows to trigger the destruction of the object when the last
* user of it calls belle_sip_object_unref().
*
* About object lifecycle<br>
* In belle-sip, objects can be, depending on their types, initially owned, that there are created with a ref count of 1, or
* initially unowned, that is with reference count of 0. Such objets are also referred as "floating object". They are automatically destroyed
* by the main loop iteration, so a floating object can be seen as a temporary object, until someones calls belle_sip_object_ref() on it.
*
* In order to know whether a kind of object is initially owned or initially unowned, you can use the test program tester/belle_sip_object_destribe.
* This tool gives the hierarchy and properties of the object type whose name is supplied in argument. For example:
*
* <pre>./tester/belle_sip_object_describe belle_sip_request_t</pre>
*
* The object memory management depends slightly on whether an object type is created initially owned or not.
* In order not to be lost and make memory fault or leaks, consider the following rules:
*
* When an object is of type initially unowned:
* * call belle_sip_object_ref() on it only if you need a pointer to this object to be used outside the scope of the current function.
* * call belle_sip_object_unref() on it only if you previously called belle_sip_object_ref().
*
* When an object is of type initially owned:
* * you can safely store its pointer.
* * use belle_sip_object_unref() when you no longer need it.
*
* Also, keep in mind that most objects of belle-sip are initially unowned, especially
* * all objects who are usually required to be used inside another object (for example: an URI is part of a from header, a contact header is part of a message)
* * all objects whose lifecyle is maintained by the stack: transactions, dialogs.
*
* On the contrary, top level objects whose lifecyle belongs only to the application are initially owned:
* * belle_sip_provider_t, belle_sip_stack_t, belle_sip_source_t.
*
* Internally, belle-sip objects containing pointers to other objects must take a reference count on the other objects they hold; and leave this reference
* when they no longer need it. This rule must be strictly followed by developers doing things inside belle-sip.
**/
typedef struct _belle_sip_object belle_sip_object_t;
......@@ -120,6 +150,7 @@ int belle_sip_object_is_unowed(const belle_sip_object_t *obj);
/**
* Increments reference counter, which prevents the object from being destroyed.
* If the object is initially unowed, this acquires the first reference.
*
**/
belle_sip_object_t * belle_sip_object_ref(void *obj);
......@@ -156,13 +187,13 @@ const char* belle_sip_object_get_name(belle_sip_object_t *obj);
/*copy the content of ref object to new object, for the part they have in common in their inheritence diagram*/
void _belle_sip_object_copy(belle_sip_object_t *newobj, const belle_sip_object_t *ref);
belle_sip_object_t *belle_sip_object_clone(const belle_sip_object_t *obj);
/**
* Delete the object: this function is intended for unowed object, that is objects
* that were created with a 0 reference count. For all others, use belle_sip_object_unref().
* Clone an object.
*
* This clone function makes a deep copy of all object internal structure, so that the new object and the reference object have no dependencies at all.
*
**/
void belle_sip_object_delete(void *obj);
belle_sip_object_t *belle_sip_object_clone(const belle_sip_object_t *obj);
/**
* Returns a string describing the inheritance diagram and implemented interfaces of object obj.
......@@ -176,8 +207,17 @@ char *belle_sip_object_describe_type_from_name(const char *name);
void *belle_sip_object_cast(belle_sip_object_t *obj, belle_sip_type_id_t id, const char *castname, const char *file, int fileno);
/**
* Returns a newly allocated string representing the object.
* WHen the object is a sip header, uri or message, this is the textual representation of the header, uri or message.
* This function internally calls belle_sip_object_marshal().
**/
char* belle_sip_object_to_string(belle_sip_object_t* obj);
/**
* Writes a string representation of the object into the supplied buffer.
* Same as belle_sip_object_to_string(), but without allocating space for the output string.
**/
int belle_sip_object_marshal(belle_sip_object_t* obj, char* buff,unsigned int offset,size_t buff_size);
int belle_sip_object_is_instance_of(belle_sip_object_t * obj,belle_sip_type_id_t id);
......
......@@ -133,6 +133,8 @@ void belle_sip_set_log_level(int level);
char * belle_sip_random_token(char *ret, size_t size);
char * belle_sip_octets_to_text(const unsigned char *hash, size_t hash_len, char *ret, size_t size);
char * belle_sip_create_tag(char *ret, size_t size);
#if defined(WIN32) || defined(WIN32_WCE)
......
......@@ -76,7 +76,7 @@ BELLE_SIP_INSTANCIATE_VPTR(belle_sip_header_t,belle_sip_object_t,belle_sip_heade
***********************/
struct _belle_sip_header_address {
belle_sip_parameters_t base;
const char* displayname;
char* displayname;
belle_sip_uri_t* uri;
};
......@@ -85,8 +85,8 @@ static void belle_sip_header_address_init(belle_sip_header_address_t* object){
}
static void belle_sip_header_address_destroy(belle_sip_header_address_t* address) {
if (address->displayname) belle_sip_free((void*)(address->displayname));
if (address->uri) belle_sip_object_unref(BELLE_SIP_OBJECT(address->uri));
if (address->displayname) belle_sip_free(address->displayname);
if (address->uri) belle_sip_object_unref(address->uri);
}
static void belle_sip_header_address_clone(belle_sip_header_address_t *addr, const belle_sip_header_address_t *orig){
......@@ -127,18 +127,23 @@ BELLE_SIP_PARSE(header_address)
GET_SET_STRING(belle_sip_header_address,displayname);
void belle_sip_header_address_set_quoted_displayname(belle_sip_header_address_t* address,const char* value) {
if (address->displayname != NULL) belle_sip_free((void*)(address->displayname));
if (address->displayname != NULL) belle_sip_free(address->displayname);
if (strlen(value)>2)
address->displayname=_belle_sip_str_dup_and_unquote_string(value);
else
address->displayname=NULL;
}
belle_sip_uri_t* belle_sip_header_address_get_uri(const belle_sip_header_address_t* address) {
return address->uri;
}
void belle_sip_header_address_set_uri(belle_sip_header_address_t* address, belle_sip_uri_t* uri) {
address->uri=(belle_sip_uri_t*)belle_sip_object_ref(uri);
belle_sip_object_ref(uri);
if (address->uri){
belle_sip_object_unref(address->uri);
}
address->uri=uri;
}
belle_sip_header_address_t* belle_sip_header_address_create(const char* display, belle_sip_uri_t* uri) {
......@@ -265,6 +270,7 @@ static void belle_sip_header_from_destroy(belle_sip_header_from_t* from) {
static void belle_sip_header_from_clone(belle_sip_header_from_t* from, const belle_sip_header_from_t* cloned) {
}
int belle_sip_header_from_marshal(belle_sip_header_from_t* from, char* buff,unsigned int offset,unsigned int buff_size) {
BELLE_SIP_FROM_LIKE_MARSHAL(from);
}
......@@ -281,7 +287,7 @@ belle_sip_header_from_t* belle_sip_header_from_create2(const char *address, cons
belle_sip_header_from_t* belle_sip_header_from_create(const belle_sip_header_address_t* address, const char *tag) {
belle_sip_header_from_t* header= belle_sip_header_from_new();
_belle_sip_object_copy((belle_sip_object_t*)header,(belle_sip_object_t*)address);
belle_sip_header_set_name(BELLE_SIP_HEADER(header),BELLE_SIP_FROM); /*restaure header name*/
belle_sip_header_set_name(BELLE_SIP_HEADER(header),BELLE_SIP_FROM); /*restore header name*/
if (tag) belle_sip_header_from_set_tag(header,tag);
return header;
}
......@@ -290,8 +296,7 @@ BELLE_SIP_PARSE(header_from)
GET_SET_STRING_PARAM2(belle_sip_header_from,tag,raw_tag);
void belle_sip_header_from_set_random_tag(belle_sip_header_from_t *obj){
char tmp[8];
/*not less than 32bit */
char tmp[BELLE_SIP_TAG_LENGTH];
belle_sip_header_from_set_raw_tag(obj,belle_sip_random_token(tmp,sizeof(tmp)));
}
......
......@@ -145,6 +145,8 @@ typedef struct weak_ref{
void *belle_sip_object_get_interface_methods(belle_sip_object_t *obj, belle_sip_interface_id_t ifid);
void belle_sip_object_delete_unowned(void);
/*used internally by unref()*/
void belle_sip_object_delete(void *obj);
#define BELLE_SIP_OBJECT_VPTR(obj,object_type) ((BELLE_SIP_OBJECT_VPTR_TYPE(object_type)*)(((belle_sip_object_t*)obj)->vptr))
......@@ -580,6 +582,8 @@ static inline void belle_sip_transaction_stop_timer(belle_sip_transaction_t *obj
void belle_sip_transaction_notify_timeout(belle_sip_transaction_t *t);
void belle_sip_transaction_set_dialog(belle_sip_transaction_t *t, belle_sip_dialog_t *dialog);
/*
*
*
......@@ -846,4 +850,8 @@ belle_sip_refresher_t* belle_sip_refresher_new(belle_sip_client_transaction_t* t
#define BELLE_SIP_SOCKET_TIMEOUT 30000
#define BELLE_SIP_BRANCH_ID_LENGTH 10
/*Shall not be less than 32bit */
#define BELLE_SIP_TAG_LENGTH 6
#endif
......@@ -92,6 +92,9 @@ void belle_sip_main_loop_remove_source(belle_sip_main_loop_t *ml, belle_sip_sour
static void belle_sip_main_loop_destroy(belle_sip_main_loop_t *ml){
belle_sip_main_loop_remove_source(ml,ml->control);
while (ml->sources){
belle_sip_main_loop_remove_source(ml,(belle_sip_source_t*)ml->sources->data);
}
close(ml->control_fds[0]);
close(ml->control_fds[1]);
belle_sip_object_unref(ml->control);
......@@ -289,7 +292,7 @@ int belle_sip_main_loop_quit(belle_sip_main_loop_t *ml){
//if (write(ml->control_fds[1],"a",1)==-1){
// belle_sip_error("Fail to write to main loop control fd.");
//}
return 0;
return BELLE_SIP_STOP;
}
void belle_sip_main_loop_sleep(belle_sip_main_loop_t *ml, int milliseconds){
......
......@@ -40,6 +40,7 @@ static void belle_sip_parameters_clone(belle_sip_parameters_t *params, const bel
belle_sip_parameters_set_parameter( params,container->name,container->value);
}
}
int belle_sip_parameters_marshal(const belle_sip_parameters_t* params, char* buff,unsigned int offset,unsigned int buff_size) {
belle_sip_list_t* list=params->param_list;
unsigned int curent_offset=offset;
......
......@@ -106,7 +106,7 @@ BELLE_SIP_INSTANCIATE_VPTR(belle_sip_uri_t,belle_sip_parameters_t,belle_sip_uri_
belle_sip_uri_t* belle_sip_uri_new () {
belle_sip_uri_t* l_object = (belle_sip_uri_t*)belle_sip_object_new(belle_sip_uri_t);
belle_sip_uri_t* l_object = belle_sip_object_new(belle_sip_uri_t);
belle_sip_parameters_init((belle_sip_parameters_t*)l_object); /*super*/
l_object->header_list = belle_sip_parameters_new();
belle_sip_object_ref(l_object->header_list);
......
......@@ -530,17 +530,77 @@ unsigned int belle_sip_random(void){
return (unsigned int) random();
}
static const char *symbols="aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789-~";
/**
* Write a random text token of supplied size.
**/
char * belle_sip_random_token(char *ret, size_t size){
static const char *symbols="aAbBcCdDeEfFgGhHiIjJkKlLmMnN0pPqQrRsStTuUvVwWxXyYzZ";
unsigned int val;
int i,j;
for(i=0,j=0;i<size-1;++i,++j){
if (j%6==0) val=belle_sip_random();
ret[i]=symbols[val & 31];
val=val>>5;
if (j%5==0) val=belle_sip_random();
ret[i]=symbols[val & 63];
val=val>>6;
}
ret[i]=0;
return ret;
}
typedef struct bits_reader{
const uint8_t *buffer;
size_t buf_size;
int bit_index;
}bits_reader_t;
static void bits_reader_init(bits_reader_t *reader, const uint8_t *buffer, size_t bufsize){
reader->buffer=buffer;
reader->buf_size=bufsize;
reader->bit_index=0;
}
static int bits_reader_read(bits_reader_t *reader, int count, unsigned int *ret){
unsigned int tmp;
int byte_index=reader->bit_index/8;
int bit_index=reader->bit_index % 8;
int shift=32-bit_index-count;
if (count>=24){
belle_sip_error("This bit reader cannot read more than 24 bits at once.");
return -1;
}
if (byte_index<reader->buf_size)
tmp=((unsigned int)reader->buffer[byte_index++])<<24;
else{
belle_sip_error("Bit reader goes end of stream.");
return -1;
}
if (byte_index<reader->buf_size)
tmp|=((unsigned int)reader->buffer[byte_index++])<<16;
if (byte_index<reader->buf_size)
tmp|=((unsigned int)reader->buffer[byte_index++])<<8;
if (byte_index<reader->buf_size)
tmp|=((unsigned int)reader->buffer[byte_index++]);
tmp=tmp>>shift;
tmp=tmp & ((1<<count)-1);
reader->bit_index+=count;
*ret=tmp;
return 0;
}
char * belle_sip_octets_to_text(const uint8_t *hash, size_t hash_len, char *ret, size_t size){
int i;
bits_reader_t bitctx;
bits_reader_init(&bitctx,hash,hash_len);
for(i=0;i<size-1;++i){
unsigned int val=0;
if (bits_reader_read(&bitctx,6,&val)==0){
ret[i]=symbols[val];
}else break;
}
ret[i]=0;
return ret;
......
......@@ -50,7 +50,6 @@ static belle_sip_list_t * for_each_weak_unref_free(belle_sip_list_t *l, belle_si
}
static void belle_sip_channel_destroy(belle_sip_channel_t *obj){
if (obj->peer) freeaddrinfo(obj->peer);
belle_sip_free(obj->peer_name);
if (obj->local_ip) belle_sip_free(obj->local_ip);
......
......@@ -45,7 +45,7 @@ static void belle_sip_dialog_uninit(belle_sip_dialog_t *obj){
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_dialog_t);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_dialog_t)={
BELLE_SIP_VPTR_INIT(belle_sip_dialog_t, belle_sip_object_t,FALSE),
BELLE_SIP_VPTR_INIT(belle_sip_dialog_t, belle_sip_object_t,TRUE),
(belle_sip_object_destroy_t)belle_sip_dialog_uninit,
NULL,
NULL
......
......@@ -218,9 +218,9 @@ int belle_sip_message_named_headers_marshal(belle_sip_message_t *message, const
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s","\r\n");\
}
*/
typedef void (*heach_header_cb)(const belle_sip_header_t* header,void* userdata);
typedef void (*each_header_cb)(const belle_sip_header_t* header,void* userdata);
static void belle_sip_message_for_each_header(const belle_sip_message_t *message,heach_header_cb cb,void* user_data) {
static void belle_sip_message_for_each_header(const belle_sip_message_t *message,each_header_cb cb,void* user_data) {
belle_sip_list_t* headers_list;
belle_sip_list_t* header_list;
for(headers_list=message->header_list;headers_list!=NULL;headers_list=headers_list->next){
......@@ -262,12 +262,12 @@ int belle_sip_headers_marshal(belle_sip_message_t *message, char* buff,unsigned
struct _belle_sip_request {
belle_sip_message_t message;
const char* method;
char* method;
belle_sip_uri_t* uri;
};
static void belle_sip_request_destroy(belle_sip_request_t* request) {
if (request->method) belle_sip_free((void*)(request->method));
if (request->method) belle_sip_free(request->method);
if (request->uri) belle_sip_object_unref(request->uri);
}
......@@ -278,6 +278,7 @@ static void belle_sip_request_clone(belle_sip_request_t *request, const belle_si
if (orig->method) request->method=belle_sip_strdup(orig->method);
if (orig->uri) request->uri=(belle_sip_uri_t*)belle_sip_object_ref(belle_sip_object_clone((belle_sip_object_t*)orig->uri));
}
int belle_sip_request_marshal(belle_sip_request_t* request, char* buff,unsigned int offset,unsigned int buff_size) {
unsigned int current_offset=offset;
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s ",belle_sip_request_get_method(request));
......@@ -295,10 +296,11 @@ BELLE_SIP_PARSE(request)
GET_SET_STRING(belle_sip_request,method);
void belle_sip_request_set_uri(belle_sip_request_t* request,belle_sip_uri_t* uri) {
belle_sip_object_ref(uri);
if (request->uri) {
belle_sip_object_unref(request->uri);
}
request->uri=BELLE_SIP_URI(belle_sip_object_ref(uri));
request->uri=uri;
}
belle_sip_uri_t * belle_sip_request_get_uri(belle_sip_request_t *request){
......
......@@ -18,6 +18,8 @@
#include "belle_sip_internal.h"
#include "listeningpoint_internal.h"
#include "md5.h"
belle_sip_dialog_t *belle_sip_provider_find_dialog(belle_sip_provider_t *prov, belle_sip_request_t *msg, int as_uas);
typedef struct authorization_context {
......@@ -135,10 +137,40 @@ static void belle_sip_provider_dispatch_message(belle_sip_provider_t *prov, bell
belle_sip_object_unref(msg);
}
/*
* takes example on 16.11 of RFC3261
*/
static void compute_branch(belle_sip_message_t *msg, char *branchid, size_t branchid_size){
md5_state_t ctx;
unsigned int cseq=belle_sip_header_cseq_get_seq_number(belle_sip_message_get_header_by_type(msg,belle_sip_header_cseq_t));
char tmp[256]={0};
uint8_t digest[16];
const char*callid=belle_sip_header_call_id_get_call_id(belle_sip_message_get_header_by_type(msg,belle_sip_header_call_id_t));
const char *from_tag=belle_sip_header_from_get_tag(belle_sip_message_get_header_by_type(msg,belle_sip_header_from_t));
const char *to_tag=belle_sip_header_to_get_tag(belle_sip_message_get_header_by_type(msg,belle_sip_header_to_t));
belle_sip_header_via_t *prev_via=(belle_sip_header_via_t*)belle_sip_message_get_headers(msg,"via")->next;
md5_init(&ctx);
belle_sip_object_marshal((belle_sip_object_t*)belle_sip_request_get_uri(BELLE_SIP_REQUEST(msg)),tmp,0,sizeof(tmp)-1);
md5_append(&ctx,(uint8_t*)tmp,strlen(tmp));
if (from_tag)
md5_append(&ctx,(uint8_t*)from_tag,strlen(from_tag));
if (to_tag)
md5_append(&ctx,(uint8_t*)to_tag,strlen(to_tag));
md5_append(&ctx,(uint8_t*)callid,strlen(callid));
md5_append(&ctx,(uint8_t*)&cseq,sizeof(cseq));
if (prev_via){
belle_sip_object_marshal((belle_sip_object_t*)prev_via,tmp,0,sizeof(tmp)-1);
md5_append(&ctx,(uint8_t*)tmp,strlen(tmp));
}
md5_finish(&ctx,digest);
belle_sip_octets_to_text(digest,sizeof(digest),branchid,branchid_size);
}
static void fix_outgoing_via(belle_sip_provider_t *p, belle_sip_channel_t *chan, belle_sip_message_t *msg){
belle_sip_header_via_t *via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header(msg,"via"));
belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(via),"rport",NULL);
char token[7]="fixme";
if (belle_sip_header_via_get_host(via)==NULL){
const char *local_ip;
int local_port;
......@@ -149,10 +181,13 @@ static void fix_outgoing_via(belle_sip_provider_t *p, belle_sip_channel_t *chan,
belle_sip_header_via_set_transport(via,belle_sip_channel_get_transport_name(chan));
}
if (belle_sip_header_via_get_branch(via)==NULL){
/*FIXME: should not be set random here: but rather a hash of message invariants*/
char *branchid=belle_sip_strdup_printf(BELLE_SIP_BRANCH_MAGIC_COOKIE ".%s",token);
/*branch id should not be set random here (stateless forwarding): but rather a hash of message invariants*/
char branchid[24];
char token[BELLE_SIP_BRANCH_ID_LENGTH];
compute_branch(msg,token,sizeof(token));
snprintf(branchid,sizeof(branchid)-1,BELLE_SIP_BRANCH_MAGIC_COOKIE ".%s",token);
belle_sip_header_via_set_branch(via,branchid);
belle_sip_free(branchid);
belle_sip_message("Computing branch id %s for message sent statelessly", branchid);
}
}
/*
......@@ -300,8 +335,8 @@ belle_sip_dialog_t * belle_sip_provider_create_dialog_internal(belle_sip_provide
}
dialog=belle_sip_dialog_new(t);
if (dialog) {
t->dialog=(belle_sip_dialog_t*)belle_sip_object_ref(dialog);
belle_sip_provider_add_dialog(prov,(belle_sip_dialog_t*)belle_sip_object_ref(dialog));
belle_sip_transaction_set_dialog(t,dialog);
belle_sip_provider_add_dialog(prov,dialog);
}
return dialog;
}
......@@ -371,7 +406,7 @@ belle_sip_client_transaction_t *belle_sip_provider_create_client_transaction(bel
return NULL;
}
else t=(belle_sip_client_transaction_t*)belle_sip_nict_new(prov,req);
t->base.dialog=belle_sip_provider_find_dialog(prov,req,FALSE);
belle_sip_transaction_set_dialog((belle_sip_transaction_t*)t,belle_sip_provider_find_dialog(prov,req,FALSE));
return t;
}
......@@ -384,7 +419,7 @@ belle_sip_server_transaction_t *belle_sip_provider_create_server_transaction(bel
return NULL;
}else
t=(belle_sip_server_transaction_t*)belle_sip_nist_new(prov,req);
t->base.dialog=belle_sip_provider_find_dialog(prov,req,TRUE);
belle_sip_transaction_set_dialog((belle_sip_transaction_t*)t,belle_sip_provider_find_dialog(prov,req,TRUE));
belle_sip_provider_add_server_transaction(prov,t);
return t;
}
......@@ -696,7 +731,7 @@ int belle_sip_provider_add_authorization(belle_sip_provider_t *p, belle_sip_requ
belle_sip_header_authorization_set_nonce(authorization,auth_context->nonce);
belle_sip_header_authorization_set_qop(authorization,auth_context->qop);
belle_sip_header_authorization_set_opaque(authorization,auth_context->opaque);
belle_sip_header_authorization_set_uri(authorization,(belle_sip_uri_t*)belle_sip_object_ref(belle_sip_request_get_uri(request)));
belle_sip_header_authorization_set_uri(authorization,(belle_sip_uri_t*)belle_sip_request_get_uri(request));
if (auth_context->qop)
belle_sip_header_authorization_set_nonce_count(authorization,++auth_context->nonce_count);
if (auth_event->ha1) {
......
......@@ -27,6 +27,7 @@ struct belle_sip_refresher {
int expires;
unsigned int started;
belle_sip_listener_callbacks_t listener_callbacks;
belle_sip_listener_t *sip_listener;
void* user_data;
};
......@@ -100,6 +101,7 @@ static void process_transaction_terminated(void *user_ctx, const belle_sip_trans
static void destroy(belle_sip_refresher_t *refresher){
if (refresher->transaction) belle_sip_object_unref(refresher->transaction);
if (refresher->sip_listener) belle_sip_object_unref(refresher->sip_listener);
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_refresher_t);
......@@ -112,7 +114,6 @@ void belle_sip_refresher_set_listener(belle_sip_refresher_t* refresher, belle_si
}
static int refresh(belle_sip_refresher_t* refresher) {
belle_sip_request_t*old_request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(refresher->transaction));
belle_sip_dialog_t* dialog = belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(refresher->transaction));
belle_sip_client_transaction_t* client_transaction;
......@@ -153,7 +154,7 @@ static int refresh(belle_sip_refresher_t* refresher) {
belle_sip_error("Cannot send refresh method [%s] for refresher [%p]"
,belle_sip_request_get_method(old_request)
,refresher);
return -1;
return -1;
}
return 0;
}
......@@ -273,8 +274,9 @@ belle_sip_refresher_t* belle_sip_refresher_new(belle_sip_client_transaction_t* t
refresher->listener_callbacks.process_timeout=process_timeout;
refresher->listener_callbacks.process_io_error=process_io_error;
refresher->listener_callbacks.process_dialog_terminated=process_dialog_terminated;
refresher->listener_callbacks.process_transaction_terminated=process_transaction_terminated;
belle_sip_provider_add_internal_sip_listener(transaction->base.provider,belle_sip_listener_create_from_callbacks(&(refresher->listener_callbacks),refresher));
refresher->listener_callbacks.process_transaction_terminated=process_transaction_terminated;;
refresher->sip_listener=belle_sip_listener_create_from_callbacks(&(refresher->listener_callbacks),refresher);
belle_sip_provider_add_internal_sip_listener(transaction->base.provider,refresher->sip_listener);
if (set_expires_from_trans(refresher)){
belle_sip_error("Unable to extract refresh value from transaction [%p]",transaction);
}
......
......@@ -110,7 +110,12 @@ BELLE_SIP_IMPLEMENT_INTERFACE_END
BELLE_SIP_DECLARE_IMPLEMENTED_INTERFACES_1(belle_sip_callbacks_t,belle_sip_listener_t);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_callbacks_t,belle_sip_object_t,NULL,NULL,NULL,FALSE);
static void belle_sip_callbacks_destroy(belle_sip_callbacks_t *obj){
if (obj->cbs.listener_destroyed)
obj->cbs.listener_destroyed(obj->user_ctx);
}
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_callbacks_t,belle_sip_object_t,belle_sip_callbacks_destroy,NULL,NULL,FALSE);
belle_sip_listener_t *belle_sip_listener_create_from_callbacks(const belle_sip_listener_callbacks_t *callbacks, void *user_ctx){
......
......@@ -18,53 +18,22 @@
#include "belle_sip_internal.h"
#include "listeningpoint_internal.h"
#ifdef HAVE_GNUTLS
#include <gnutls/gnutls.h>
#endif
static void belle_sip_stack_destroy(belle_sip_stack_t *stack){
#ifdef HAVE_GNUTLS
gnutls_global_deinit ();
#endif
belle_sip_object_unref(stack->ml);
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_stack_t);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_stack_t,belle_sip_object_t,belle_sip_stack_destroy,NULL,NULL,FALSE);
#ifdef HAVE_GNUTLS
static void _gnutls_log_func( int level, const char* log) {
belle_sip_log_level belle_sip_level;
switch(level) {
case 1: belle_sip_level=BELLE_SIP_LOG_ERROR;break;
case 2: belle_sip_level=BELLE_SIP_LOG_WARNING;break;
case 3: belle_sip_level=BELLE_SIP_LOG_MESSAGE;break;
default:belle_sip_level=BELLE_SIP_LOG_MESSAGE;break;
}
belle_sip_log(belle_sip_level,"gnutls:%s",log);
}
#endif /*HAVE_GNUTLS*/
belle_sip_stack_t * belle_sip_stack_new(const char *properties){
#ifdef HAVE_GNUTLS
int result;
#endif
belle_sip_stack_t *stack=belle_sip_object_new(belle_sip_stack_t);
stack->ml=belle_sip_main_loop_new ();
stack->timer_config.T1=500;
stack->timer_config.T2=4000;
stack->timer_config.T4=5000;
stack->transport_timeout=30000;
#ifdef HAVE_OPENSSL
SSL_library_init();
SSL_load_error_strings();
/*CRYPTO_set_id_callback(&threadid_cb);
CRYPTO_set_locking_callback(&locking_function);*/
#endif
#ifdef HAVE_GNUTLS
/*gnutls_global_set_log_level(9);*/
gnutls_global_set_log_function(_gnutls_log_func);
if ((result = gnutls_global_init ()) <0) {
belle_sip_fatal("Cannot initialize gnu tls caused by [%s]",gnutls_strerror(result));
}
#endif
return stack;
}
......
......@@ -51,6 +51,7 @@ static void transaction_destroy(belle_sip_transaction_t *t){
if (t->last_response) belle_sip_object_unref(t->last_response);
if (t->channel) belle_sip_object_unref(t->channel);
if (t->branch_id) belle_sip_free(t->branch_id);
if (t->dialog) belle_sip_object_unref(t->dialog);
}
......@@ -104,6 +105,11 @@ belle_sip_dialog_t* belle_sip_transaction_get_dialog(const belle_sip_transactio
return t->dialog;
}
void belle_sip_transaction_set_dialog(belle_sip_transaction_t *t, belle_sip_dialog_t *dialog){
if (dialog) belle_sip_object_ref(dialog);
t->dialog=dialog;
}
/*
* Server transaction
*/
......@@ -242,7 +248,7 @@ int belle_sip_client_transaction_send_request(belle_sip_client_transaction_t *t)
belle_sip_error("belle_sip_client_transaction_send_request: bad state.");
return -1;
}
/*store preset route for futur use by refresher*/
/*store preset route for future use by refresher*/
t->preset_route=BELLE_SIP_HEADER_ROUTE(belle_sip_message_get_header(BELLE_SIP_MESSAGE(t->base.request),"route"));
if (t->preset_route) belle_sip_object_ref(t->preset_route);
......@@ -356,7 +362,7 @@ BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_client_transaction_t)={
void belle_sip_client_transaction_init(belle_sip_client_transaction_t *obj, belle_sip_provider_t *prov, belle_sip_request_t *req){
belle_sip_header_via_t *via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header((belle_sip_message_t*)req,"via"));
char token[10];
char token[BELLE_SIP_BRANCH_ID_LENGTH];
if (!via){
belle_sip_fatal("belle_sip_client_transaction_init(): No via in request.");
......@@ -394,7 +400,6 @@ belle_sip_request_t* belle_sip_client_transaction_create_authenticated_request(b
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_PROXY_AUTHORIZATION);
/*add preset route if any*/
if (t->preset_route) {
belle_sip_object_ref(t->preset_route);
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(t->preset_route));
}
/*put auth header*/
......
......@@ -39,7 +39,7 @@ BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_stream_listening_point_t);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_stream_listening_point_t)={
{
{
BELLE_SIP_VPTR_INIT(belle_sip_stream_listening_point_t, belle_sip_listening_point_t,FALSE),
BELLE_SIP_VPTR_INIT(belle_sip_stream_listening_point_t, belle_sip_listening_point_t,TRUE),
(belle_sip_object_destroy_t)belle_sip_stream_listening_point_uninit,
NULL,
NULL
......
......@@ -21,7 +21,57 @@
#ifdef HAVE_OPENSSL
#include "gnutls/openssl.h"
#endif
#ifdef HAVE_GNUTLS
#include <gnutls/gnutls.h>
#endif
static int tls_ready=0;
#ifdef HAVE_GNUTLS
static void _gnutls_log_func( int level, const char* log) {
belle_sip_log_level belle_sip_level;
switch(level) {
case 1: belle_sip_level=BELLE_SIP_LOG_ERROR;break;
case 2: belle_sip_level=BELLE_SIP_LOG_WARNING;break;
case 3: belle_sip_level=BELLE_SIP_LOG_MESSAGE;break;
default:belle_sip_level=BELLE_SIP_LOG_MESSAGE;break;
}
belle_sip_log(belle_sip_level,"gnutls:%s",log);
}
#endif /*HAVE_GNUTLS*/
static void check_tls_init(void){
if (tls_ready==0){
#ifdef HAVE_OPENSSL
SSL_library_init();
SSL_load_error_strings();
/*CRYPTO_set_id_callback(&threadid_cb);
CRYPTO_set_locking_callback(&locking_function);*/
#endif
#ifdef HAVE_GNUTLS
int result;
/*gnutls_global_set_log_level(9);*/
gnutls_global_set_log_function(_gnutls_log_func);
if ((result = gnutls_global_init ()) <0) {
belle_sip_fatal("Cannot initialize gnu tls caused by [%s]",gnutls_strerror(result));
}
#endif
}
tls_ready++;
}
static void check_tls_deinit(void){
tls_ready--;
if (tls_ready==0){
#ifdef HAVE_GNUTLS
gnutls_global_deinit ();
#endif
}
}
static void belle_sip_tls_listening_point_uninit(belle_sip_tls_listening_point_t *lp){
check_tls_deinit();
}
static belle_sip_channel_t *tls_create_channel(belle_sip_listening_point_t *lp, const char *dest_ip, int port){
......@@ -42,7 +92,7 @@ BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_tls_listening_point_t);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_tls_listening_point_t)={
{
{
BELLE_SIP_VPTR_INIT(belle_sip_tls_listening_point_t, belle_sip_listening_point_t,FALSE),
BELLE_SIP_VPTR_INIT(belle_sip_tls_listening_point_t, belle_sip_listening_point_t,TRUE),
(belle_sip_object_destroy_t)belle_sip_tls_listening_point_uninit,