Commit f3651773 authored by Simon Morlat's avatar Simon Morlat

* add support for ipv6, at least tested for UDP.

* fix many bugs and crashes:
  - rport shall not be set if not present in the request
  - received shall not be set if identical to via's host
  - belle_sip_response_get_return_hop() wasn't working without received parameter
  - belle_sip_response_get_return_hop() wasn't working if no rport and no port (that is default port to be used).
parent 8d150254
......@@ -218,21 +218,21 @@ BELLESIP_EXPORT const char* belle_sip_header_via_get_host(const belle_sip_header
BELLESIP_EXPORT int belle_sip_header_via_get_port(const belle_sip_header_via_t* via);
BELLESIP_EXPORT int belle_sip_header_via_get_listening_port(const belle_sip_header_via_t *via);
const char* belle_sip_header_via_get_maddr(const belle_sip_header_via_t* via);
BELLESIP_EXPORT const char* belle_sip_header_via_get_maddr(const belle_sip_header_via_t* via);
BELLESIP_EXPORT const char* belle_sip_header_via_get_protocol(const belle_sip_header_via_t* via);
BELLESIP_EXPORT const char* belle_sip_header_via_get_received(const belle_sip_header_via_t* via);
BELLESIP_EXPORT int belle_sip_header_via_get_rport(const belle_sip_header_via_t* via);
int belle_sip_header_via_get_ttl(const belle_sip_header_via_t* via);
BELLESIP_EXPORT int belle_sip_header_via_get_ttl(const belle_sip_header_via_t* via);
void belle_sip_header_via_set_branch(belle_sip_header_via_t* via,const char* branch);
void belle_sip_header_via_set_host(belle_sip_header_via_t* via, const char* host);
int belle_sip_header_via_set_port(belle_sip_header_via_t* via,int port);
void belle_sip_header_via_set_maddr(belle_sip_header_via_t* via, const char* maddr);
void belle_sip_header_via_set_protocol(belle_sip_header_via_t* via, const char* protocol);
BELLESIP_EXPORT void belle_sip_header_via_set_branch(belle_sip_header_via_t* via,const char* branch);
BELLESIP_EXPORT void belle_sip_header_via_set_host(belle_sip_header_via_t* via, const char* host);
BELLESIP_EXPORT int belle_sip_header_via_set_port(belle_sip_header_via_t* via,int port);
BELLESIP_EXPORT void belle_sip_header_via_set_maddr(belle_sip_header_via_t* via, const char* maddr);
BELLESIP_EXPORT void belle_sip_header_via_set_protocol(belle_sip_header_via_t* via, const char* protocol);
BELLESIP_EXPORT void belle_sip_header_via_set_received(belle_sip_header_via_t* via, const char* received);
int belle_sip_header_via_set_rport(belle_sip_header_via_t* via,int rport);
void belle_sip_header_via_set_transport(belle_sip_header_via_t* via,const char* transport);
int belle_sip_header_via_set_ttl(belle_sip_header_via_t* via, int ttl);
BELLESIP_EXPORT int belle_sip_header_via_set_rport(belle_sip_header_via_t* via,int rport);
BELLESIP_EXPORT void belle_sip_header_via_set_transport(belle_sip_header_via_t* via,const char* transport);
BELLESIP_EXPORT int belle_sip_header_via_set_ttl(belle_sip_header_via_t* via, int ttl);
#define BELLE_SIP_HEADER_VIA(t) BELLE_SIP_CAST(t,belle_sip_header_via_t)
#define BELLE_SIP_VIA "Via"
......
......@@ -36,23 +36,24 @@ BELLESIP_EXPORT void belle_sip_parameters_clean(belle_sip_parameters_t* params);
BELLESIP_EXPORT const char* belle_sip_parameters_get_parameter(const belle_sip_parameters_t* obj,const char* name);
/*
* same as #belle_sip_parameters_get_parameter but name is case insensitive */
const char* belle_sip_parameters_get_case_parameter(const belle_sip_parameters_t* params,const char* name);
BELLESIP_EXPORT const char* belle_sip_parameters_get_case_parameter(const belle_sip_parameters_t* params,const char* name);
/**
* returns 0 if not found
*/
BELLESIP_EXPORT unsigned int belle_sip_parameters_is_parameter(const belle_sip_parameters_t* obj,const char* name);
BELLESIP_EXPORT unsigned int belle_sip_parameters_has_parameter(const belle_sip_parameters_t* obj,const char* name);
BELLESIP_EXPORT void belle_sip_parameters_set_parameter(belle_sip_parameters_t* obj,const char* name,const char* value);
const belle_sip_list_t * belle_sip_parameters_get_parameter_names(const belle_sip_parameters_t* obj);
BELLESIP_EXPORT const belle_sip_list_t * belle_sip_parameters_get_parameter_names(const belle_sip_parameters_t* obj);
const belle_sip_list_t * belle_sip_parameters_get_parameters(const belle_sip_parameters_t* obj);
BELLESIP_EXPORT const belle_sip_list_t * belle_sip_parameters_get_parameters(const belle_sip_parameters_t* obj);
void belle_sip_parameters_remove_parameter(belle_sip_parameters_t* obj,const char* name);
BELLESIP_EXPORT void belle_sip_parameters_remove_parameter(belle_sip_parameters_t* obj,const char* name);
int belle_sip_parameters_marshal(const belle_sip_parameters_t* obj, char* buff,unsigned int offset,unsigned int buff_size);
BELLESIP_EXPORT int belle_sip_parameters_marshal(const belle_sip_parameters_t* obj, char* buff,unsigned int offset,unsigned int buff_size);
#define BELLE_SIP_PARAMETERS(obj) BELLE_SIP_CAST(obj,belle_sip_parameters_t)
#endif /*PARAMETERS_H_*/
......@@ -535,10 +535,11 @@ int belle_sip_header_via_set_port (belle_sip_header_via_t* obj,int value) {
int belle_sip_header_via_get_listening_port(const belle_sip_header_via_t *via){
int ret=belle_sip_header_via_get_port(via);
if (ret==-1) ret=belle_sip_listening_point_get_well_known_port(via->protocol);
if (ret==0) ret=belle_sip_listening_point_get_well_known_port(via->transport);
return ret;
}
const char* belle_sip_header_via_get_transport_lowercase(const belle_sip_header_via_t* via) {
const char* belle_sip_header_via_get_transport_lowercase(const belle_sip_header_via_t* via) {
if (strcasecmp("udp",via->transport)==0) return "udp";
else if (strcasecmp("tcp",via->transport)==0) return "tcp";
else if (strcasecmp("tls",via->transport)==0) return "tls";
......
......@@ -276,7 +276,7 @@ BELLESIP_INTERNAL_EXPORT char *belle_sip_strdup_printf(const char *fmt,...);
#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_is_parameter(BELLE_SIP_PARAMETERS(obj),#attribute) && !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);\
......@@ -349,7 +349,7 @@ BELLESIP_INTERNAL_EXPORT char *belle_sip_strdup_printf(const char *fmt,...);
}
#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);\
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);\
......
......@@ -68,17 +68,18 @@ const char* belle_sip_parameters_get_parameter_base(const belle_sip_parameters_t
return NULL;
}
}
const char* belle_sip_parameters_get_parameter(const belle_sip_parameters_t* params,const char* name) {
const char* belle_sip_parameters_get_parameter(const belle_sip_parameters_t* params,const char* name) {
return belle_sip_parameters_get_parameter_base(params,name,(belle_sip_compare_func)belle_sip_param_pair_comp_func);
}
const char* belle_sip_parameters_get_case_parameter(const belle_sip_parameters_t* params,const char* name) {
const char* belle_sip_parameters_get_case_parameter(const belle_sip_parameters_t* params,const char* name) {
return belle_sip_parameters_get_parameter_base(params,name,(belle_sip_compare_func)belle_sip_param_pair_case_comp_func);
}
unsigned int belle_sip_parameters_is_parameter(const belle_sip_parameters_t* params,const char* name) {
unsigned int belle_sip_parameters_has_parameter(const belle_sip_parameters_t* params,const char* name) {
return belle_sip_list_find_custom(params->param_list, (belle_sip_compare_func)belle_sip_param_pair_comp_func, name) != NULL;
}
void belle_sip_parameters_set_parameter(belle_sip_parameters_t* params,const char* name,const char* value) {
void belle_sip_parameters_set_parameter(belle_sip_parameters_t* params,const char* name,const char* value) {
/*1 check if present*/
belle_sip_param_pair_t* lNewpair;
belle_sip_list_t * lResult = belle_sip_list_find_custom(params->paramnames_list, (belle_sip_compare_func)strcmp, name);
......@@ -102,7 +103,7 @@ const belle_sip_list_t* belle_sip_parameters_get_parameter_names(const belle_sip
return params?params->paramnames_list:NULL;
}
void belle_sip_parameters_remove_parameter(belle_sip_parameters_t* params,const char* name) {
void belle_sip_parameters_remove_parameter(belle_sip_parameters_t* params,const char* name) {
/*1 check if present*/
belle_sip_list_t * lResult = belle_sip_list_find_custom(params->paramnames_list, (belle_sip_compare_func)strcmp, name);
/* first remove from header names list*/
......
......@@ -138,7 +138,7 @@ static int resolver_process_a_data(belle_sip_resolver_context_t *ctx, unsigned i
sin6.sin6_port = ctx->port;
if (getnameinfo((struct sockaddr *)&sin6, sizeof(sin6), host, sizeof(host), service, sizeof(service), NI_NUMERICHOST) != 0)
continue;
ctx->ai = belle_sip_ip_address_to_addrinfo(host, ctx->port);
ctx->ai = belle_sip_ip_address_to_addrinfo(ctx->family, host, ctx->port);
belle_sip_message("%s has address %s", ctx->name, host);
break;
} else {
......@@ -151,7 +151,7 @@ static int resolver_process_a_data(belle_sip_resolver_context_t *ctx, unsigned i
sin.sin_port = ctx->port;
if (getnameinfo((struct sockaddr *)&sin, sizeof(sin), host, sizeof(host), service, sizeof(service), NI_NUMERICHOST) != 0)
continue;
ctx->ai = belle_sip_ip_address_to_addrinfo(host, ctx->port);
ctx->ai = belle_sip_ip_address_to_addrinfo(ctx->family, host, ctx->port);
belle_sip_message("%s has address %s", ctx->name, host);
break;
}
......@@ -263,15 +263,18 @@ int belle_sip_addrinfo_to_ip(const struct addrinfo *ai, char *ip, size_t ip_size
return 0;
}
struct addrinfo * belle_sip_ip_address_to_addrinfo(const char *ipaddress, int port){
struct addrinfo * belle_sip_ip_address_to_addrinfo(int family, const char *ipaddress, int port){
struct addrinfo *res=NULL;
struct addrinfo hints={0};
char serv[10];
int err;
snprintf(serv,sizeof(serv),"%i",port);
hints.ai_family=AF_UNSPEC;
hints.ai_family=family;
hints.ai_flags=AI_NUMERICSERV|AI_NUMERICHOST;
if (family==AF_INET6) hints.ai_flags|=AI_V4MAPPED;
err=getaddrinfo(ipaddress,serv,&hints,&res);
if (err!=0){
return NULL;
......@@ -297,7 +300,7 @@ 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,FALSE);
unsigned long belle_sip_resolve(belle_sip_stack_t *stack, const char *name, int port, int family, belle_sip_resolver_callback_t cb , void *data, belle_sip_main_loop_t *ml) {
struct addrinfo *res = belle_sip_ip_address_to_addrinfo(name, port);
struct addrinfo *res = belle_sip_ip_address_to_addrinfo(family,name, port);
if (res == NULL) {
/* Then perform asynchronous DNS query */
belle_sip_resolver_context_t *ctx = belle_sip_object_new(belle_sip_resolver_context_t);
......@@ -337,7 +340,8 @@ void belle_sip_resolve_cancel(belle_sip_main_loop_t *ml, unsigned long id){
}
}
void belle_sip_get_src_addr_for(const struct sockaddr *dest, socklen_t destlen, struct sockaddr *src, socklen_t *srclen){
void belle_sip_get_src_addr_for(const struct sockaddr *dest, socklen_t destlen, struct sockaddr *src, socklen_t *srclen, int local_port){
int af_type=dest->sa_family;
int sock=socket(af_type,SOCK_DGRAM,IPPROTO_UDP);
......@@ -353,6 +357,15 @@ void belle_sip_get_src_addr_for(const struct sockaddr *dest, socklen_t destlen,
belle_sip_error("belle_sip_get_src_addr_for: getsockname() failed: %s",belle_sip_get_socket_error_string());
goto fail;
}
if (af_type==AF_INET6){
struct sockaddr_in6 *sin6=(struct sockaddr_in6*)src;
sin6->sin6_port=htons(local_port);
}else{
struct sockaddr_in *sin=(struct sockaddr_in*)src;
sin->sin_port=htons(local_port);
}
close_socket(sock);
return;
fail:
......@@ -366,5 +379,34 @@ fail:
*srclen=res->ai_addrlen;
freeaddrinfo(res);
}
if (sock==(belle_sip_socket_t)-1) close_socket(sock);
if (sock!=(belle_sip_socket_t)-1) close_socket(sock);
}
#ifndef IN6_GET_ADDR_V4MAPPED
#define IN6_GET_ADDR_V4MAPPED(sin6_addr) *(unsigned int*)((unsigned char*)(sin6_addr)+12)
#endif
void belle_sip_address_remove_v4_mapping(const struct sockaddr *v6, struct sockaddr *result, socklen_t *result_len){
if (v6->sa_family==AF_INET6){
struct sockaddr_in6 *in6=(struct sockaddr_in6*)v6;
if (IN6_IS_ADDR_V4MAPPED(&in6->sin6_addr)){
struct sockaddr_in *in=(struct sockaddr_in*)result;
result->sa_family=AF_INET;
in->sin_addr.s_addr = IN6_GET_ADDR_V4MAPPED(&in6->sin6_addr);
in->sin_port=in6->sin6_port;
*result_len=sizeof(struct sockaddr_in);
}else{
if (v6!=result) memcpy(result,v6,sizeof(struct sockaddr_in6));
*result_len=sizeof(struct sockaddr_in6);
}
}else{
*result_len=sizeof(struct sockaddr_in);
if (v6!=result) memcpy(result,v6,sizeof(struct sockaddr_in));
}
}
......@@ -52,11 +52,21 @@ struct belle_sip_resolver_context{
};
int belle_sip_addrinfo_to_ip(const struct addrinfo *ai, char *ip, size_t ip_size, int *port);
BELLESIP_INTERNAL_EXPORT struct addrinfo * belle_sip_ip_address_to_addrinfo(const char *ipaddress, int port);
BELLESIP_INTERNAL_EXPORT struct addrinfo * belle_sip_ip_address_to_addrinfo(int family, const char *ipaddress, int port);
BELLESIP_INTERNAL_EXPORT unsigned long belle_sip_resolve(belle_sip_stack_t *stack, const char *name, int port, int family, belle_sip_resolver_callback_t cb , void *data, belle_sip_main_loop_t *ml);
void belle_sip_resolve_cancel(belle_sip_main_loop_t *ml, unsigned long id);
void belle_sip_get_src_addr_for(const struct sockaddr *dest, socklen_t destlen, struct sockaddr *src, socklen_t *srclen);
/**
* Lookups the source address from local interface that can be used to connect to a destination address.
* local_port is only used to be assigned into the result source address.
**/
void belle_sip_get_src_addr_for(const struct sockaddr *dest, socklen_t destlen, struct sockaddr *src, socklen_t *srclen, int local_port);
/**
* This function will transform a V4 to V6 mapped address to a pure V4 and write it into result, or will just copy it otherwise.
* The memory for v6 and result may be the same, in which case processing is done in place or no copy is done.
* The pointer to result must have sufficient storage, typically a struct sockaddr_storage.
**/
void belle_sip_address_remove_v4_mapping(const struct sockaddr *v6, struct sockaddr *result, socklen_t *result_len);
#endif
......@@ -84,8 +84,16 @@ static void fix_incoming_via(belle_sip_request_t *msg, const struct addrinfo* or
}
via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header((belle_sip_message_t*)msg,"via"));
if (via){
belle_sip_header_via_set_received(via,received);
belle_sip_header_via_set_rport(via,atoi(rport));
const char* host = belle_sip_header_via_get_host(via);
if (strcmp(host,received)!=0)
belle_sip_header_via_set_received(via,received);
if (belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(via),"rport")){
int port = belle_sip_header_via_get_listening_port(via);
int rport_int=atoi(rport);
if (rport_int!=port) belle_sip_header_via_set_rport(via,atoi(rport));
}
}
}
static int get_message_start_pos(char *buff, size_t bufflen) {
......@@ -495,7 +503,7 @@ static void channel_res_done(void *data, const char *name, struct addrinfo *res)
void belle_sip_channel_resolve(belle_sip_channel_t *obj){
channel_set_state(obj,BELLE_SIP_CHANNEL_RES_IN_PROGRESS);
obj->resolver_id=belle_sip_resolve(obj->stack, obj->peer_name, obj->peer_port, 0, channel_res_done, obj, obj->stack->ml);
obj->resolver_id=belle_sip_resolve(obj->stack, obj->peer_name, obj->peer_port, obj->lp->ai_family, channel_res_done, obj, obj->stack->ml);
return ;
}
......
......@@ -29,13 +29,11 @@ void belle_sip_listening_point_init(belle_sip_listening_point_t *lp, belle_sip_s
}
static void belle_sip_listening_point_uninit(belle_sip_listening_point_t *lp){
char *tmp=belle_sip_object_to_string((belle_sip_object_t*)BELLE_SIP_LISTENING_POINT(lp)->listening_uri);
belle_sip_listening_point_clean_channels(lp);
belle_sip_message("Listening point [%p] on [%s://%s:%i] destroyed" ,lp
,belle_sip_uri_get_transport_param(BELLE_SIP_LISTENING_POINT(lp)->listening_uri)
,belle_sip_uri_get_host(BELLE_SIP_LISTENING_POINT(lp)->listening_uri)
,belle_sip_uri_get_port(BELLE_SIP_LISTENING_POINT(lp)->listening_uri));
belle_sip_message("Listening point [%p] on [%s] destroyed",lp, tmp);
belle_sip_object_unref(lp->listening_uri);
belle_sip_free(tmp);
lp->channel_listener=NULL; /*does not unref provider*/
belle_sip_uninit_sockets();
belle_sip_listening_point_set_keep_alive(lp,-1);
......
......@@ -43,6 +43,7 @@ struct belle_sip_listening_point{
belle_sip_uri_t* listening_uri;
belle_sip_source_t* keep_alive_timer;
belle_sip_channel_listener_t* channel_listener; /*initial channel listener used for channel creation, specially for socket server*/
int ai_family; /*AF_INET or AF_INET6*/
};
void belle_sip_listening_point_init(belle_sip_listening_point_t *lp, belle_sip_stack_t *s, const char *address, int port);
......
......@@ -554,10 +554,9 @@ void belle_sip_response_fill_for_dialog(belle_sip_response_t *obj, belle_sip_req
belle_sip_hop_t* belle_sip_response_get_return_hop(belle_sip_response_t *msg){
belle_sip_header_via_t *via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header(BELLE_SIP_MESSAGE(msg),"via"));
const char *host=belle_sip_header_via_get_received(via)?belle_sip_header_via_get_received(via):belle_sip_header_via_get_received(via);
int port=belle_sip_header_via_get_rport(via)>0?belle_sip_header_via_get_rport(via):belle_sip_header_via_get_listening_port(via);
belle_sip_hop_t* hop=belle_sip_hop_new(belle_sip_header_via_get_transport_lowercase(via),host,port);
return hop;
const char *host=belle_sip_header_via_get_received(via) ? belle_sip_header_via_get_received(via) : belle_sip_header_via_get_host(via);
int port=belle_sip_header_via_get_rport(via)>0 ? belle_sip_header_via_get_rport(via) : belle_sip_header_via_get_listening_port(via);
return belle_sip_hop_new(belle_sip_header_via_get_transport_lowercase(via),host,port);
}
int belle_sip_response_fix_contact(const belle_sip_response_t* response,belle_sip_header_contact_t* contact) {
......
......@@ -63,14 +63,8 @@ int udp_channel_connect(belle_sip_channel_t *obj, const struct addrinfo *ai){
struct sockaddr_storage laddr;
socklen_t lslen=sizeof(laddr);
if (obj->local_ip==NULL){
belle_sip_get_src_addr_for(ai->ai_addr,ai->ai_addrlen,(struct sockaddr*)&laddr,&lslen);
if (ai->ai_family==AF_INET6){
struct sockaddr_in6 *sin6=(struct sockaddr_in6*)&laddr;
sin6->sin6_port=htons(obj->local_port);
}else{
struct sockaddr_in *sin=(struct sockaddr_in*)&laddr;
sin->sin_port=htons(obj->local_port);
}
belle_sip_get_src_addr_for(ai->ai_addr,ai->ai_addrlen,(struct sockaddr*)&laddr,&lslen,obj->local_port);
belle_sip_address_remove_v4_mapping((struct sockaddr*)&laddr,(struct sockaddr*)&laddr,&lslen);
}
belle_sip_channel_set_ready(obj,(struct sockaddr*)&laddr,lslen);
return 0;
......
......@@ -58,7 +58,7 @@ BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_udp_listening_point_t)={
};
static belle_sip_socket_t create_udp_socket(const char *addr, int port){
static belle_sip_socket_t create_udp_socket(const char *addr, int port, int *family){
struct addrinfo hints={0};
struct addrinfo *res=NULL;
int err;
......@@ -75,6 +75,7 @@ static belle_sip_socket_t create_udp_socket(const char *addr, int port){
belle_sip_error("getaddrinfo() failed for %s port %i: %s",addr,port,gai_strerror(err));
return -1;
}
*family=res->ai_family;
sock=socket(res->ai_family,res->ai_socktype,res->ai_protocol);
if (sock==-1){
belle_sip_error("Cannot create UDP socket: %s",belle_sip_get_socket_error_string());
......@@ -91,18 +92,24 @@ static belle_sip_socket_t create_udp_socket(const char *addr, int port){
freeaddrinfo(res);
return sock;
}
static int on_udp_data(belle_sip_udp_listening_point_t *lp, unsigned int events);
static belle_sip_listening_point_t* belle_sip_udp_listening_point_init(belle_sip_udp_listening_point_t *lp) {
static int belle_sip_udp_listening_point_init_socket(belle_sip_udp_listening_point_t *lp){
lp->sock=create_udp_socket(belle_sip_uri_get_host(((belle_sip_listening_point_t*)lp)->listening_uri)
,belle_sip_uri_get_port(((belle_sip_listening_point_t*)lp)->listening_uri));
,belle_sip_uri_get_port(((belle_sip_listening_point_t*)lp)->listening_uri),&lp->base.ai_family);
if (lp->sock==(belle_sip_socket_t)-1){
belle_sip_object_unref(lp);
return NULL;
return -1;
}
lp->source=belle_sip_socket_source_new((belle_sip_source_func_t)on_udp_data,lp,lp->sock,BELLE_SIP_EVENT_READ,-1);
belle_sip_main_loop_add_source(((belle_sip_listening_point_t*)lp)->stack->ml,lp->source);
return BELLE_SIP_LISTENING_POINT(lp);
return 0;
}
static void belle_sip_udp_listening_point_init(belle_sip_udp_listening_point_t *lp, belle_sip_stack_t *s, const char *ipaddress, int port) {
belle_sip_listening_point_init((belle_sip_listening_point_t*)lp,s,ipaddress,port);
belle_sip_udp_listening_point_init_socket(lp);
}
/*peek data from the master socket to see where it comes from, and dispatch to matching channel.
......@@ -117,15 +124,17 @@ static int on_udp_data(belle_sip_udp_listening_point_t *lp, unsigned int events)
belle_sip_debug("udp_listening_point: data to read.");
err=recvfrom(lp->sock,(char*)buf,sizeof(buf),MSG_PEEK,(struct sockaddr*)&addr,&addrlen);
if (err==-1){
belle_sip_error("udp_listening_point: recvfrom() failed on [%s:%i], : [%s] reopening server socket"
,belle_sip_uri_get_host(((belle_sip_listening_point_t*)lp)->listening_uri)
,belle_sip_uri_get_port(((belle_sip_listening_point_t*)lp)->listening_uri)
char *tmp=belle_sip_object_to_string((belle_sip_object_t*) ((belle_sip_listening_point_t*)lp)->listening_uri);
belle_sip_error("udp_listening_point: recvfrom() failed on [%s], : [%s] reopening server socket"
,tmp
,belle_sip_get_socket_error_string());
belle_sip_free(tmp);
belle_sip_udp_listening_point_uninit(lp);
belle_sip_udp_listening_point_init(lp);
belle_sip_udp_listening_point_init_socket(lp);
}else{
belle_sip_channel_t *chan;
struct addrinfo ai={0};
belle_sip_address_remove_v4_mapping((struct sockaddr*)&addr,(struct sockaddr*)&addr,&addrlen);
ai.ai_family=((struct sockaddr*)&addr)->sa_family;
ai.ai_addr=(struct sockaddr*)&addr;
ai.ai_addrlen=addrlen;
......@@ -159,7 +168,11 @@ static int on_udp_data(belle_sip_udp_listening_point_t *lp, unsigned int events)
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);
return belle_sip_udp_listening_point_init(lp);
belle_sip_udp_listening_point_init(lp,s,ipaddress, port);
if (lp->sock==(belle_sip_socket_t)-1){
belle_sip_object_unref(s);
return NULL;
}
return (belle_sip_listening_point_t*)lp;
}
......@@ -174,7 +174,7 @@ static void test_via_header(void) {
CU_ASSERT_STRING_EQUAL(belle_sip_header_via_get_host(L_via), "::1");
CU_ASSERT_EQUAL(belle_sip_header_via_get_port(L_via),5062);
CU_ASSERT_TRUE(belle_sip_parameters_is_parameter(BELLE_SIP_PARAMETERS(L_via),"rport"));
CU_ASSERT_TRUE(belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(L_via),"rport"));
CU_ASSERT_STRING_EQUAL(belle_sip_header_via_get_received(L_via),"192.169.0.4");
CU_ASSERT_STRING_EQUAL(belle_sip_header_via_get_branch(L_via),"z9hG4bK368560724");
belle_sip_object_unref(BELLE_SIP_OBJECT(L_via));
......
......@@ -58,6 +58,7 @@ typedef struct endpoint {
const char* received;
int rport;
unsigned char unreconizable_contact;
int connection_family;
} endpoint_t;
......@@ -202,7 +203,7 @@ static void server_process_request_event(void *obj, const belle_sip_request_even
contact=belle_sip_header_contact_new();
}
if(endpoint->unreconizable_contact) {
/*put an unexopected address*/
/*put an unexpected address*/
belle_sip_uri_set_host(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact)),"nimportequoi.com");
}
belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(contact));
......@@ -225,7 +226,20 @@ static void client_process_response_event(void *obj, const belle_sip_response_ev
int status = belle_sip_response_get_status_code(belle_sip_response_event_get_response(event));
belle_sip_message("caller_process_response_event [%i]",status);
switch (status) {
case 200:endpoint->stat.twoHundredOk++; break;
case 200:
endpoint->stat.twoHundredOk++;
if (endpoint->connection_family!=AF_UNSPEC){
const char *host;
int family_found;
belle_sip_header_contact_t *ct=belle_sip_message_get_header_by_type(
(belle_sip_message_t*)belle_sip_response_event_get_response(event),belle_sip_header_contact_t);
CU_ASSERT_PTR_NOT_NULL_FATAL(ct);
host=belle_sip_uri_get_host(belle_sip_header_address_get_uri((belle_sip_header_address_t*)ct));
if (strchr(host,':')) family_found=AF_INET6;
else family_found=AF_INET;
CU_ASSERT_TRUE(family_found==endpoint->connection_family);
}
break;
case 401:endpoint->stat.fourHundredOne++; break;
default: break;
}
......@@ -261,13 +275,15 @@ static void belle_sip_refresher_listener ( const belle_sip_refresher_t* refreshe
}
}
static endpoint_t* create_endpoint(int port,const char* transport,belle_sip_listener_callbacks_t* listener_callbacks) {
static endpoint_t* create_endpoint(const char *ip, int port,const char* transport,belle_sip_listener_callbacks_t* listener_callbacks) {
endpoint_t* endpoint = belle_sip_new0(endpoint_t);
endpoint->stack=belle_sip_stack_new(NULL);
endpoint->listener_callbacks=listener_callbacks;
endpoint->lp=belle_sip_stack_create_listening_point(endpoint->stack,"0.0.0.0",port,transport);
CU_ASSERT_PTR_NOT_NULL_FATAL(endpoint->lp);
belle_sip_object_ref(endpoint->lp);
endpoint->lp=belle_sip_stack_create_listening_point(endpoint->stack,ip,port,transport);
endpoint->connection_family=AF_INET;
if (endpoint->lp) belle_sip_object_ref(endpoint->lp);
endpoint->provider=belle_sip_stack_create_provider(endpoint->stack,endpoint->lp);
belle_sip_provider_add_sip_listener(endpoint->provider,(endpoint->listener=belle_sip_listener_create_from_callbacks(endpoint->listener_callbacks,endpoint)));
sprintf(endpoint->nonce,"%p",endpoint); /*initial nonce*/
......@@ -284,7 +300,9 @@ static void destroy_endpoint(endpoint_t* endpoint) {
}
static endpoint_t* create_udp_endpoint(int port,belle_sip_listener_callbacks_t* listener_callbacks) {
return create_endpoint(port,"udp",listener_callbacks);
endpoint_t *endpoint=create_endpoint("0.0.0.0",port,"udp",listener_callbacks);
CU_ASSERT_PTR_NOT_NULL_FATAL(endpoint->lp);
return endpoint;
}
static void register_base(endpoint_t* client,endpoint_t *server) {
......@@ -302,7 +320,10 @@ static void register_base(endpoint_t* client,endpoint_t *server) {
dest_uri=(belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)belle_sip_listening_point_get_uri(server->lp));
belle_sip_uri_set_host(dest_uri,"127.0.0.1");
if (client->connection_family==AF_INET6)
belle_sip_uri_set_host(dest_uri,"::1");
else
belle_sip_uri_set_host(dest_uri,"127.0.0.1");
destination_route=belle_sip_header_route_create(belle_sip_header_address_create(NULL,dest_uri));
......@@ -481,6 +502,48 @@ static void register_with_unrecognizable_contact(void) {
destroy_endpoint(server);
}
static int register_test_with_interfaces(const char *transport, const char *client_ip, const char *server_ip, int connection_family) {
int ret=0;
belle_sip_listener_callbacks_t client_callbacks;
belle_sip_listener_callbacks_t server_callbacks;
endpoint_t* client,*server;
memset(&client_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
memset(&server_callbacks,0,sizeof(belle_sip_listener_callbacks_t));
client_callbacks.process_response_event=client_process_response_event;
client_callbacks.process_auth_requested=client_process_auth_requested;
server_callbacks.process_request_event=server_process_request_event;
client = create_endpoint(client_ip,3452,transport,&client_callbacks);
client->connection_family=connection_family;
server = create_endpoint(server_ip,6788,transport,&server_callbacks);
server->expire_in_contact=client->expire_in_contact=0;
server->auth=none;
if (client->lp==NULL || server->lp==NULL){
belle_sip_warning("Cannot check ipv6 because host has no ipv6 support.");
ret=-1;
}else register_base(client,server);
destroy_endpoint(client);
destroy_endpoint(server);
return ret;
}
static void register_test_ipv6_to_ipv4(void){
register_test_with_interfaces("udp","::0","0.0.0.0",AF_INET);
}
static void register_test_ipv4_to_ipv6(void){
register_test_with_interfaces("udp","0.0.0.0","::0",AF_INET);
}
static void register_test_ipv6_to_ipv6_with_ipv4(void){
register_test_with_interfaces("udp","::0","::0",AF_INET);
}
static void register_test_ipv6_to_ipv6_with_ipv6(void){
register_test_with_interfaces("udp","::0","::0",AF_INET6);
}
test_t refresher_tests[] = {
{ "REGISTER Expires header", register_expires_header },
......@@ -489,6 +552,10 @@ test_t refresher_tests[] = {
{ "REGISTER Expires in Contact digest auth", register_expires_in_contact_header_digest_auth },
{ "SUBSCRIBE", subscribe_test },
{ "REGISTER with unrecognizable Contact", register_with_unrecognizable_contact },
{ "REGISTER UDP from ipv6 to ipv4", register_test_ipv6_to_ipv4 },
{ "REGISTER UDP from ipv4 to ipv6", register_test_ipv4_to_ipv6 },
{ "REGISTER UDP from ipv6 to ipv6 with ipv4", register_test_ipv6_to_ipv6_with_ipv4 },
{ "REGISTER UDP from ipv6 to ipv6 with ipv6", register_test_ipv6_to_ipv6_with_ipv6 }
};
test_suite_t refresher_test_suite = {
......
......@@ -102,7 +102,7 @@ static void ipv4_a_query(void) {
if (client->result) {
struct sockaddr_in *sock_in = (struct sockaddr_in *)client->result->ai_addr;
CU_ASSERT_EQUAL(ntohs(sock_in->sin_port), SIP_PORT);
ai = belle_sip_ip_address_to_addrinfo(IPV4_SIP_IP, SIP_PORT);
ai = belle_sip_ip_address_to_addrinfo(AF_INET, IPV4_SIP_IP, SIP_PORT);
if (ai) {
CU_ASSERT_EQUAL(sock_in->sin_addr.s_addr, ((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr);
}
......@@ -169,7 +169,7 @@ static void ipv6_aaaa_query(void) {
if (client->result) {
struct sockaddr_in6 *sock_in6 = (struct sockaddr_in6 *)client->result->ai_addr;
CU_ASSERT_EQUAL(ntohs(sock_in6->sin6_port), SIP_PORT);
ai = belle_sip_ip_address_to_addrinfo(IPV6_SIP_IP, SIP_PORT);
ai = belle_sip_ip_address_to_addrinfo(AF_INET6, IPV6_SIP_IP, SIP_PORT);
if (ai) {
struct in6_addr *ipv6_address = &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr;
int i;
......
......@@ -183,7 +183,7 @@ int main (int argc, char *argv[]) {
fprintf(stderr,"%s \t--help\n"
"\t\t\t--verbose\n"
"\t\t\t--domain <test sip domain>\n"
"\t\t\t---auth-domain <test auth domain>\n"
"\t\t\t--auth-domain <test auth domain>\n"
#if HAVE_CU_GET_SUITE
"\t\t\t--suite <suite name>\n"
"\t\t\t--test <test name>\n"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment