Commit 5a453382 authored by Simon Morlat's avatar Simon Morlat

- add belle_sip_object_describe

- rework the "initially_unowned" attribute
- continue implementing channel and udp listening point to receive messages (not yet working)
parent ac7ae248
......@@ -8,6 +8,7 @@ AC_CONFIG_SRCDIR([src/belle_sip_utils.c])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE
AM_SILENT_RULES(yes)
# Checks for programs.
AC_PROG_CC
......@@ -68,6 +69,7 @@ fi
# Checks for library functions.
AC_CHECK_LIB(rt, clock_gettime)
AC_CHECK_LIB(dl, dlopen)
AM_CONDITIONAL(BUILD_TESTS,test x$found_cunit = xyes)
......
......@@ -162,9 +162,19 @@ belle_sip_object_t *belle_sip_object_clone(const belle_sip_object_t *obj);
**/
void belle_sip_object_delete(void *obj);
/**
* Returns a string describing the inheritance diagram and implemented interfaces of object obj.
**/
char *belle_sip_object_describe(void *obj);
/**
* Returns a string describing the inheritance diagram and implemented interfaces of an object given its type name.
**/
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);
void *belle_sip_object_cast_to_interface(belle_sip_object_t *obj, belle_sip_interface_id_t id, const char *castname, const char *file, int fileno);
void *belle_sip_object_interface_cast(belle_sip_object_t *obj, belle_sip_interface_id_t id, const char *castname, const char *file, int fileno);
char* belle_sip_object_to_string(belle_sip_object_t* obj);
......@@ -191,11 +201,20 @@ BELLE_SIP_END_DECLS
#define BELLE_SIP_INTERFACE_METHODS_TYPE(interface_name) methods_##interface_name
#define belle_sip_object_describe_type(type) \
belle_sip_object_describe_type_from_name(#type)
typedef struct belle_sip_interface_desc{
belle_sip_interface_id_t id;
const char *ifname;
}belle_sip_interface_desc_t;
#define BELLE_SIP_DECLARE_INTERFACE_BEGIN(interface_name) \
typedef struct struct##interface_name interface_name;\
typedef struct struct_methods_##interface_name BELLE_SIP_INTERFACE_METHODS_TYPE(interface_name);\
struct struct_methods_##interface_name {\
belle_sip_interface_id_t id;
belle_sip_interface_desc_t desc;\
#define BELLE_SIP_DECLARE_INTERFACE_END };
......
......@@ -45,6 +45,8 @@ BELLE_SIP_BEGIN_DECLS
void belle_sip_main_loop_add_source(belle_sip_main_loop_t *ml, belle_sip_source_t *source);
void belle_sip_main_loop_remove_source(belle_sip_main_loop_t *ml, belle_sip_source_t *source);
/**
* Creates a mainloop.
**/
......
......@@ -49,4 +49,6 @@ void belle_sip_provider_send_response(belle_sip_provider_t *p, belle_sip_respons
BELLE_SIP_END_DECLS
#define BELLE_SIP_PROVIDER(obj) BELLE_SIP_CAST(obj,belle_sip_provider_t)
#endif
......@@ -48,6 +48,7 @@ libbellesip_la_CFLAGS=$(STRICT_OPTIONS)
libbellesip_la_LIBADD=libbellesip_generated.la -lantlr3c
INCLUDES=-I$(top_srcdir)/include
EXTRA_DIST=$(grammar_files)
......
......@@ -269,7 +269,7 @@ int belle_sdp_base_description_marshal(belle_sdp_base_description_t* base_descri
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sdp_base_description_t);
BELLE_SIP_INSTANCIATE_VPTR(belle_sdp_base_description_t,belle_sip_object_t,belle_sdp_base_description_destroy,NULL,belle_sdp_base_description_marshal);
BELLE_SIP_INSTANCIATE_VPTR(belle_sdp_base_description_t,belle_sip_object_t,belle_sdp_base_description_destroy,NULL,belle_sdp_base_description_marshal,FALSE);
static int belle_sdp_base_description_attribute_comp_func(const belle_sdp_attribute_t* a, const char*b) {
return strcmp(a->name,b);
......@@ -992,7 +992,7 @@ static void belle_sdp_mime_parameter_destroy(belle_sdp_mime_parameter_t *mime_pa
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sdp_mime_parameter_t);
BELLE_SIP_INSTANCIATE_VPTR(belle_sdp_mime_parameter_t,belle_sip_object_t,belle_sdp_mime_parameter_destroy,NULL,NULL);
BELLE_SIP_INSTANCIATE_VPTR(belle_sdp_mime_parameter_t,belle_sip_object_t,belle_sdp_mime_parameter_destroy,NULL,NULL,TRUE);
belle_sdp_mime_parameter_t* belle_sdp_mime_parameter_new() {
belle_sdp_mime_parameter_t* l_param = belle_sip_object_new(belle_sdp_mime_parameter_t);
......
......@@ -64,7 +64,7 @@ int belle_sip_header_marshal(belle_sip_header_t* header, char* buff,unsigned int
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_header_t);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_header_t,belle_sip_object_t,belle_sip_header_destroy,belle_sip_header_clone,belle_sip_header_marshal);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_header_t,belle_sip_object_t,belle_sip_header_destroy,belle_sip_header_clone,belle_sip_header_marshal,TRUE);
/************************
......@@ -727,7 +727,7 @@ GET_SET_STRING(belle_sip_header_extension,value);
static void belle_sip_header_authorization_destroy(belle_sip_header_authorization_t* authorization) {
if (authorization->username) belle_sip_free((void*)authorization->username);
if (authorization->uri) {
belle_sip_object_unref(BELLE_SIP_OBJECT(authorization->uri));
belle_sip_object_unref(authorization->uri);
}
if (authorization->cnonce) belle_sip_free((void*)authorization->cnonce);
AUTH_BASE_DESTROY(authorization)
......@@ -752,11 +752,11 @@ belle_sip_uri_t* belle_sip_header_authorization_get_uri(const belle_sip_header_a
}
void belle_sip_header_authorization_set_uri(belle_sip_header_authorization_t* authorization, belle_sip_uri_t* uri) {
if (uri) belle_sip_object_ref(uri);
if (authorization->uri) {
belle_sip_object_unref(BELLE_SIP_OBJECT(authorization->uri));
}
authorization->uri=uri;
if (authorization->uri) belle_sip_object_ref(authorization->uri);
}
int belle_sip_header_authorization_marshal(belle_sip_header_authorization_t* authorization, char* buff,unsigned int offset,unsigned int buff_size) {
AUTH_BASE_MARSHAL(authorization)
......
......@@ -40,9 +40,11 @@ typedef void (*belle_sip_object_clone_t)(belle_sip_object_t* obj, const belle_si
typedef int (*belle_sip_object_marshal_t)(belle_sip_object_t* obj, char* buff,unsigned int offset,size_t buff_size);
struct _belle_sip_object_vptr{
belle_sip_type_id_t id;
belle_sip_type_id_t id;
const char *type_name;
int initially_unowned;
struct _belle_sip_object_vptr *parent;
belle_sip_interface_id_t **interfaces; /*NULL terminated table of */
belle_sip_interface_desc_t **interfaces; /*NULL terminated table of */
belle_sip_object_destroy_t destroy;
belle_sip_object_clone_t clone;
belle_sip_object_marshal_t marshal;
......@@ -62,23 +64,26 @@ extern belle_sip_object_vptr_t belle_sip_object_t_vptr;
#define BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(object_type, parent_type) \
typedef struct object_type##_vptr_struct BELLE_SIP_OBJECT_VPTR_TYPE(object_type);\
extern BELLE_SIP_OBJECT_VPTR_TYPE(object_type) BELLE_SIP_OBJECT_VPTR_NAME(object_type);\
struct object_type##_vptr_struct{\
BELLE_SIP_OBJECT_VPTR_TYPE(parent_type) base;
#define BELLE_SIP_DECLARE_CUSTOM_VPTR_END };
#define BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(object_type) \
BELLE_SIP_OBJECT_VPTR_TYPE(object_type) BELLE_SIP_OBJECT_VPTR_NAME(object_type)
BELLE_SIP_OBJECT_VPTR_TYPE(object_type) BELLE_SIP_OBJECT_VPTR_NAME(object_type)
#define BELLE_SIP_VPTR_INIT(object_type,parent_type) \
#define BELLE_SIP_VPTR_INIT(object_type,parent_type,unowned) \
BELLE_SIP_TYPE_ID(object_type), \
#object_type,\
unowned,\
(belle_sip_object_vptr_t*)&BELLE_SIP_OBJECT_VPTR_NAME(parent_type), \
(belle_sip_interface_id_t**)object_type##interfaces_table
(belle_sip_interface_desc_t**)object_type##interfaces_table
#define BELLE_SIP_INSTANCIATE_VPTR(object_type,parent_type,destroy,clone,marshal) \
#define BELLE_SIP_INSTANCIATE_VPTR(object_type,parent_type,destroy,clone,marshal,unowned) \
BELLE_SIP_OBJECT_VPTR_TYPE(object_type) BELLE_SIP_OBJECT_VPTR_NAME(object_type)={ \
BELLE_SIP_VPTR_INIT(object_type,parent_type), \
BELLE_SIP_VPTR_INIT(object_type,parent_type,unowned), \
(belle_sip_object_destroy_t)destroy, \
(belle_sip_object_clone_t)clone, \
(belle_sip_object_marshal_t)marshal\
......@@ -87,25 +92,26 @@ extern belle_sip_object_vptr_t belle_sip_object_t_vptr;
#define BELLE_SIP_IMPLEMENT_INTERFACE_BEGIN(object_type,interface_name) \
static BELLE_SIP_INTERFACE_METHODS_TYPE(interface_name) methods_##object_type##_##interface_name={\
BELLE_SIP_INTERFACE_ID(interface_name),
{ BELLE_SIP_INTERFACE_ID(interface_name),\
#interface_name },
#define BELLE_SIP_IMPLEMENT_INTERFACE_END };
#define BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(object_type)\
static belle_sip_type_id_t * object_type##interfaces_table[]={\
static belle_sip_interface_desc_t * object_type##interfaces_table[]={\
NULL \
}
#define BELLE_SIP_DECLARE_IMPLEMENTED_INTERFACES_1(object_type,iface1) \
static belle_sip_type_id_t * object_type##interfaces_table[]={\
(belle_sip_type_id_t*)&methods_##object_type##_##iface1, \
static belle_sip_interface_desc_t * object_type##interfaces_table[]={\
(belle_sip_interface_desc_t*)&methods_##object_type##_##iface1, \
NULL \
}
#define BELLE_SIP_DECLARE_IMPLEMENTED_INTERFACES_2(object_type,iface1,iface2) \
static belle_sip_type_id_t * object_type##interfaces_table[]={\
(belle_sip_type_id_t*)&methods_##object_type##_##iface1, \
(belle_sip_type_id_t*)&methods_##object_type##_##iface2, \
static belle_sip_interface_desc_t * object_type##interfaces_table[]={\
(belle_sip_interface_desc_t*)&methods_##object_type##_##iface1, \
(belle_sip_interface_desc_t*)&methods_##object_type##_##iface2, \
NULL \
}
......@@ -161,11 +167,10 @@ struct _belle_sip_object{
weak_ref_t *weak_refs;
};
belle_sip_object_t * _belle_sip_object_new(size_t objsize, belle_sip_object_vptr_t *vptr, int initially_unowed);
belle_sip_object_t * _belle_sip_object_new(size_t objsize, belle_sip_object_vptr_t *vptr);
void *belle_sip_object_get_interface_methods(belle_sip_object_t *obj, belle_sip_interface_id_t ifid);
#define belle_sip_object_new(_type) (_type*)_belle_sip_object_new(sizeof(_type),(belle_sip_object_vptr_t*)&BELLE_SIP_OBJECT_VPTR_NAME(_type),0)
#define belle_sip_object_new_unowed(_type)(_type*)_belle_sip_object_new(sizeof(_type),(belle_sip_object_vptr_t*)&BELLE_SIP_OBJECT_VPTR_NAME(_type),1)
#define belle_sip_object_new(_type) (_type*)_belle_sip_object_new(sizeof(_type),(belle_sip_object_vptr_t*)&BELLE_SIP_OBJECT_VPTR_NAME(_type))
#define BELLE_SIP_OBJECT_VPTR(obj,object_type) ((BELLE_SIP_OBJECT_VPTR_TYPE(object_type)*)(((belle_sip_object_t*)obj)->vptr))
#define belle_sip_object_init(obj) /*nothing*/
......@@ -486,9 +491,9 @@ belle_sip_##object_type##_t* belle_sip_##object_type##_parse (const char* value)
, belle_sip_##super_type##_t\
, belle_sip_##object_type##_destroy\
, belle_sip_##object_type##_clone\
, belle_sip_##object_type##_marshal); \
, belle_sip_##object_type##_marshal, TRUE); \
belle_sip_##object_type##_t* belle_sip_##object_type##_new () { \
belle_sip_##object_type##_t* l_object = belle_sip_object_new_unowed(belle_sip_##object_type##_t);\
belle_sip_##object_type##_t* l_object = belle_sip_object_new(belle_sip_##object_type##_t);\
belle_sip_##super_type##_init((belle_sip_##super_type##_t*)l_object); \
belle_sip_##init_type##_init((belle_sip_##init_type##_t*) l_object); \
if (name) belle_sip_header_set_name(BELLE_SIP_HEADER(l_object),name);\
......@@ -661,7 +666,7 @@ belle_sdp_##object_type##_t* belle_sdp_##object_type##_parse (const char* value)
, super_type##_t\
, belle_sdp_##object_type##_destroy\
, belle_sdp_##object_type##_clone\
, belle_sdp_##object_type##_marshal); \
, belle_sdp_##object_type##_marshal, TRUE); \
belle_sdp_##object_type##_t* belle_sdp_##object_type##_new () { \
belle_sdp_##object_type##_t* l_object = belle_sip_object_new(belle_sdp_##object_type##_t);\
super_type##_init((super_type##_t*)l_object); \
......@@ -673,7 +678,7 @@ belle_sdp_##object_type##_t* belle_sdp_##object_type##_parse (const char* value)
, super_type##_t\
, belle_sdp_##object_type##_destroy\
, belle_sdp_##object_type##_clone\
, belle_sdp_##object_type##_marshal); \
, belle_sdp_##object_type##_marshal,TRUE); \
belle_sdp_##object_type##_t* belle_sdp_##object_type##_new () { \
belle_sdp_##object_type##_t* l_object = belle_sip_object_new(belle_sdp_##object_type##_t);\
super_type##_init((super_type##_t*)l_object); \
......
......@@ -43,7 +43,7 @@ void belle_sip_fd_source_init(belle_sip_source_t *s, belle_sip_source_func_t fun
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_source_t);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_source_t,belle_sip_object_t,belle_sip_source_destroy,NULL,NULL);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_source_t,belle_sip_object_t,belle_sip_source_destroy,NULL,NULL,TRUE);
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){
belle_sip_source_t *s=belle_sip_object_new(belle_sip_source_t);
......@@ -68,7 +68,7 @@ struct belle_sip_main_loop{
int control_fds[2];
};
static void belle_sip_main_loop_remove_source(belle_sip_main_loop_t *ml, belle_sip_source_t *source){
void belle_sip_main_loop_remove_source(belle_sip_main_loop_t *ml, belle_sip_source_t *source){
ml->sources=belle_sip_list_remove_link(ml->sources,&source->node);
ml->nsources--;
......@@ -80,7 +80,6 @@ static void belle_sip_main_loop_remove_source(belle_sip_main_loop_t *ml, belle_s
static void belle_sip_main_loop_destroy(belle_sip_main_loop_t *ml){
belle_sip_main_loop_remove_source(ml,ml->control);
belle_sip_object_unref(ml->control);
close(ml->control_fds[0]);
close(ml->control_fds[1]);
}
......@@ -92,7 +91,7 @@ static int main_loop_done(void *data, unsigned int events){
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_main_loop_t);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_main_loop_t,belle_sip_object_t,belle_sip_main_loop_destroy,NULL,NULL);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_main_loop_t,belle_sip_object_t,belle_sip_main_loop_destroy,NULL,NULL,FALSE);
belle_sip_main_loop_t *belle_sip_main_loop_new(void){
belle_sip_main_loop_t*m=belle_sip_object_new(belle_sip_main_loop_t);
......
......@@ -283,7 +283,6 @@ uri_token: {IS_TOKEN(uri)}? token;
digest_uri [belle_sip_header_authorization_t* header_authorization_base]
: uri_token /*'uri'*/ equal DQUOTE uri DQUOTE
{belle_sip_header_authorization_set_uri(header_authorization_base,$uri.ret);
belle_sip_object_unref(BELLE_SIP_OBJECT($uri.ret));
};
/*
digest_uri_value : rquest_uri ;
......@@ -394,7 +393,7 @@ contact_param
name_addr[belle_sip_header_address_t* object]
: ( display_name[object] )? sp_laquot_sp addr_spec[object] sp_raquot_sp;
addr_spec[belle_sip_header_address_t* object]
: uri {belle_sip_header_address_set_uri(object,BELLE_SIP_URI(belle_sip_object_ref(BELLE_SIP_OBJECT($uri.ret))));};//| absoluteURI;
: uri {belle_sip_header_address_set_uri(object,$uri.ret);};//| absoluteURI;
display_name[belle_sip_header_address_t* object]
: token {belle_sip_header_address_set_displayname(object,(const char*)($token.text->chars));}
......
......@@ -32,16 +32,16 @@ int belle_sip_object_is_instance_of(belle_sip_object_t * obj,belle_sip_type_id_t
return has_type(obj,id);
}
belle_sip_object_t * _belle_sip_object_new(size_t objsize, belle_sip_object_vptr_t *vptr, int initially_unowed){
belle_sip_object_t * _belle_sip_object_new(size_t objsize, belle_sip_object_vptr_t *vptr){
belle_sip_object_t *obj=(belle_sip_object_t *)belle_sip_malloc0(objsize);
obj->ref=initially_unowed ? 0 : 1;
obj->ref=vptr->initially_unowned ? 0 : 1;
obj->vptr=vptr;
obj->size=objsize;
return obj;
}
int belle_sip_object_is_unowed(const belle_sip_object_t *obj){
return obj->ref==0;
int belle_sip_object_is_initially_unowned(const belle_sip_object_t *obj){
return obj->vptr->initially_unowned;
}
belle_sip_object_t * belle_sip_object_ref(void *obj){
......@@ -118,6 +118,8 @@ static void _belle_sip_object_clone(belle_sip_object_t *obj, const belle_sip_obj
belle_sip_object_vptr_t belle_sip_object_t_vptr={
BELLE_SIP_TYPE_ID(belle_sip_object_t),
"belle_sip_object_t",
FALSE,
NULL, /*no parent, it's god*/
NULL,
_belle_sip_object_uninit,
......@@ -175,10 +177,10 @@ void *belle_sip_object_get_interface_methods(belle_sip_object_t *obj, belle_sip_
if (obj!=NULL){
belle_sip_object_vptr_t *vptr;
for (vptr=obj->vptr;vptr!=NULL;vptr=vptr->parent){
belle_sip_interface_id_t **ifaces=vptr->interfaces;
belle_sip_interface_desc_t **ifaces=vptr->interfaces;
if (ifaces!=NULL){
for(;*ifaces!=0;++ifaces){
if (**ifaces==ifid){
if ((*ifaces)->id==ifid){
return *ifaces;
}
}
......@@ -192,7 +194,7 @@ int belle_sip_object_implements(belle_sip_object_t *obj, belle_sip_interface_id_
return belle_sip_object_get_interface_methods(obj,id)!=NULL;
}
void *belle_sip_object_cast_to_interface(belle_sip_object_t *obj, belle_sip_interface_id_t ifid, const char *castname, const char *file, int fileno){
void *belle_sip_object_interface_cast(belle_sip_object_t *obj, belle_sip_interface_id_t ifid, const char *castname, const char *file, int fileno){
if (obj!=NULL){
if (belle_sip_object_get_interface_methods(obj,ifid)==0){
belle_sip_fatal("Bad cast to interface %s at %s:%i",castname,file,fileno);
......@@ -226,6 +228,7 @@ int belle_sip_object_marshal(belle_sip_object_t* obj, char* buff,unsigned int of
}
return -1; /*no implementation found*/
}
char* belle_sip_object_to_string(belle_sip_object_t* obj) {
char buff[2048]; /*to be optimized*/
int size = belle_sip_object_marshal(obj,buff,0,sizeof(buff));
......@@ -233,3 +236,63 @@ char* belle_sip_object_to_string(belle_sip_object_t* obj) {
return strdup(buff);
}
char * _belle_sip_object_describe_type(belle_sip_object_vptr_t *vptr){
const int maxbufsize=2048;
char *ret=belle_sip_malloc(maxbufsize);
belle_sip_object_vptr_t *it;
int pos=0;
belle_sip_list_t *l=NULL,*elem;
pos+=snprintf(ret+pos,maxbufsize-pos,"Ownership:\n");
pos+=snprintf(ret+pos,maxbufsize-pos,"\t%s is created initially %s\n",vptr->type_name,
vptr->initially_unowned ? "unowned" : "owned");
pos+=snprintf(ret+pos,maxbufsize-pos,"\nInheritance diagram:\n");
for(it=vptr;it!=NULL;it=it->parent){
l=belle_sip_list_prepend(l,it);
}
for(elem=l;elem!=NULL;elem=elem->next){
it=(belle_sip_object_vptr_t*)elem->data;
pos+=snprintf(ret+pos,maxbufsize-pos,"\t%s\n",it->type_name);
if (elem->next)
pos+=snprintf(ret+pos,maxbufsize-pos,"\t |\n");
}
belle_sip_list_free(l);
pos+=snprintf(ret+pos,maxbufsize-pos,"\nImplemented interfaces:\n");
for(it=vptr;it!=NULL;it=it->parent){
belle_sip_interface_desc_t **desc=it->interfaces;
if (desc!=NULL){
for(;*desc!=NULL;desc++){
pos+=snprintf(ret+pos,maxbufsize-pos,"\t* %s\n",(*desc)->ifname);
}
}
}
return ret;
}
char *belle_sip_object_describe(void *obj){
belle_sip_object_t *o=BELLE_SIP_OBJECT(obj);
return _belle_sip_object_describe_type(o->vptr);
}
#include <dlfcn.h>
char *belle_sip_object_describe_type_from_name(const char *name){
char *vptr_name;
void *handle;
void *symbol;
handle=dlopen(NULL,RTLD_LAZY);
if (handle==NULL){
belle_sip_error("belle_sip_object_describe_type_from_name: dlopen() failed: %s",dlerror());
return NULL;
}
vptr_name=belle_sip_strdup_printf("%s_vptr",name);
symbol=dlsym(handle,vptr_name);
belle_sip_free(vptr_name);
dlclose(handle);
if (symbol==NULL){
belle_sip_error("belle_sip_object_describe_type_from_name: could not find vptr for type %s",name);
return NULL;
}
return _belle_sip_object_describe_type((belle_sip_object_vptr_t*)symbol);
}
......@@ -63,7 +63,7 @@ void belle_sip_resolver_context_destroy(belle_sip_resolver_context_t *ctx){
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_resolver_context_t);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_resolver_context_t, belle_sip_source_t,belle_sip_resolver_context_destroy, NULL, NULL);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_resolver_context_t, belle_sip_source_t,belle_sip_resolver_context_destroy, NULL, NULL,FALSE);
static int resolver_callback(belle_sip_resolver_context_t *ctx){
ctx->cb(ctx->cb_data, ctx->name, ctx->ai);
......@@ -77,7 +77,7 @@ belle_sip_resolver_context_t *belle_sip_resolver_context_new(){
belle_sip_fatal("pipe() failed: %s",strerror(errno));
}
belle_sip_fd_source_init(&ctx->source,(belle_sip_source_func_t)resolver_callback,ctx,ctx->ctlpipe[0],BELLE_SIP_EVENT_READ,-1);
ctx->source.on_remove=(belle_sip_source_remove_callback_t)belle_sip_resolver_context_destroy;
ctx->source.on_remove=(belle_sip_source_remove_callback_t)belle_sip_object_unref;
return ctx;
}
......
......@@ -97,7 +97,7 @@ int belle_sip_uri_marshal(belle_sip_uri_t* uri, char* buff,unsigned int offset,u
BELLE_SIP_PARSE(uri);
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_uri_t);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_uri_t,belle_sip_parameters_t,belle_sip_uri_destroy,belle_sip_uri_clone,belle_sip_uri_marshal);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_uri_t,belle_sip_parameters_t,belle_sip_uri_destroy,belle_sip_uri_clone,belle_sip_uri_marshal,TRUE);
belle_sip_uri_t* belle_sip_uri_new () {
......
......@@ -47,19 +47,23 @@ BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_channel_t);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_channel_t)=
{
{
BELLE_SIP_VPTR_INIT(belle_sip_channel_t,belle_sip_source_t),
BELLE_SIP_VPTR_INIT(belle_sip_channel_t,belle_sip_source_t,FALSE),
(belle_sip_object_destroy_t)belle_sip_channel_destroy,
NULL, /*clone*/
NULL, /*marshall*/
}
};
void belle_sip_channel_process_data(belle_sip_channel_t *obj,unsigned int revents){
BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_event,obj,revents);
}
static void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_stack_t *stack, const char *peername, int peer_port){
static void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_stack_t *stack, int fd, const char *peername, int peer_port){
obj->peer_name=belle_sip_strdup(peername);
obj->peer_port=peer_port;
obj->peer=NULL;
obj->stack=stack;
belle_sip_fd_source_init((belle_sip_source_t*)obj,(belle_sip_source_func_t)belle_sip_channel_process_data,obj,fd,BELLE_SIP_EVENT_READ|BELLE_SIP_EVENT_ERROR,-1);
}
void belle_sip_channel_add_listener(belle_sip_channel_t *obj, belle_sip_channel_listener_t *l){
......@@ -73,8 +77,8 @@ void belle_sip_channel_remove_listener(belle_sip_channel_t *obj, belle_sip_chann
obj->listeners=belle_sip_list_remove(obj->listeners,l);
}
int belle_sip_channel_matches(const belle_sip_channel_t *obj, const char *peername, int peerport, struct addrinfo *addr){
if (strcmp(peername,obj->peer_name)==0 && peerport==obj->peer_port)
int belle_sip_channel_matches(const belle_sip_channel_t *obj, const char *peername, int peerport, const struct addrinfo *addr){
if (peername && strcmp(peername,obj->peer_name)==0 && peerport==obj->peer_port)
return 1;
if (addr && obj->peer)
return addr->ai_addrlen==obj->peer->ai_addrlen && memcmp(addr->ai_addr,obj->peer->ai_addr,addr->ai_addrlen)==0;
......@@ -222,7 +226,7 @@ BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_udp_channel_t)=
{
{
{
BELLE_SIP_VPTR_INIT(belle_sip_udp_channel_t,belle_sip_channel_t),
BELLE_SIP_VPTR_INIT(belle_sip_udp_channel_t,belle_sip_channel_t,FALSE),
(belle_sip_object_destroy_t)udp_channel_uninit,
NULL,
NULL
......@@ -237,8 +241,27 @@ BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_udp_channel_t)=
belle_sip_channel_t * belle_sip_channel_new_udp(belle_sip_stack_t *stack, int sock, const char *dest, int port){
belle_sip_udp_channel_t *obj=belle_sip_object_new(belle_sip_udp_channel_t);
belle_sip_channel_init((belle_sip_channel_t*)obj,stack,dest,port);
belle_sip_channel_init((belle_sip_channel_t*)obj,stack,sock,dest,port);
obj->sock=sock;
return (belle_sip_channel_t*)obj;
}
belle_sip_channel_t * belle_sip_channel_new_udp_with_addr(belle_sip_stack_t *stack, int sock, const struct addrinfo *peer){
belle_sip_udp_channel_t *obj=belle_sip_object_new(belle_sip_udp_channel_t);
struct addrinfo *ai=belle_sip_new0(struct addrinfo);
char name[NI_MAXHOST];
char serv[NI_MAXSERV];
int err;
obj->sock=sock;
*ai=*peer;
err=getnameinfo(ai->ai_addr,ai->ai_addrlen,name,sizeof(name),serv,sizeof(serv),NI_NUMERICHOST|NI_NUMERICSERV);
if (err!=0){
belle_sip_error("belle_sip_channel_new_udp_with_addr(): getnameinfo() failed: %s",gai_strerror(err));
belle_sip_object_unref(obj);
return NULL;
}
belle_sip_channel_init((belle_sip_channel_t*)obj,stack,sock,name,atoi(serv));
return (belle_sip_channel_t*)obj;
}
......
......@@ -45,9 +45,12 @@ typedef enum belle_sip_channel_state{
typedef struct belle_sip_channel belle_sip_channel_t;
BELLE_SIP_DECLARE_INTERFACE_BEGIN(belle_sip_channel_listener_t)
void (*on_state_changed)(belle_sip_channel_listener_t *obj, belle_sip_channel_t *, belle_sip_channel_state_t state);
void (*on_state_changed)(belle_sip_channel_listener_t *l, belle_sip_channel_t *, belle_sip_channel_state_t state);
int (*on_event)(belle_sip_channel_listener_t *l, belle_sip_channel_t *obj, unsigned revents);
BELLE_SIP_DECLARE_INTERFACE_END
#define BELLE_SIP_CHANNEL_LISTENER(obj) BELLE_SIP_INTERFACE_CAST(obj,belle_sip_channel_listener_t)
struct belle_sip_channel{
belle_sip_source_t base;
belle_sip_stack_t *stack;
......@@ -64,13 +67,15 @@ struct belle_sip_channel{
belle_sip_channel_t * belle_sip_channel_new_udp(belle_sip_stack_t *stack, int sock, const char *peername, int peerport);
belle_sip_channel_t * belle_sip_channel_new_udp_with_addr(belle_sip_stack_t *stack, int sock, const struct addrinfo *ai);
belle_sip_channel_t * belle_sip_channel_new_tcp(belle_sip_stack_t *stack, const char *name, int port);
void belle_sip_channel_add_listener(belle_sip_channel_t *chan, belle_sip_channel_listener_t *l);
void belle_sip_channel_remove_listener(belle_sip_channel_t *obj, belle_sip_channel_listener_t *l);
int belle_sip_channel_matches(const belle_sip_channel_t *obj, const char *peername, int peerport, struct addrinfo *addr);
int belle_sip_channel_matches(const belle_sip_channel_t *obj, const char *peername, int peerport, const struct addrinfo *addr);
int belle_sip_channel_resolve(belle_sip_channel_t *obj);
......@@ -88,6 +93,8 @@ const char * chain_sip_channel_get_transport_name(const belle_sip_channel_t *obj
const struct addrinfo * belle_sip_channel_get_peer(belle_sip_channel_t *obj);
/*just invokes the listeners to process data*/
void belle_sip_channel_process_data(belle_sip_channel_t *obj,unsigned int revents);
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_channel_t,belle_sip_source_t)
const char *transport;
......
......@@ -64,7 +64,7 @@ static void belle_sip_listening_point_remove_channel(belle_sip_listening_point_t
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_listening_point_t);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_listening_point_t)={
{
BELLE_SIP_VPTR_INIT(belle_sip_listening_point_t, belle_sip_object_t),
BELLE_SIP_VPTR_INIT(belle_sip_listening_point_t, belle_sip_object_t,FALSE),
(belle_sip_object_destroy_t)belle_sip_listening_point_uninit,
NULL,
NULL
......@@ -93,36 +93,43 @@ int belle_sip_listening_point_get_well_known_port(const char *transport){
return -1;
}
belle_sip_channel_t *belle_sip_listening_point_get_channel(belle_sip_listening_point_t *lp,const char *peer_name, int peer_port){
static belle_sip_channel_t *_belle_sip_listening_point_get_channel(belle_sip_listening_point_t *lp,const char *peer_name, int peer_port, const struct addrinfo *addr){
belle_sip_list_t *elem;
belle_sip_channel_t *chan;
for(elem=lp->channels;elem!=NULL;elem=elem->next){
chan=(belle_sip_channel_t*)elem->data;
if (belle_sip_channel_matches(chan,peer_name,peer_port,addr)){
return chan;
}
}
return NULL;
}
belle_sip_channel_t *belle_sip_listening_point_get_channel(belle_sip_listening_point_t *lp,const char *peer_name, int peer_port){
struct addrinfo *res=NULL;
struct addrinfo hints={0};
char portstr[20];
belle_sip_channel_t *chan;
hints.ai_flags=AI_NUMERICHOST|AI_NUMERICSERV;
snprintf(portstr,sizeof(portstr),"%i",peer_port);
getaddrinfo(peer_name,portstr,&hints,&res);
for(elem=lp->channels;elem!=NULL;elem=elem->next){
chan=(belle_sip_channel_t*)elem->data;
if (belle_sip_channel_matches(chan,peer_name,peer_port,res)){
if (res) freeaddrinfo(res);
return chan;
}
}
chan=_belle_sip_listening_point_get_channel(lp,peer_name,peer_port,res);
if (res) freeaddrinfo(res);
return NULL;
return chan;
}
struct belle_sip_udp_listening_point{
belle_sip_listening_point_t base;
int sock;
belle_sip_source_t *source;
};
static void belle_sip_udp_listening_point_uninit(belle_sip_udp_listening_point_t *lp){
if (lp->sock!=-1) close(lp->sock);
if (lp->source) belle_sip_main_loop_remove_source(lp->base.stack->ml,lp->source);
}
static belle_sip_channel_t *udp_create_channel(belle_sip_listening_point_t *lp, const char *dest_ip, int port){
......@@ -134,7 +141,7 @@ BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_udp_listening_point_t);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_udp_listening_point_t)={
{
{
BELLE_SIP_VPTR_INIT(belle_sip_udp_listening_point_t, belle_sip_listening_point_t),
BELLE_SIP_VPTR_INIT(belle_sip_udp_listening_point_t, belle_sip_listening_point_t,FALSE),
(belle_sip_object_destroy_t)belle_sip_udp_listening_point_uninit,
NULL,
NULL
......@@ -152,27 +159,69 @@ static int create_udp_socket(const char *addr, int port){
int sock;
char portnum[10];
sock=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
if (sock==-1){
belle_sip_error("Cannot create UDP socket: %s",strerror(errno));
return -1;
}
snprintf(portnum,sizeof(portnum),"%i",port);
hints.ai_family=AF_UNSPEC;
hints.ai_socktype=SOCK_DGRAM;
hints.ai_protocol=IPPROTO_UDP;
hints.ai_flags=AI_NUMERICSERV;
err=getaddrinfo(addr,portnum,&hints,&res);
if (err!=0){
belle_sip_error("getaddrinfo() failed for %s port %i: %s",addr,port,strerror(errno));
close(sock);
belle_sip_error("getaddrinfo() failed for %s port %i: %s",addr,port,gai_strerror(err));
return -1;
}
sock=socket(res->ai_family,res->ai_socktype,res->ai_protocol);
if (sock==-1){
belle_sip_error("Cannot create UDP socket: %s",strerror(errno));
freeaddrinfo(res);
return -1;
}
err=bind(sock,res->ai_addr,res->ai_addrlen);
if (err==-1){
belle_sip_error("udp bind() failed for %s port %i: %s",addr,port,strerror(errno));
close(sock);
freeaddrinfo(res);
return -1;
}
freeaddrinfo(res);
return sock;
}
/*peek data from the master socket to see where it comes from, and dispatch to matching channel.
* If the channel does not exist, create it */
static int on_udp_data(belle_sip_udp_listening_point_t *lp, unsigned int events){
int err;
unsigned char buf[1];
struct sockaddr_storage addr;
socklen_t addrlen=sizeof(addr);
if (events & BELLE_SIP_EVENT_READ){
belle_sip_message("udp_listening_point: data to read.");
err=recvfrom(lp->sock,buf,sizeof(buf),MSG_PEEK,(struct sockaddr*)&addr,&addrlen);
if (err==-1){
belle_sip_error("udp_listening_point: recvfrom() failed: %s",strerror(errno));
}else{
belle_sip_channel_t *chan;
struct addrinfo ai={0};
ai.ai_addr=(struct sockaddr*)&addr;
ai.ai_addrlen=addrlen;
chan=_belle_sip_listening_point_get_channel((belle_sip_listening_point_t*)lp,NULL,0,&ai);
if (chan==NULL){
chan=belle_sip_channel_new_udp_with_addr(lp->base.stack,lp->sock,&ai);
if (chan!=NULL){
belle_sip_message("udp_listening_point: new channel created to %s:%i",chan->peer_name,chan->peer_port);
belle_sip_listening_point_add_channel((belle_sip_listening_point_t*)lp,chan);
}
}
if (chan){
/*notify the channel*/
belle_sip_message("Notifying channel.");
belle_sip_channel_process_data(chan,events);
}
}
}
return BELLE_SIP_CONTINUE;
}
belle_sip_listening_point_t * belle_sip_udp_listening_point_new(belle_sip_stack_t *s, const char *ipaddress, int port){
belle_sip_udp_listening_point_t *lp=belle_sip_object_new(belle_sip_udp_listening_point_t);
belle_sip_listening_point_init((belle_sip_listening_point_t*)lp,s,ipaddress,port);
......@@ -181,6 +230,8 @@ belle_sip_listening_point_t * belle_sip_udp_listening_point_new(belle_sip_stack_
belle_sip_object_unref(lp);
return NULL;
}
lp->source=belle_sip_fd_source_new((belle_sip_source_func_t)on_udp_data,lp,lp->sock,BELLE_SIP_EVENT_READ,-1);
belle_sip_main_loop_add_source(s->ml,lp->source);
return BELLE_SIP_LISTENING_POINT(lp);
}
......