Commit ae453247 authored by Simon Morlat's avatar Simon Morlat

fix multiple problems with networking on windows.

A problem remains for udp ipv6 channel on windows, who are apparently
unable to guess their local ip.
parent b1d815ca
......@@ -89,9 +89,9 @@ static void belle_sip_source_to_poll(belle_sip_source_t *s, belle_sip_pollfd_t *
long events=0;
if (s->events & BELLE_SIP_EVENT_READ)
events|=FD_READ;
events|=FD_READ|FD_ACCEPT;
if (s->events & BELLE_SIP_EVENT_WRITE)
events|=FD_WRITE;
events|=FD_WRITE|FD_CONNECT;
if (events!=s->armed_events){
s->armed_events=events;
err=WSAEventSelect(s->sock,s->fd,events);
......@@ -113,10 +113,10 @@ static unsigned int belle_sip_source_get_revents(belle_sip_source_t *s,belle_sip
belle_sip_error("WSAEnumNetworkEvents() failed: %s socket=%x",belle_sip_get_socket_error_string(),(unsigned int)s->sock);
return 0;
}
if (revents.lNetworkEvents & FD_READ){
if (revents.lNetworkEvents & FD_READ || revents.lNetworkEvents & FD_ACCEPT){
ret|=BELLE_SIP_EVENT_READ;
}
if (revents.lNetworkEvents & FD_WRITE){
if (revents.lNetworkEvents & FD_WRITE || revents.lNetworkEvents & FD_CONNECT){
ret|=BELLE_SIP_EVENT_WRITE;
}
s->armed_events=0;
......
......@@ -588,7 +588,7 @@ struct addrinfo * belle_sip_ip_address_to_addrinfo(int family, const char *ipadd
hints.ai_flags=AI_NUMERICSERV|AI_NUMERICHOST;
hints.ai_socktype=SOCK_STREAM; //not used but it's needed to specify it because otherwise getaddrinfo returns one struct addrinfo per socktype.
if (family==AF_INET6 && strchr(ipaddress,'.')!=NULL) {
if (family==AF_INET6 && strchr(ipaddress,':')==NULL) {
hints.ai_flags|=AI_V4MAPPED;
}
err=belle_sip_getaddrinfo(ipaddress,serv,&hints,&res);
......@@ -970,7 +970,10 @@ void belle_sip_resolver_context_cancel(belle_sip_resolver_context_t *obj){
BELLE_SIP_OBJECT_VPTR(obj,belle_sip_resolver_context_t)->cancel(obj);
}
/*
This function does the connect() method to get local ip address suitable to reach a given destination.
It works on all platform except for windows using ipv6 sockets. TODO: find a workaround for win32+ipv6 socket
*/
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);
......@@ -979,6 +982,11 @@ void belle_sip_get_src_addr_for(const struct sockaddr *dest, socklen_t destlen,
belle_sip_fatal("Could not create socket: %s",belle_sip_get_socket_error_string());
goto fail;
}
if (af_type==AF_INET6){
belle_sip_socket_enable_dual_stack(sock);
}
if (connect(sock,dest,destlen)==-1){
belle_sip_error("belle_sip_get_src_addr_for: connect() failed: %s",belle_sip_get_socket_error_string());
goto fail;
......
......@@ -190,7 +190,17 @@ int belle_sip_socket_set_dscp(belle_sip_socket_t sock, int ai_family, int dscp){
#endif
#ifdef ANDROID
int belle_sip_socket_enable_dual_stack(belle_sip_socket_t sock){
int value=0;
int err=setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&value, sizeof(value));
if (err==-1){
belle_sip_warning("belle_sip_socket_enable_dual_stack: setsockopt(IPV6_ONLY) failed: %s",belle_sip_get_socket_error_string());
}
return err;
}
#if defined(ANDROID) || defined(WIN32)
/*
* SHAME !!! bionic's getaddrinfo does not implement the AI_V4MAPPED flag !
......@@ -198,6 +208,11 @@ int belle_sip_socket_set_dscp(belle_sip_socket_t sock, int ai_family, int dscp){
* The code below is to emulate a _compliant_ getaddrinfo for android.
**/
/**
* SHAME AGAIN !!! Win32's implementation of getaddrinfo is bogus !
* it is not able to return an IPv6 addrinfo from an IPv4 address when AI_V4MAPPED is set !
**/
struct addrinfo *_belle_sip_alloc_addrinfo(int ai_family, int socktype, int proto){
struct addrinfo *ai=(struct addrinfo*)belle_sip_malloc0(sizeof(struct addrinfo));
ai->ai_family=ai_family;
......
......@@ -61,6 +61,9 @@
# ifndef AI_ALL
# define AI_ALL 0x00000000
# endif
# ifndef IPV6_V6ONLY
# define IPV6_V6ONLY 27
# endif
#endif
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(__WIN32__)
......@@ -81,6 +84,7 @@ BELLESIP_INTERNAL_EXPORT int belle_sip_init_sockets(void);
BELLESIP_INTERNAL_EXPORT void belle_sip_uninit_sockets(void);
int belle_sip_socket_set_nonblocking (belle_sip_socket_t sock);
int belle_sip_socket_set_dscp(belle_sip_socket_t sock, int ai_family, int dscp);
int belle_sip_socket_enable_dual_stack(belle_sip_socket_t sock);
#if defined(WIN32)
......
......@@ -131,6 +131,9 @@ int stream_channel_connect(belle_sip_stream_channel_t *obj, const struct addrinf
belle_sip_error("setsockopt TCP_NODELAY failed: [%s]",belle_sip_get_socket_error_string());
}
belle_sip_socket_set_nonblocking(sock);
if (ai->ai_family==AF_INET6){
belle_sip_socket_enable_dual_stack(sock);
}
err = connect(sock,ai->ai_addr,ai->ai_addrlen);
if (err != 0 && get_socket_error()!=BELLESIP_EINPROGRESS && get_socket_error()!=BELLESIP_EWOULDBLOCK) {
......
......@@ -85,7 +85,7 @@ static belle_sip_socket_t create_server_socket(const char *addr, int * port, int
}
*family=res->ai_family;
sock=socket(res->ai_family,res->ai_socktype,res->ai_protocol);
if (sock==-1){
if (sock==(belle_sip_socket_t)-1){
belle_sip_error("Cannot create TCP socket: %s",belle_sip_get_socket_error_string());
freeaddrinfo(res);
return -1;
......@@ -95,6 +95,9 @@ static belle_sip_socket_t create_server_socket(const char *addr, int * port, int
if (err == -1){
belle_sip_warning ("Fail to set SIP/TCP address reusable: %s.", belle_sip_get_socket_error_string());
}
if (res->ai_family==AF_INET6){
belle_sip_socket_enable_dual_stack(sock);
}
err=bind(sock,res->ai_addr,res->ai_addrlen);
if (err==-1){
......@@ -129,6 +132,7 @@ static belle_sip_socket_t create_server_socket(const char *addr, int * port, int
void belle_sip_stream_listening_point_setup_server_socket(belle_sip_stream_listening_point_t *obj, belle_sip_source_func_t on_new_connection_cb ){
int port=belle_sip_uri_get_port(obj->base.listening_uri);
obj->server_sock=create_server_socket(belle_sip_uri_get_host(obj->base.listening_uri),
&port, &obj->base.ai_family);
if (obj->server_sock==(belle_sip_socket_t)-1) return;
......
......@@ -90,6 +90,9 @@ static belle_sip_socket_t create_udp_socket(const char *addr, int *port, int *fa
if (err == -1){
belle_sip_warning ("Fail to set SIP/UDP address reusable: %s.", belle_sip_get_socket_error_string());
}
if (res->ai_family==AF_INET6){
belle_sip_socket_enable_dual_stack(sock);
}
err=bind(sock,res->ai_addr,res->ai_addrlen);
if (err==-1){
......
......@@ -584,12 +584,10 @@ static void testMalformedFrom(void){
listener_cbs.process_response_event = testMalformedFrom_process_response_cb;
listener = belle_sip_listener_create_from_callbacks(&listener_cbs, &called_times);
belle_sip_provider_add_sip_listener(provider, listener);
belle_sip_object_ref(message);
belle_sip_object_ref(message); /* double ref: originally the message is created with 0 refcount, and dispatch_message will unref() it.*/
belle_sip_provider_dispatch_message(provider, message);
// we expect the stack to send a 400 error
belle_sip_stack_sleep(stack,1000);
......
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