/*
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 2 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 all public headers*/
#include "belle-sip/belle-sip.h"
#include "port.h"
#ifdef HAVE_CONFIG_H
#ifdef PACKAGE
#undef PACKAGE
#endif
#ifdef PACKAGE_BUGREPORT
#undef PACKAGE_BUGREPORT
#endif
#ifdef PACKAGE_NAME
#undef PACKAGE_NAME
#endif
#ifdef PACKAGE_STRING
#undef PACKAGE_STRING
#endif
#ifdef PACKAGE_TARNAME
#undef PACKAGE_TARNAME
#endif
#ifdef VERSION
#undef VERSION
#endif
#ifdef PACKAGE_VERSION
#undef PACKAGE_VERSION
#endif
#include "config.h"
#else
#ifndef PACKAGE_VERSION
#error "PACKAGE_VERSION must be defined and equal to the VERSION file included in the belle-sip repository"
#endif
#endif
/*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,method) \
if (list!=NULL) {\
belle_sip_list_t *__copy=belle_sip_list_copy_with_data((list), (void* (*)(void*))belle_sip_object_ref);\
const belle_sip_list_t *__elem=__copy;\
do{\
void *__method;\
interface_name *__obj=(interface_name*)__elem->data;\
__method=BELLE_SIP_INTERFACE_GET_METHODS(__obj,interface_name)->method;\
if (__method) BELLE_SIP_INTERFACE_GET_METHODS(__obj,interface_name)->
#define __BELLE_SIP_INVOKE_LISTENER_END \
__elem=__elem->next;\
}while(__elem!=NULL);\
belle_sip_list_free_with_data(__copy,belle_sip_object_unref);\
}
#define BELLE_SIP_INVOKE_LISTENERS_VOID(list,interface_name,method) \
__BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name,method)\
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)\
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)\
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
#define BELLE_SIP_INVOKE_LISTENER_ARG(listener,interface_name,method,arg) \
((BELLE_SIP_INTERFACE_GET_METHODS((listener),interface_name)->method!=NULL) ? \
BELLE_SIP_INTERFACE_GET_METHODS((listener),interface_name)->method(listener,(arg)) : 0 )
typedef struct weak_ref{
struct weak_ref *next;
belle_sip_object_destroy_notify_t notify;
void *userpointer;
}weak_ref_t;
void *belle_sip_object_get_interface_methods(belle_sip_object_t *obj, belle_sip_interface_id_t ifid);
/*used internally by unref()*/
void belle_sip_object_delete(void *obj);
void belle_sip_object_pool_add(belle_sip_object_pool_t *pool, belle_sip_object_t *obj);
void belle_sip_object_pool_remove(belle_sip_object_pool_t *pool, belle_sip_object_t *obj);
#define belle_sip_object_init(obj) /*nothing*/
/*list of all vptrs (classes) used in belle-sip*/
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_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_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_raw_attribute_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_repeate_time_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_rtcp_fb_attribute_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_rtcp_xr_attribute_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);
BELLE_SIP_DECLARE_VPTR(belle_sip_refresher_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_subscription_state_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_service_route_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_refer_to_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_referred_by_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_replaces_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_date_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_hop_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_object_pool_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_p_preferred_identity_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_privacy_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_certificates_chain_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_signing_key_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_dns_srv_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_dict_t)
BELLE_SIP_DECLARE_VPTR(belle_http_provider_t);
BELLE_SIP_DECLARE_VPTR(belle_http_channel_context_t);
BELLE_SIP_DECLARE_VPTR(belle_http_request_t);
BELLE_SIP_DECLARE_VPTR(belle_http_response_t);
BELLE_SIP_DECLARE_VPTR(belle_generic_uri_t);
BELLE_SIP_DECLARE_VPTR(belle_http_callbacks_t);
BELLE_SIP_DECLARE_VPTR(belle_tls_verify_policy_t);
BELLE_SIP_DECLARE_VPTR(belle_http_header_authorization_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_event_t);
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_resolver_context_t,belle_sip_source_t)
void (*cancel)(belle_sip_resolver_context_t *);
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_simple_resolver_context_t,belle_sip_resolver_context_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_combined_resolver_context_t,belle_sip_resolver_context_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_dual_resolver_context_t,belle_sip_resolver_context_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
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;
belle_sip_fd_t fd;
unsigned short events,revents;
#ifdef WIN32
unsigned short armed_events;
unsigned short pad;
#endif
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;
belle_sip_socket_t sock;
unsigned char cancelled;
unsigned char expired;
unsigned char oneshot;
unsigned char notify_required; /*for testing purpose, use to ask for being scheduled*/
};
void belle_sip_socket_source_init(belle_sip_source_t *s, belle_sip_source_func_t func, void *data, belle_sip_socket_t fd, unsigned int events, unsigned int timeout_value_ms);
void belle_sip_fd_source_init(belle_sip_source_t *s, belle_sip_source_func_t func, void *data, belle_sip_fd_t fd, unsigned int events, unsigned int timeout_value_ms);
void belle_sip_source_uninit(belle_sip_source_t *s);
void belle_sip_source_set_notify(belle_sip_source_t *s, belle_sip_source_func_t func);
/* include private headers */
#include "channel.h"
#define belle_sip_new(type) (type*)belle_sip_malloc(sizeof(type))
#define belle_sip_new0(type) (type*)belle_sip_malloc0(sizeof(type))
#define belle_list_next(elem) ((elem)->next)
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_delete_custom(belle_sip_list_t *list, belle_sip_compare_func compare_func, const void *user_data);
belle_sip_list_t* _belle_sip_list_remove(belle_sip_list_t* first, void *data, int warn_if_not_found);
#define belle_sip_list_next(elem) ((elem)->next)
/* dictionary */
struct belle_sip_dict {
belle_sip_object_t base;
};
#undef MIN
#define MIN(a,b) ((a)>(b) ? (b) : (a))
#undef MAX
#define MAX(a,b) ((a)>(b) ? (a) : (b))
BELLESIP_INTERNAL_EXPORT char * belle_sip_concat (const char *str, ...);
/*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) {\
const char* previous_value = obj->attribute; /*preserve if same value re-asigned*/ \
if (value) {\
obj->attribute=belle_sip_strdup(value); \
} else obj->attribute=NULL;\
if (previous_value != NULL) belle_sip_free((void*)previous_value);\
}
/*#define GET_SET_STRING_PARAM_NULL_ALLOWED(object_type,attribute) \
GET_STRING_PARAM2(object_type,attribute,attribute) \
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 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) \
GET_STRING_PARAM2(object_type,attribute,func_name) \
void object_type##_set_##func_name (object_type##_t* obj,const char* value) {\
if (belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(obj),#attribute) && !value) {\
belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(obj),#attribute); \
} else \
belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(obj),#attribute,value);\
}
#define GET_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;\
}
#define DESTROY_STRING(object,attribute) if (object->attribute) belle_sip_free((void*)object->attribute);
#define CLONE_STRING_GENERIC(object_type_src,object_type_dest,attribute,dest,src) \
if ( object_type_src##_get_##attribute (src)) {\
object_type_dest##_set_##attribute(dest,object_type_src##_get_##attribute(src));\
}
#define CLONE_STRING(object_type,attribute,dest,src) CLONE_STRING_GENERIC(object_type,object_type,attribute,dest,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) (float)strtod(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_has_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);\
}
#ifdef HAVE_ANTLR_STRING_STREAM_NEW
#define ANTLR_STREAM_NEW(object_type, value,length) \
antlr3StringStreamNew((pANTLR3_UINT8)value,ANTLR3_ENC_8BIT,(ANTLR3_UINT32)length,(pANTLR3_UINT8)#object_type)
#else
#define ANTLR_STREAM_NEW(object_type, value, length) \
antlr3NewAsciiStringCopyStream((pANTLR3_UINT8)value,(ANTLR3_UINT32)length,NULL)
#endif /*HAVE_ANTLR_STRING_STREAM_NEW*/
#define BELLE_PARSE(parser_name, object_type_prefix, object_type) \
object_type_prefix##object_type##_t* object_type_prefix##object_type##_parse (const char* value) { \
pANTLR3_INPUT_STREAM input; \
pbelle_sip_messageLexer lex; \
pANTLR3_COMMON_TOKEN_STREAM tokens; \
p##parser_name parser; \
object_type_prefix##object_type##_t* l_parsed_object; \
input = ANTLR_STREAM_NEW(object_type,value,strlen(value));\
lex = belle_sip_messageLexerNew (input);\
tokens = antlr3CommonTokenStreamSourceNew (ANTLR3_SIZE_HINT, TOKENSOURCE(lex));\
parser = parser_name##New (tokens);\
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_PARSE(object_type) BELLE_PARSE(belle_sip_messageParser,belle_sip_,object_type)
#define BELLE_NEW(object_type,super_type) \
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(object_type##_t); \
BELLE_SIP_INSTANCIATE_VPTR( object_type##_t\
, super_type##_t\
, object_type##_destroy\
, object_type##_clone\
, object_type##_marshal, TRUE); \
object_type##_t* object_type##_new () { \
object_type##_t* l_object = belle_sip_object_new(object_type##_t);\
super_type##_init((super_type##_t*)l_object); \
object_type##_init((object_type##_t*) l_object); \
return l_object;\
}
#define BELLE_SIP_NEW(object_type,super_type) BELLE_NEW (belle_sip_##object_type, belle_sip_##super_type)
#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;\
}
struct belle_sip_param_pair {
int ref;
char* name;
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) ;
int belle_sip_param_pair_case_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);
/*calss header*/
struct _belle_sip_header {
belle_sip_object_t base;
belle_sip_header_t* next;
char *name;
char *unparsed_value;
};
void belle_sip_response_fill_for_dialog(belle_sip_response_t *obj, belle_sip_request_t *req);
void belle_sip_util_copy_headers(belle_sip_message_t *orig, belle_sip_message_t *dest, const char*header, int multiple);
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
*/
#include "listeningpoint_internal.h"
struct belle_sip_hop{
belle_sip_object_t base;
char *cname;
char *host;
char *transport;
int port;
};
/*
belle_sip_stack_t
*/
struct belle_sip_stack{
belle_sip_object_t base;
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*/
int resolver_tx_delay; /*used to simulate network transmission delay, for tests*/
int resolver_send_error; /* used to simulate network error*/
int dscp;
char *dns_user_hosts_file; /* used to load additional hosts file for tests */
char *dns_resolv_conf; /*used to load custom resolv.conf, for tests*/
unsigned char dns_srv_enabled;
};
belle_sip_hop_t* belle_sip_hop_new(const char* transport, const char *cname, const char* host,int port);
belle_sip_hop_t* belle_sip_hop_new_from_uri(const belle_sip_uri_t *uri);
belle_sip_hop_t* belle_sip_hop_new_from_generic_uri(const belle_generic_uri_t *uri);
belle_sip_hop_t * belle_sip_stack_get_next_hop(belle_sip_stack_t *stack, belle_sip_request_t *req);
/*
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_list_t *internal_listeners; /*for transaction internaly managed by belle-sip. I.E by refreshers*/
belle_sip_list_t *client_transactions;
belle_sip_list_t *server_transactions;
belle_sip_list_t *dialogs;
belle_sip_list_t *auth_contexts;
unsigned char rport_enabled; /*0 if rport should not be set in via header*/
unsigned char nat_helper;
unsigned char unconditional_answer_enabled;
};
BELLESIP_INTERNAL_EXPORT belle_sip_provider_t *belle_sip_provider_new(belle_sip_stack_t *s, belle_sip_listening_point_t *lp);
void belle_sip_provider_add_client_transaction(belle_sip_provider_t *prov, belle_sip_client_transaction_t *t);
belle_sip_client_transaction_t *belle_sip_provider_find_matching_client_transaction(belle_sip_provider_t *prov, belle_sip_response_t *resp);
void belle_sip_provider_remove_client_transaction(belle_sip_provider_t *prov, belle_sip_client_transaction_t *t);
void belle_sip_provider_add_server_transaction(belle_sip_provider_t *prov, belle_sip_server_transaction_t *t);
BELLESIP_INTERNAL_EXPORT belle_sip_server_transaction_t * belle_sip_provider_find_matching_server_transaction(belle_sip_provider_t *prov,belle_sip_request_t *req);
void belle_sip_provider_remove_server_transaction(belle_sip_provider_t *prov, belle_sip_server_transaction_t *t);
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 belle_sip_hop_t *hop);
void belle_sip_provider_add_dialog(belle_sip_provider_t *prov, belle_sip_dialog_t *dialog);
void belle_sip_provider_remove_dialog(belle_sip_provider_t *prov, belle_sip_dialog_t *dialog);
void belle_sip_provider_release_channel(belle_sip_provider_t *p, belle_sip_channel_t *chan);
void belle_sip_provider_add_internal_sip_listener(belle_sip_provider_t *p, belle_sip_listener_t *l, int prepend);
void belle_sip_provider_remove_internal_sip_listener(belle_sip_provider_t *p, belle_sip_listener_t *l);
belle_sip_client_transaction_t * belle_sip_provider_find_matching_client_transaction_from_req(belle_sip_provider_t *prov, belle_sip_request_t *req);
belle_sip_dialog_t *belle_sip_provider_find_dialog_from_message(belle_sip_provider_t *prov, belle_sip_message_t *msg, int as_uas);
/*for testing purpose only:*/
BELLESIP_INTERNAL_EXPORT void belle_sip_provider_dispatch_message(belle_sip_provider_t *prov, belle_sip_message_t *msg);
typedef struct listener_ctx{
belle_sip_listener_t *listener;
void *data;
}listener_ctx_t;
#define BELLE_SIP_PROVIDER_INVOKE_LISTENERS_FOR_TRANSACTION(t,callback,event) \
BELLE_SIP_PROVIDER_INVOKE_LISTENERS((t)->is_internal?(t)->provider->internal_listeners:(t)->provider->listeners,callback,event)
#define BELLE_SIP_PROVIDER_INVOKE_LISTENERS(listeners,callback,event) \
BELLE_SIP_INVOKE_LISTENERS_ARG((listeners),belle_sip_listener_t,callback,(event))
/*
* http provider
*/
belle_http_provider_t *belle_http_provider_new(belle_sip_stack_t *s, const char *bind_ip);
/*
* SIP and http messages
**/
#define BELLESIP_MULTIPART_BOUNDARY "---------------------------14737809831466499882746641449"
void belle_sip_message_init(belle_sip_message_t *message);
struct _belle_sip_message {
belle_sip_object_t base;
belle_sip_list_t* header_list;
belle_sip_body_handler_t *body_handler;
};
struct _belle_sip_request {
belle_sip_message_t base;
char* method;
belle_sip_uri_t* uri;
belle_generic_uri_t *absolute_uri;
belle_sip_dialog_t *dialog;/*set if request was created by a dialog to avoid to search in dialog list*/
char *rfc2543_branch; /*computed 'branch' id in case we receive this request from an old RFC2543 stack*/
unsigned char dialog_queued;
};
/** HTTP request**/
struct belle_http_request{
belle_sip_message_t base;
belle_generic_uri_t *req_uri;
char* method;
belle_http_request_listener_t *listener;
belle_generic_uri_t *orig_uri;/*original uri before removing host and user/passwd*/
belle_http_response_t *response;
belle_sip_channel_t *channel;
int auth_attempt_count;
int background_task_id;
int cancelled;
};
void belle_http_request_set_listener(belle_http_request_t *req, belle_http_request_listener_t *l);
void belle_http_request_set_channel(belle_http_request_t *req, belle_sip_channel_t *chan);
void belle_http_request_set_response(belle_http_request_t *req, belle_http_response_t *resp);
/*
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 *last_response;
belle_sip_channel_t *channel;
belle_sip_dialog_t *dialog;
char *branch_id;
belle_sip_transaction_state_t state;
void *appdata;
unsigned char is_internal;
unsigned char timed_out;
unsigned char sent_by_dialog_queue;
};
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_transaction_t,belle_sip_object_t)
void (*on_terminate)(belle_sip_transaction_t *obj);
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
static BELLESIP_INLINE const belle_sip_timer_config_t * belle_sip_transaction_get_timer_config(belle_sip_transaction_t *obj){
return belle_sip_stack_get_timer_config(obj->provider->stack);
}
static BELLESIP_INLINE void belle_sip_transaction_start_timer(belle_sip_transaction_t *obj, belle_sip_source_t *timer){
belle_sip_main_loop_add_source(obj->provider->stack->ml,timer);
}
/** */
static BELLESIP_INLINE void belle_sip_transaction_stop_timer(belle_sip_transaction_t *obj, belle_sip_source_t *timer){
belle_sip_main_loop_remove_source(obj->provider->stack->ml,timer);
}
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);
void belle_sip_transaction_set_state(belle_sip_transaction_t *t, belle_sip_transaction_state_t state);
/*
*
*
* Client transaction
*
*
*/
struct belle_sip_client_transaction{
belle_sip_transaction_t base;
belle_sip_uri_t* preset_route; /*use to store outbound proxy, will be helpful for refresher*/
belle_sip_hop_t* next_hop; /*use to send cancel request*/
};
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_client_transaction_t,belle_sip_transaction_t)
void (*send_request)(belle_sip_client_transaction_t *);
void (*on_response)(belle_sip_client_transaction_t *obj, belle_sip_response_t *resp);
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
void belle_sip_client_transaction_init(belle_sip_client_transaction_t *obj, 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);
void belle_sip_client_transaction_notify_response(belle_sip_client_transaction_t *t, belle_sip_response_t *resp);
struct belle_sip_ict{
belle_sip_client_transaction_t base;
belle_sip_source_t *timer_A;
belle_sip_source_t *timer_B;
belle_sip_source_t *timer_D;
belle_sip_source_t *timer_M;
belle_sip_request_t *ack;
};
typedef struct belle_sip_ict belle_sip_ict_t;
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_ict_t,belle_sip_client_transaction_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
belle_sip_ict_t * belle_sip_ict_new(belle_sip_provider_t *prov, belle_sip_request_t *req);
struct belle_sip_nict{
belle_sip_client_transaction_t base;
belle_sip_source_t *timer_F;
belle_sip_source_t *timer_E;
belle_sip_source_t *timer_K;
};
typedef struct belle_sip_nict belle_sip_nict_t;
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_nict_t,belle_sip_client_transaction_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
belle_sip_nict_t * belle_sip_nict_new(belle_sip_provider_t *prov, belle_sip_request_t *req);
/*
*
*
* Server transaction
*
*
*/
struct belle_sip_server_transaction{
belle_sip_transaction_t base;
char to_tag[8];
};
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_server_transaction_t,belle_sip_transaction_t)
int (*send_new_response)(belle_sip_server_transaction_t *, belle_sip_response_t *resp);
void (*on_request_retransmission)(belle_sip_server_transaction_t *obj);
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
void belle_sip_server_transaction_init(belle_sip_server_transaction_t *t, belle_sip_provider_t *prov,belle_sip_request_t *req);
void belle_sip_server_transaction_on_request(belle_sip_server_transaction_t *t, belle_sip_request_t *req);
struct belle_sip_ist{
belle_sip_server_transaction_t base;
belle_sip_source_t *timer_G;
belle_sip_source_t *timer_H;
belle_sip_source_t *timer_I;
belle_sip_source_t *timer_L;
};
typedef struct belle_sip_ist belle_sip_ist_t;
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_ist_t,belle_sip_server_transaction_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
belle_sip_ist_t * belle_sip_ist_new(belle_sip_provider_t *prov, belle_sip_request_t *req);
/* returns 0 if the ack should be notified to TU, or -1 otherwise*/
int belle_sip_ist_process_ack(belle_sip_ist_t *obj, belle_sip_message_t *ack);
struct belle_sip_nist{
belle_sip_server_transaction_t base;
belle_sip_source_t *timer_J;
};
typedef struct belle_sip_nist belle_sip_nist_t;
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_nist_t,belle_sip_server_transaction_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
belle_sip_nist_t * belle_sip_nist_new(belle_sip_provider_t *prov, belle_sip_request_t *req);
/*
* Dialogs
*/
struct belle_sip_dialog{
belle_sip_object_t base;
void *appdata;
belle_sip_provider_t *provider;
belle_sip_request_t *last_out_invite;
belle_sip_request_t *last_out_ack; /*so that it can be retransmitted when needed*/
belle_sip_response_t *last_200Ok;
belle_sip_source_t *timer_200Ok;
belle_sip_source_t *timer_200Ok_end;
belle_sip_dialog_state_t state;
belle_sip_dialog_state_t previous_state;
belle_sip_header_call_id_t *call_id;
belle_sip_header_address_t *local_party;
belle_sip_header_address_t *remote_party;
belle_sip_list_t *route_set;
belle_sip_header_address_t *remote_target;
char *local_tag;
char *remote_tag;
unsigned int local_cseq;
unsigned int remote_cseq;
belle_sip_transaction_t* last_transaction;
belle_sip_header_privacy_t* privacy;
belle_sip_list_t *queued_ct;/* queued client transactions*/
unsigned char is_server;
unsigned char is_secure;
unsigned char terminate_on_bye;
unsigned char needs_ack;
};
belle_sip_dialog_t *belle_sip_dialog_new(belle_sip_transaction_t *t);
belle_sip_dialog_t * belle_sip_provider_create_dialog_internal(belle_sip_provider_t *prov, belle_sip_transaction_t *t,unsigned int check_last_resp);
int belle_sip_dialog_is_authorized_transaction(const belle_sip_dialog_t *dialog,const char* method) ;
/*returns 1 if message belongs to the dialog, 0 otherwise */
int _belle_sip_dialog_match(belle_sip_dialog_t *obj, const char *call_id, const char *local_tag, const char *remote_tag);
int belle_sip_dialog_match(belle_sip_dialog_t *obj, belle_sip_message_t *msg, int as_uas);
int belle_sip_dialog_update(belle_sip_dialog_t *obj,belle_sip_transaction_t* transaction, int as_uas);
void belle_sip_dialog_check_ack_sent(belle_sip_dialog_t*obj);
int belle_sip_dialog_handle_ack(belle_sip_dialog_t *obj, belle_sip_request_t *ack);
void belle_sip_dialog_queue_client_transaction(belle_sip_dialog_t *dialog, belle_sip_client_transaction_t *tr);
/*
belle_sip_response_t
*/
belle_sip_hop_t* belle_sip_response_get_return_hop(belle_sip_response_t *msg);
/*********************************************************
* 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; \
belle_sdp_##object_type##_t* l_parsed_object; \
input = ANTLR_STREAM_NEW(object_type, value,strlen(value));\
lex = belle_sdpLexerNew (input);\
tokens = antlr3CommonTokenStreamSourceNew (ANTLR3_SIZE_HINT, TOKENSOURCE(lex));\
parser = belle_sdpParserNew (tokens);\
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;\
}
struct belle_sip_dialog_terminated_event{
belle_sip_provider_t *source;
belle_sip_dialog_t *dialog;
};
struct belle_sip_io_error_event{
belle_sip_object_t *source; /*the object impacted by this error*/
const char *transport;
const char *host;
unsigned int port;
};
struct belle_sip_request_event{
belle_sip_object_t *source;
belle_sip_server_transaction_t *server_transaction;
belle_sip_dialog_t *dialog;
belle_sip_request_t *request;
};
struct belle_sip_response_event{
belle_sip_object_t *source;
belle_sip_client_transaction_t *client_transaction;
belle_sip_dialog_t *dialog;
belle_sip_response_t *response;
};
struct belle_sip_timeout_event{
belle_sip_object_t *source;
belle_sip_transaction_t *transaction;
int is_server_transaction;
};
struct belle_sip_transaction_terminated_event{
belle_sip_provider_t *source;
belle_sip_transaction_t *transaction;
int is_server_transaction;
};
struct belle_sip_auth_event {
belle_sip_object_t *source;
belle_sip_auth_mode_t mode;
char* username;
char* userid;
char* realm;
char* passwd;
char* ha1;
char* domain;
char* distinguished_name;
belle_sip_certificates_chain_t * cert;
belle_sip_signing_key_t* key;
};
belle_sip_auth_event_t* belle_sip_auth_event_create(belle_sip_object_t *source, const char* realm,const belle_sip_uri_t * from_uri);
void belle_sip_auth_event_set_distinguished_name(belle_sip_auth_event_t* event,const char* value);
/*
* refresher
* */
belle_sip_refresher_t* belle_sip_refresher_new(belle_sip_client_transaction_t* transaction);
/*
* returns a char, even if entry is escaped*/
int belle_sip_get_char (const char*a,int n,char*out);
/*return an escaped string*/
BELLESIP_INTERNAL_EXPORT char* belle_sip_uri_to_escaped_username(const char* buff) ;
BELLESIP_INTERNAL_EXPORT char* belle_sip_uri_to_escaped_userpasswd(const char* buff) ;
BELLESIP_INTERNAL_EXPORT char* belle_sip_uri_to_escaped_parameter(const char* buff) ;
BELLESIP_INTERNAL_EXPORT char* belle_sip_uri_to_escaped_header(const char* buff) ;
/*(uri RFC 2396)*/
BELLESIP_INTERNAL_EXPORT char* belle_generic_uri_to_escaped_query(const char* buff);
BELLESIP_INTERNAL_EXPORT char* belle_generic_uri_to_escaped_path(const char* buff);
#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
#define BELLE_SIP_MAX_TO_STRING_SIZE 2048
void belle_sip_header_contact_set_unknown(belle_sip_header_contact_t *a, int value);
void belle_sip_request_set_dialog(belle_sip_request_t *req, belle_sip_dialog_t *dialog);
void belle_sip_request_set_rfc2543_branch(belle_sip_request_t *req, const char *rfc2543branch);
void belle_sip_dialog_update_request(belle_sip_dialog_t *dialog, belle_sip_request_t *req);
belle_sip_error_code belle_sip_headers_marshal(belle_sip_message_t *message, char* buff, size_t buff_size, size_t *offset);
#define SET_OBJECT_PROPERTY(obj,property_name,new_value) \
if (new_value) belle_sip_object_ref(new_value); \
if (obj->property_name){ \
belle_sip_object_unref(obj->property_name); \
}\
obj->property_name=new_value;
#include "parserutils.h"
/******************************
*
* private Extension header inherit from header
*
******************************/
typedef struct _belle_sip_header_extension belle_sip_header_extension_t;
belle_sip_header_extension_t* belle_sip_header_extension_new();
belle_sip_header_extension_t* belle_sip_header_extension_parse (const char* extension) ;
belle_sip_header_extension_t* belle_sip_header_extension_create (const char* name,const char* value);
BELLESIP_INTERNAL_EXPORT const char* belle_sip_header_extension_get_value(const belle_sip_header_extension_t* extension);
void belle_sip_header_extension_set_value(belle_sip_header_extension_t* extension,const char* value);
#define BELLE_SIP_HEADER_EXTENSION(t) BELLE_SIP_CAST(t,belle_sip_header_extension_t)
/****************
* belle_sip_body_handler_t object
***************/
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_body_handler_t,belle_sip_object_t)
void (*chunk_recv)(belle_sip_body_handler_t *obj, belle_sip_message_t *msg, size_t offset, const uint8_t *buf, size_t size);
int (*chunk_send)(belle_sip_body_handler_t *obj, belle_sip_message_t *msg, size_t offset, uint8_t *buf, size_t * size);
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
void belle_sip_body_handler_begin_transfer(belle_sip_body_handler_t *obj);
void belle_sip_body_handler_recv_chunk(belle_sip_body_handler_t *obj, belle_sip_message_t *msg, const uint8_t *buf, size_t size);
int belle_sip_body_handler_send_chunk(belle_sip_body_handler_t *obj, belle_sip_message_t *msg, uint8_t *buf, size_t *size);
void belle_sip_body_handler_end_transfer(belle_sip_body_handler_t *obj);
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_memory_body_handler_t,belle_sip_body_handler_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_user_body_handler_t,belle_sip_body_handler_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_file_body_handler_t,belle_sip_body_handler_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_multipart_body_handler_t,belle_sip_body_handler_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
/**
* file manipulation
*/
/**
* Parse a directory and return all files in it.
*
* @param[in] path The directory to be parsed
* @param[in] file_type if not NULL return only the file with the given extension, must include the '.', ex:".pem"
* @return a belle_sip list containing all found file or NULL if no file were found or directory doesn't exist. List must be destroyed using belle_sip_list_free_with_data(, belle_sip_free)
*/
belle_sip_list_t *belle_sip_parse_directory(const char *path, const char *file_type);
/**
* create a directory if it doesn't already exists
*
* @param[in] path The directory to be created
* @return 0 in case of succes, -1 otherwise, note it returns -1 if the directory already exists
*/
int belle_sip_mkdir(const char *path);
#endif