/* belle-sip - SIP (RFC3261) library. Copyright (C) 2010 Belledonne Communications SARL This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef belle_utils_h #define belle_utils_h #include #include #include #include #include #include #ifndef WIN32 #include #include #include #endif /* include all public headers*/ #include "belle-sip/belle-sip.h" typedef void (*belle_sip_object_destroy_t)(belle_sip_object_t*); typedef void (*belle_sip_object_clone_t)(belle_sip_object_t* obj, const belle_sip_object_t *orig); 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; const char *type_name; int initially_unowned; struct _belle_sip_object_vptr *parent; 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; }; typedef struct _belle_sip_object_vptr belle_sip_object_vptr_t; extern belle_sip_object_vptr_t belle_sip_object_t_vptr; #define BELLE_SIP_OBJECT_VPTR_NAME(object_type) object_type##_vptr #define BELLE_SIP_OBJECT_VPTR_TYPE(object_type) object_type##_vptr_t #define BELLE_SIP_DECLARE_VPTR(object_type) \ typedef belle_sip_object_vptr_t BELLE_SIP_OBJECT_VPTR_TYPE(object_type);\ extern BELLE_SIP_OBJECT_VPTR_TYPE(object_type) BELLE_SIP_OBJECT_VPTR_NAME(object_type); #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) #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_desc_t**)object_type##interfaces_table #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,unowned), \ (belle_sip_object_destroy_t)destroy, \ (belle_sip_object_clone_t)clone, \ (belle_sip_object_marshal_t)marshal\ } #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),\ #interface_name }, #define BELLE_SIP_IMPLEMENT_INTERFACE_END }; #define BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(object_type)\ static belle_sip_interface_desc_t * object_type##interfaces_table[]={\ NULL \ } #define BELLE_SIP_DECLARE_IMPLEMENTED_INTERFACES_1(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_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 \ } /*etc*/ #define BELLE_SIP_INTERFACE_GET_METHODS(obj,interface) \ ((BELLE_SIP_INTERFACE_METHODS_TYPE(interface)*)belle_sip_object_get_interface_methods((belle_sip_object_t*)obj,BELLE_SIP_INTERFACE_ID(interface))) #define __BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name) \ if (list!=NULL) {\ const belle_sip_list_t *__elem=list;\ do{\ interface_name *__obj=(interface_name*)__elem->data;\ BELLE_SIP_INTERFACE_GET_METHODS(__obj,interface_name)-> #define __BELLE_SIP_INVOKE_LISTENER_END \ __elem=__elem->next;\ }while(__elem!=NULL);\ } #define BELLE_SIP_INVOKE_LISTENERS_VOID(list,interface_name,method) \ __BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name)\ method(__obj);\ __BELLE_SIP_INVOKE_LISTENER_END #define BELLE_SIP_INVOKE_LISTENERS_ARG(list,interface_name,method,arg) \ __BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name)\ method(__obj,arg);\ __BELLE_SIP_INVOKE_LISTENER_END #define BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(list,interface_name,method,arg1,arg2) \ __BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name)\ method(__obj,arg1,arg2);\ __BELLE_SIP_INVOKE_LISTENER_END #define BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2_ARG3(list,interface_name,method,arg1,arg2,arg3) \ __BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name)\ method(__obj,arg1,arg2,arg3);\ __BELLE_SIP_INVOKE_LISTENER_END typedef struct weak_ref{ struct weak_ref *next; belle_sip_object_destroy_notify_t notify; void *userpointer; }weak_ref_t; struct _belle_sip_object{ belle_sip_object_vptr_t *vptr; size_t size; int ref; char* name; weak_ref_t *weak_refs; }; 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)) #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*/ /*list of all vptrs (classes) used in belle-sip*/ BELLE_SIP_DECLARE_VPTR(belle_sip_object_t); BELLE_SIP_DECLARE_VPTR(belle_sip_stack_t); BELLE_SIP_DECLARE_VPTR(belle_sip_datagram_listening_point_t); BELLE_SIP_DECLARE_VPTR(belle_sip_provider_t); BELLE_SIP_DECLARE_VPTR(belle_sip_main_loop_t); BELLE_SIP_DECLARE_VPTR(belle_sip_source_t); BELLE_SIP_DECLARE_VPTR(belle_sip_resolver_context_t); BELLE_SIP_DECLARE_VPTR(belle_sip_transaction_t); BELLE_SIP_DECLARE_VPTR(belle_sip_server_transaction_t); BELLE_SIP_DECLARE_VPTR(belle_sip_client_transaction_t); BELLE_SIP_DECLARE_VPTR(belle_sip_dialog_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_address_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_contact_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_from_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_to_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_via_t); BELLE_SIP_DECLARE_VPTR(belle_sip_uri_t); BELLE_SIP_DECLARE_VPTR(belle_sip_message_t); BELLE_SIP_DECLARE_VPTR(belle_sip_request_t); BELLE_SIP_DECLARE_VPTR(belle_sip_response_t); BELLE_SIP_DECLARE_VPTR(belle_sip_parameters_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_call_id_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_cseq_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_content_type_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_route_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_record_route_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_user_agent_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_content_length_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_extension_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_authorization_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_www_authenticate_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_proxy_authorization_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_max_forwards_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_expires_t); BELLE_SIP_DECLARE_VPTR(belle_sip_header_allow_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_attribute_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_bandwidth_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_connection_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_email_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_info_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_key_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_media_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_media_description_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_origin_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_phone_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_repeate_time_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_session_description_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_session_name_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_time_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_time_description_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_uri_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_version_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_base_description_t); BELLE_SIP_DECLARE_VPTR(belle_sdp_mime_parameter_t); typedef void (*belle_sip_source_remove_callback_t)(belle_sip_source_t *); struct belle_sip_source{ belle_sip_object_t base; belle_sip_list_t node; unsigned long id; int fd; unsigned int events; int timeout; void *data; uint64_t expire_ms; int index; /* index in pollfd table */ belle_sip_source_func_t notify; belle_sip_source_remove_callback_t on_remove; unsigned char cancelled; unsigned char expired; }; void belle_sip_fd_source_init(belle_sip_source_t *s, belle_sip_source_func_t func, void *data, int fd, unsigned int events, unsigned int timeout_value_ms); #define belle_list_next(elem) ((elem)->next) /* include private headers */ #include "channel.h" #ifdef __cplusplus extern "C"{ #endif #define belle_sip_new(type) (type*)belle_sip_malloc(sizeof(type)) #define belle_sip_new0(type) (type*)belle_sip_malloc0(sizeof(type)) belle_sip_list_t *belle_sip_list_new(void *data); belle_sip_list_t* belle_sip_list_append_link(belle_sip_list_t* elem,belle_sip_list_t *new_elem); belle_sip_list_t *belle_sip_list_find_custom(belle_sip_list_t *list, belle_sip_compare_func compare_func, const void *user_data); belle_sip_list_t *belle_sip_list_delete_custom(belle_sip_list_t *list, belle_sip_compare_func compare_func, const void *user_data); belle_sip_list_t * belle_sip_list_free(belle_sip_list_t *list); #define belle_sip_list_next(elem) ((elem)->next) extern belle_sip_log_function_t belle_sip_logv_out; extern unsigned int __belle_sip_log_mask; #define belle_sip_log_level_enabled(level) (__belle_sip_log_mask & (level)) #if !defined(WIN32) && !defined(_WIN32_WCE) #define belle_sip_logv(level,fmt,args) \ {\ if (belle_sip_logv_out!=NULL && belle_sip_log_level_enabled(level)) \ belle_sip_logv_out(level,fmt,args);\ if ((level)==BELLE_SIP_FATAL) abort();\ }while(0) #else void belle_sip_logv(int level, const char *fmt, va_list args); #endif #ifdef BELLE_SIP_DEBUG_MODE static inline void belle_sip_debug(const char *fmt,...) { va_list args; va_start (args, fmt); belle_sip_logv(BELLE_SIP_DEBUG, fmt, args); va_end (args); } #else #define belle_sip_debug(...) #endif #ifdef BELLE_SIP_NOMESSAGE_MODE #define belle_sip_log(...) #define belle_sip_message(...) #define belle_sip_warning(...) #else static inline void belle_sip_log(belle_sip_log_level lev, const char *fmt,...){ va_list args; va_start (args, fmt); belle_sip_logv(lev, fmt, args); va_end (args); } static inline void belle_sip_message(const char *fmt,...) { va_list args; va_start (args, fmt); belle_sip_logv(BELLE_SIP_MESSAGE, fmt, args); va_end (args); } static inline void belle_sip_warning(const char *fmt,...) { va_list args; va_start (args, fmt); belle_sip_logv(BELLE_SIP_WARNING, fmt, args); va_end (args); } #endif static inline void belle_sip_error(const char *fmt,...) { va_list args; va_start (args, fmt); belle_sip_logv(BELLE_SIP_ERROR, fmt, args); va_end (args); } static inline void belle_sip_fatal(const char *fmt,...) { va_list args; va_start (args, fmt); belle_sip_logv(BELLE_SIP_FATAL, fmt, args); va_end (args); } #undef MIN #define MIN(a,b) ((a)>(b) ? (b) : (a)) #undef MAX #define MAX(a,b) ((a)>(b) ? (a) : (b)) char * belle_sip_concat (const char *str, ...); uint64_t belle_sip_time_ms(void); unsigned int belle_sip_random(void); char *belle_sip_strdup_printf(const char *fmt,...); /*parameters accessors*/ #define GET_SET_STRING(object_type,attribute) \ const char* object_type##_get_##attribute (const object_type##_t* obj) {\ return obj->attribute;\ }\ void object_type##_set_##attribute (object_type##_t* obj,const char* value) {\ if (obj->attribute != NULL) free((void*)obj->attribute);\ obj->attribute=malloc(strlen(value)+1);\ strcpy((char*)(obj->attribute),value);\ } #define GET_SET_STRING_PARAM(object_type,attribute) GET_SET_STRING_PARAM2(object_type,attribute,attribute) #define GET_SET_STRING_PARAM2(object_type,attribute,func_name) \ const char* object_type##_get_##func_name (const object_type##_t* obj) {\ const char* l_value = belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(obj),#attribute);\ if (l_value == NULL) { \ /*belle_sip_warning("cannot find parameters [%s]",#attribute);*/\ return NULL;\ }\ return l_value;\ }\ void object_type##_set_##func_name (object_type##_t* obj,const char* value) {\ belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(obj),#attribute,value);\ } #define CLONE_STRING(object_type,attribute,dest,src) \ if ( object_type##_get_##attribute (src)) {\ object_type##_set_##attribute(dest,object_type##_get_##attribute(src));\ } #define GET_SET_INT(object_type,attribute,type) GET_SET_INT_PRIVATE(object_type,attribute,type,) #define GET_SET_INT_PRIVATE(object_type,attribute,type,set_prefix) \ type object_type##_get_##attribute (const object_type##_t* obj) {\ return obj->attribute;\ }\ void set_prefix##object_type##_set_##attribute (object_type##_t* obj,type value) {\ obj->attribute=value;\ } #define GET_SET_INT_PARAM(object_type,attribute,type) GET_SET_INT_PARAM_PRIVATE(object_type,attribute,type,) #define GET_SET_INT_PARAM2(object_type,attribute,type,func_name) GET_SET_INT_PARAM_PRIVATE2(object_type,attribute,type,,func_name) #define ATO_(type,value) ATO_##type(value) #define ATO_int(value) atoi(value) #define ATO_float(value) strtof(value,NULL) #define FORMAT_(type) FORMAT_##type #define FORMAT_int "%i" #define FORMAT_float "%f" #define GET_SET_INT_PARAM_PRIVATE(object_type,attribute,type,set_prefix) GET_SET_INT_PARAM_PRIVATE2(object_type,attribute,type,set_prefix,attribute) #define GET_SET_INT_PARAM_PRIVATE2(object_type,attribute,type,set_prefix,func_name) \ type object_type##_get_##func_name (const object_type##_t* obj) {\ const char* l_value = belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(obj),#attribute);\ if (l_value == NULL) { \ belle_sip_error("cannot find parameters [%s]",#attribute);\ return -1;\ }\ return ATO_(type,l_value);\ }\ void set_prefix##object_type##_set_##func_name (object_type##_t* obj,type value) {\ char l_str_value[16];\ if (value == -1) { \ belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(obj),#attribute);\ return;\ }\ snprintf(l_str_value,16,FORMAT_(type),value);\ belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(obj),#attribute,(const char*)l_str_value);\ } #define GET_SET_BOOL(object_type,attribute,getter) \ unsigned int object_type##_##getter##_##attribute (const object_type##_t* obj) {\ return obj->attribute;\ }\ void object_type##_set_##attribute (object_type##_t* obj,unsigned int value) {\ obj->attribute=value;\ } #define GET_SET_BOOL_PARAM2(object_type,attribute,getter,func_name) \ unsigned int object_type##_##getter##_##func_name (const object_type##_t* obj) {\ return belle_sip_parameters_is_parameter(BELLE_SIP_PARAMETERS(obj),#attribute);\ }\ void object_type##_set_##func_name (object_type##_t* obj,unsigned int value) {\ belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(obj),#attribute,NULL);\ } #define BELLE_SIP_PARSE(object_type) \ belle_sip_##object_type##_t* belle_sip_##object_type##_parse (const char* value) { \ pANTLR3_INPUT_STREAM input; \ pbelle_sip_messageLexer lex; \ pANTLR3_COMMON_TOKEN_STREAM tokens; \ pbelle_sip_messageParser parser; \ input = antlr3NewAsciiStringCopyStream (\ (pANTLR3_UINT8)value,\ (ANTLR3_UINT32)strlen(value),\ NULL);\ lex = belle_sip_messageLexerNew (input);\ tokens = antlr3CommonTokenStreamSourceNew (ANTLR3_SIZE_HINT, TOKENSOURCE(lex));\ parser = belle_sip_messageParserNew (tokens);\ belle_sip_##object_type##_t* l_parsed_object = parser->object_type(parser);\ parser ->free(parser);\ tokens ->free(tokens);\ lex ->free(lex);\ input ->close(input);\ if (l_parsed_object == NULL) belle_sip_error(#object_type" parser error for [%s]",value);\ return l_parsed_object;\ } #define BELLE_SIP_NEW(object_type,super_type) BELLE_SIP_NEW_HEADER(object_type,super_type,NULL) #define BELLE_SIP_NEW_HEADER(object_type,super_type,name) BELLE_SIP_NEW_HEADER_INIT(object_type,super_type,name,header) #define BELLE_SIP_NEW_HEADER_INIT(object_type,super_type,name,init_type) \ BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_##object_type##_t); \ BELLE_SIP_INSTANCIATE_VPTR( belle_sip_##object_type##_t\ , belle_sip_##super_type##_t\ , belle_sip_##object_type##_destroy\ , belle_sip_##object_type##_clone\ , 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(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);\ return l_object;\ } typedef struct belle_sip_param_pair_t { int ref; char* name; char* value; } belle_sip_param_pair_t; belle_sip_param_pair_t* belle_sip_param_pair_new(const char* name,const char* value); void belle_sip_param_pair_destroy(belle_sip_param_pair_t* pair) ; int belle_sip_param_pair_comp_func(const belle_sip_param_pair_t *a, const char*b) ; belle_sip_param_pair_t* belle_sip_param_pair_ref(belle_sip_param_pair_t* obj); void belle_sip_param_pair_unref(belle_sip_param_pair_t* obj); void belle_sip_header_address_set_quoted_displayname(belle_sip_header_address_t* address,const char* value); /*calss header*/ struct _belle_sip_header { belle_sip_object_t base; belle_sip_header_t* next; const char* name; }; void belle_sip_header_set_next(belle_sip_header_t* header,belle_sip_header_t* next); belle_sip_header_t* belle_sip_header_get_next(const belle_sip_header_t* headers); void belle_sip_header_init(belle_sip_header_t* obj); /*class parameters*/ struct _belle_sip_parameters { belle_sip_header_t base; belle_sip_list_t* param_list; belle_sip_list_t* paramnames_list; }; void belle_sip_parameters_init(belle_sip_parameters_t *obj); /* * Listening points */ typedef struct belle_sip_udp_listening_point belle_sip_udp_listening_point_t; BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_listening_point_t,belle_sip_object_t) const char *transport; belle_sip_channel_t * (*create_channel)(belle_sip_listening_point_t *,const char *dest_ip, int port); BELLE_SIP_DECLARE_CUSTOM_VPTR_END BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_udp_listening_point_t,belle_sip_listening_point_t) BELLE_SIP_DECLARE_CUSTOM_VPTR_END #define BELLE_SIP_LISTENING_POINT(obj) BELLE_SIP_CAST(obj,belle_sip_listening_point_t) #define BELLE_SIP_UDP_LISTENING_POINT(obj) BELLE_SIP_CAST(obj,belle_sip_udp_listening_point_t) belle_sip_listening_point_t * belle_sip_udp_listening_point_new(belle_sip_stack_t *s, const char *ipaddress, int port); belle_sip_channel_t *belle_sip_listening_point_get_channel(belle_sip_listening_point_t *ip, const char *dest, int port); belle_sip_channel_t *belle_sip_listening_point_create_channel(belle_sip_listening_point_t *ip, const char *dest, int port); int belle_sip_listening_point_get_well_known_port(const char *transport); /* belle_sip_stack_t */ struct belle_sip_stack{ belle_sip_object_t base; belle_sip_main_loop_t *ml; belle_sip_list_t *lp;/*list of listening points*/ belle_sip_timer_config_t timer_config; }; void belle_sip_stack_get_next_hop(belle_sip_stack_t *stack, belle_sip_request_t *req, belle_sip_hop_t *hop); const belle_sip_timer_config_t *belle_sip_stack_get_timer_config(const belle_sip_stack_t *stack); /* belle_sip_provider_t */ struct belle_sip_provider{ belle_sip_object_t base; belle_sip_stack_t *stack; belle_sip_list_t *lps; /*listening points*/ belle_sip_list_t *listeners; }; 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); belle_sip_channel_t * belle_sip_provider_get_channel(belle_sip_provider_t *p, const char *name, int port, const char *transport); typedef struct listener_ctx{ belle_sip_listener_t *listener; void *data; }listener_ctx_t; #define BELLE_SIP_PROVIDER_INVOKE_LISTENERS(provider,callback,event) \ BELLE_SIP_INVOKE_LISTENERS_ARG(((provider)->listeners),belle_sip_listener_t,callback,(event)) /* 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; 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); /* belle_sip_response_t */ void belle_sip_response_get_return_hop(belle_sip_response_t *msg, belle_sip_hop_t *hop); #define IS_TOKEN(token) \ (INPUT->toStringTT(INPUT,LT(1),LT(strlen(#token)))->chars ?\ strcmp(#token,(const char*)(INPUT->toStringTT(INPUT,LT(1),LT(strlen(#token)))->chars)) == 0:0) char* _belle_sip_str_dup_and_unquote_string(const char* quoted_string); /********************************************************* * SDP */ #define BELLE_SDP_PARSE(object_type) \ belle_sdp_##object_type##_t* belle_sdp_##object_type##_parse (const char* value) { \ pANTLR3_INPUT_STREAM input; \ pbelle_sdpLexer lex; \ pANTLR3_COMMON_TOKEN_STREAM tokens; \ pbelle_sdpParser parser; \ input = antlr3NewAsciiStringCopyStream (\ (pANTLR3_UINT8)value,\ (ANTLR3_UINT32)strlen(value),\ NULL);\ lex = belle_sdpLexerNew (input);\ tokens = antlr3CommonTokenStreamSourceNew (ANTLR3_SIZE_HINT, TOKENSOURCE(lex));\ parser = belle_sdpParserNew (tokens);\ belle_sdp_##object_type##_t* l_parsed_object = parser->object_type(parser).ret;\ parser ->free(parser);\ tokens ->free(tokens);\ lex ->free(lex);\ input ->close(input);\ if (l_parsed_object == NULL) belle_sip_error(#object_type" parser error for [%s]",value);\ return l_parsed_object;\ } #define BELLE_SDP_NEW(object_type,super_type) \ BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sdp_##object_type##_t); \ BELLE_SIP_INSTANCIATE_VPTR( belle_sdp_##object_type##_t\ , super_type##_t\ , belle_sdp_##object_type##_destroy\ , belle_sdp_##object_type##_clone\ , 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); \ return l_object;\ } #define BELLE_SDP_NEW_WITH_CTR(object_type,super_type) \ BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sdp_##object_type##_t); \ BELLE_SIP_INSTANCIATE_VPTR( belle_sdp_##object_type##_t\ , super_type##_t\ , belle_sdp_##object_type##_destroy\ , belle_sdp_##object_type##_clone\ , 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); \ belle_sdp_##object_type##_init(l_object); \ return l_object;\ } #ifdef __cplusplus } #endif /*include private headers */ #include "belle_sip_resolver.h" #define BELLE_SIP_SOCKET_TIMEOUT 30000 #endif