Commit ca677643 authored by Simon Morlat's avatar Simon Morlat
Browse files

Merge remote-tracking branch 'origin/dev_win32'

parents 57b0c388 714ab988
......@@ -134,6 +134,7 @@ case "$target_os" in
;;
*mingw*)
CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0501"
LIBS="$LIBS -lws2_32"
;;
esac
......
......@@ -28,7 +28,7 @@
typedef struct belle_sip_source belle_sip_source_t;
int belle_sip_source_set_events(belle_sip_source_t* source, int event_mask);
belle_sip_fd_t belle_sip_source_get_fd(const belle_sip_source_t* source);
belle_sip_socket_t belle_sip_source_get_socket(const belle_sip_source_t* source);
/**
* Callback function prototype for main loop notifications.
......@@ -76,10 +76,12 @@ void belle_sip_source_set_timeout(belle_sip_source_t *s, unsigned int value_ms);
unsigned int belle_sip_source_get_timeout(const belle_sip_source_t *s);
belle_sip_source_t * belle_sip_fd_source_new(belle_sip_source_func_t func, void *data, int fd, unsigned int events, unsigned int timeout_value_ms);
belle_sip_source_t * belle_sip_socket_source_new(belle_sip_source_func_t func, void *data, belle_sip_socket_t fd, unsigned int events, unsigned int timeout_value_ms);
unsigned long belle_sip_source_get_id(belle_sip_source_t *s);
belle_sip_source_t *belle_sip_main_loop_find_source(belle_sip_main_loop_t *ml, unsigned long id);
/**
* Executes the main loop forever (or until belle_sip_main_loop_quit() is called)
**/
......
......@@ -20,8 +20,8 @@
#define BELLE_SIP_MESSAGE(obj) BELLE_SIP_CAST(obj,belle_sip_message_t)
#define BELLE_SIP_REQUEST(obj) BELLE_SIP_CAST(obj,belle_sip_request_t)
#define BELLE_SIP_MESSAGE(obj) BELLE_SIP_CAST(obj,belle_sip_message_t)
#define BELLE_SIP_REQUEST(obj) BELLE_SIP_CAST(obj,belle_sip_request_t)
#define BELLE_SIP_RESPONSE(obj) BELLE_SIP_CAST(obj,belle_sip_response_t)
BELLE_SIP_BEGIN_DECLS
......
......@@ -24,6 +24,10 @@
#include <errno.h>
#include <unistd.h>
#ifdef WIN32
#include <windows.h>
#endif
/***************/
/* logging api */
/***************/
......@@ -137,13 +141,20 @@ char * belle_sip_octets_to_text(const unsigned char *hash, size_t hash_len, char
char * belle_sip_create_tag(char *ret, size_t size);
#if defined(WIN32) || defined(WIN32_WCE)
typedef SOCKET belle_sip_fd_t;
const char* belle_sip_version_to_string();
#if defined(WIN32)
#include <winsock2.h>
typedef SOCKET belle_sip_socket_t;
typedef HANDLE belle_sip_fd_t;
#else
typedef int belle_sip_socket_t;
typedef int belle_sip_fd_t;
#endif
const char* belle_sip_version_to_string();
BELLE_SIP_END_DECLS
#endif
......
......@@ -29,6 +29,7 @@ lib_LTLIBRARIES=libbellesip.la
libbellesip_la_SOURCES= \
clock_gettime.c clock_gettime.h \
port.c port.h \
belle_sip_uri_impl.c \
belle_sip_headers_impl.c \
belle_sip_utils.c belle_sip_internal.h \
......@@ -67,6 +68,8 @@ libbellesip_la_CFLAGS=$(STRICT_OPTIONS) $(ANTLR_CFLAGS) $(TLS_CFLAGS)
libbellesip_la_LIBADD=libbellesip_generated.la $(ANTLR_LIBS) $(TLS_LIBS)
libbellesip_la_LDFLAGS=-no-undefined
INCLUDES=-I$(top_srcdir)/include
......@@ -77,3 +80,4 @@ CLEANFILES=$(generated_src) *.tokens generated_src_stamp
discovery:
touch specs.cpp
$(CC) $(CFLAGS) -include $(top_builddir)/config.h $(ANTLR_CFLAGS) $(CUNIT_CFLAGS) $(TLS_CFLAGS) -E -P -v -dD specs.cpp
......@@ -24,28 +24,11 @@
#include <sys/types.h>
#include <errno.h>
#ifndef WIN32
#include <stdint.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <pthread.h>
#else
#include <ws2tcpip.h>
#include <winsock2.h>
#include <pthread.h>
#endif
/* include all public headers*/
#include "belle-sip/belle-sip.h"
#include "port.h"
#ifdef PACKAGE
#undef PACKAGE
#endif
......@@ -72,42 +55,6 @@
#include "config.h"
#endif
#if defined(WIN32) || defined(WIN32_WCE)
static inline void close_socket(belle_sip_fd_t s){
closesocket(s);
}
static inline int get_socket_error(void){
return WSAGetLastError();
}
const char *getSocketErrorString();
#define belle_sip_get_socket_error_string() getSocketErrorString()
#define belle_sip_get_socket_error_string_from_code(code) getSocketErrorString()
#define usleep(us) Sleep((us)/1000)
static inline int inet_aton(const char *ip, struct in_addr *p){
*(long*)p=inet_addr(ip);
return 0;
}
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EINPROGRESS WSAEINPROGRESS
#else
static inline void close_socket(belle_sip_fd_t s){
close(s);
}
static inline int get_socket_error(void){
return errno;
}
#define belle_sip_get_socket_error_string() strerror(errno)
#define belle_sip_get_socket_error_string_from_code(code) strerror(code)
#endif
/*etc*/
#define BELLE_SIP_INTERFACE_GET_METHODS(obj,interface) \
......@@ -241,9 +188,12 @@ struct belle_sip_source{
belle_sip_source_remove_callback_t on_remove;
unsigned char cancelled;
unsigned char expired;
belle_sip_socket_t sock;
};
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);
#define belle_list_next(elem) ((elem)->next)
......@@ -486,16 +436,7 @@ void belle_sip_parameters_init(belle_sip_parameters_t *obj);
* Listening points
*/
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
#define BELLE_SIP_LISTENING_POINT(obj) BELLE_SIP_CAST(obj,belle_sip_listening_point_t)
void belle_sip_listening_point_remove_channel(belle_sip_listening_point_t *lp, belle_sip_channel_t *chan);
#include "listeningpoint_internal.h"
/*
belle_sip_stack_t
......
......@@ -19,19 +19,117 @@
#include "belle-sip/belle-sip.h"
#include "belle_sip_internal.h"
#include <malloc.h>
#ifndef WIN32
#include <unistd.h>
#include <poll.h>
typedef struct pollfd belle_sip_pollfd_t;
static int belle_sip_poll(belle_sip_pollfd_t *pfd, int count, int duration){
int err;
err=poll(pfd,count,duration);
if (err==-1 && errno!=EINTR)
belle_sip_error("poll() error: %s",strerror(errno));
return err;
}
/*
Poll() based implementation of event loop.
*/
static int belle_sip_event_to_poll(unsigned int events){
int ret=0;
if (events & BELLE_SIP_EVENT_READ)
ret|=POLLIN;
if (events & BELLE_SIP_EVENT_WRITE)
ret|=POLLOUT;
if (events & BELLE_SIP_EVENT_ERROR)
ret|=POLLERR;
return ret;
}
static unsigned int belle_sip_poll_to_event(belle_sip_pollfd_t * pfd){
unsigned int ret=0;
short events=pfd->revents;
if (events & POLLIN)
ret|=BELLE_SIP_EVENT_READ;
if (events & POLLOUT)
ret|=BELLE_SIP_EVENT_WRITE;
if (events & POLLERR)
ret|=BELLE_SIP_EVENT_ERROR;
return ret;
}
static void belle_sip_source_to_poll(belle_sip_source_t *s, belle_sip_pollfd_t *pfd, int i){
pfd[i].fd=s->fd;
pfd[i].events=belle_sip_event_to_poll(s->events);
pfd[i].revents=0;
s->index=i;
}
static unsigned int belle_sip_source_get_revents(belle_sip_source_t *s,belle_sip_pollfd_t *pfd){
return belle_sip_poll_to_event(pfd[s->index]);
}
#else
typedef HANDLE belle_sip_pollfd_t;
static void belle_sip_source_to_poll(belle_sip_source_t *s, belle_sip_pollfd_t *pfd,int i){
int err;
long events=0;
pfd[i]=s->fd;
s->index=i;
if (s->events & BELLE_SIP_EVENT_READ)
events|=FD_READ;
if (s->events & BELLE_SIP_EVENT_WRITE)
events|=FD_WRITE;
err=WSAEventSelect(s->sock,s->fd,events);
if (err!=0) belle_sip_error("WSAEventSelect() failed: %i",err);
}
static unsigned int belle_sip_source_get_revents(belle_sip_source_t *s,belle_sip_pollfd_t *pfd){
WSANETWORKEVENTS revents={0};
int err;
unsigned int ret=0;
err=WSAEnumNetworkEvents(s->sock,NULL,&revents);
if (err!=0){
belle_sip_error("WSAEnumNetworkEvents() failed: %i",err);
return 0;
}
if (revents.lNetworkEvents & FD_READ)
ret|=BELLE_SIP_EVENT_READ;
if (revents.lNetworkEvents & FD_WRITE)
ret|=BELLE_SIP_EVENT_WRITE;
return ret;
}
static int belle_sip_poll(belle_sip_pollfd_t *pfd, int count, int duration){
DWORD ret=WaitForMultipleObjectsEx(count,pfd,FALSE,duration,FALSE);
if (ret==WAIT_FAILED){
belle_sip_error("WaitForMultipleObjectsEx() failed.");
return -1;
}
if (ret==WAIT_TIMEOUT){
return 0;
}
return ret-WAIT_OBJECT_0;
}
#endif
static void belle_sip_source_destroy(belle_sip_source_t *obj){
if (obj->node.next || obj->node.prev){
belle_sip_fatal("Destroying source currently used in main loop !");
}
belle_sip_source_uninit(obj);
}
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){
static void belle_sip_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){
static unsigned long global_id=1;
s->node.data=s;
s->id=global_id++;
......@@ -42,17 +140,54 @@ void belle_sip_fd_source_init(belle_sip_source_t *s, belle_sip_source_func_t fun
s->notify=func;
}
void belle_sip_source_uninit(belle_sip_source_t *obj){
#ifdef WIN32
if (obj->sock!=(belle_sip_socket_t)-1){
WSACloseEvent(obj->fd);
obj->fd=(WSAEVENT)-1;
}
#endif
obj->fd=(belle_sip_fd_t)-1;
obj->sock=(belle_sip_socket_t)-1;
}
void belle_sip_socket_source_init(belle_sip_source_t *s, belle_sip_source_func_t func, void *data, belle_sip_socket_t sock, unsigned int events, unsigned int timeout_value_ms){
s->sock=sock;
#ifdef WIN32
/*on windows, the fd to poll is not the socket */
belle_sip_fd_t fd=(belle_sip_fd_t)-1;
if (sock!=(belle_sip_socket_t)-1)
fd=WSACreateEvent();
else
fd=(WSAEVENT)-1;
belle_sip_source_init(s,func,data,fd,events,timeout_value_ms);
#else
belle_sip_source_init(s,func,data,sock,events,timeout_value_ms);
#endif
}
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){
belle_sip_source_init(s,func,data,fd,events,timeout_value_ms);
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_source_t);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_source_t,belle_sip_object_t,belle_sip_source_destroy,NULL,NULL,FALSE);
belle_sip_source_t * belle_sip_fd_source_new(belle_sip_source_func_t func, void *data, int fd, unsigned int events, unsigned int timeout_value_ms){
belle_sip_source_t * belle_sip_socket_source_new(belle_sip_source_func_t func, void *data, belle_sip_socket_t sock, unsigned int events, unsigned int timeout_value_ms){
belle_sip_source_t *s=belle_sip_object_new(belle_sip_source_t);
belle_sip_socket_source_init(s,func,data,sock,events,timeout_value_ms);
return s;
}
belle_sip_source_t * belle_sip_fd_source_new(belle_sip_source_func_t func, void *data, belle_sip_fd_t fd, unsigned int events, unsigned int timeout_value_ms){
belle_sip_source_t *s=belle_sip_object_new(belle_sip_source_t);
belle_sip_fd_source_init(s,func,data,fd,events,timeout_value_ms);
return s;
}
belle_sip_source_t * belle_sip_timeout_source_new(belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms){
return belle_sip_fd_source_new(func,data,-1,0,timeout_value_ms);
return belle_sip_socket_source_new(func,data,(belle_sip_socket_t)-1,0,timeout_value_ms);
}
unsigned long belle_sip_source_get_id(belle_sip_source_t *s){
......@@ -64,18 +199,16 @@ int belle_sip_source_set_events(belle_sip_source_t* source, int event_mask) {
return 0;
}
belle_sip_fd_t belle_sip_source_get_fd(const belle_sip_source_t* source) {
return source->fd;
belle_sip_socket_t belle_sip_source_get_socket(const belle_sip_source_t* source) {
return source->sock;
}
struct belle_sip_main_loop{
belle_sip_object_t base;
belle_sip_list_t *sources;
belle_sip_source_t *control;
int nsources;
int run;
int control_fds[2];
};
void belle_sip_main_loop_remove_source(belle_sip_main_loop_t *ml, belle_sip_source_t *source){
......@@ -91,37 +224,17 @@ void belle_sip_main_loop_remove_source(belle_sip_main_loop_t *ml, belle_sip_sour
static void belle_sip_main_loop_destroy(belle_sip_main_loop_t *ml){
belle_sip_main_loop_remove_source(ml,ml->control);
while (ml->sources){
belle_sip_main_loop_remove_source(ml,(belle_sip_source_t*)ml->sources->data);
}
close(ml->control_fds[0]);
close(ml->control_fds[1]);
belle_sip_object_unref(ml->control);
belle_sip_object_delete_unowned();
}
static int main_loop_done(void *data, unsigned int events){
belle_sip_main_loop_t * m=(belle_sip_main_loop_t*)data;
char tmp;
if (read(m->control_fds[0],&tmp,sizeof(tmp))!=1){
belle_sip_error("Problem on control fd of main loop.");
}
return TRUE;
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_main_loop_t);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_main_loop_t,belle_sip_object_t,belle_sip_main_loop_destroy,NULL,NULL,FALSE);
belle_sip_main_loop_t *belle_sip_main_loop_new(void){
belle_sip_main_loop_t*m=belle_sip_object_new(belle_sip_main_loop_t);
if (pipe(m->control_fds)==-1){
belle_sip_fatal("Could not create control pipe.");
}
m->control=belle_sip_fd_source_new(main_loop_done,m,m->control_fds[0],BELLE_SIP_EVENT_READ,-1);
belle_sip_object_set_name((belle_sip_object_t*)m->control,"main loop control fd");
belle_sip_main_loop_add_source(m,m->control);
return m;
}
......@@ -166,42 +279,21 @@ static int match_source_id(const void *s, const void *pid){
return -1;
}
void belle_sip_main_loop_cancel_source(belle_sip_main_loop_t *ml, unsigned long id){
belle_sip_source_t *belle_sip_main_loop_find_source(belle_sip_main_loop_t *ml, unsigned long id){
belle_sip_list_t *elem=belle_sip_list_find_custom(ml->sources,match_source_id,(const void*)id);
if (elem!=NULL){
belle_sip_source_t *s=(belle_sip_source_t*)elem->data;
s->cancelled=TRUE;
return (belle_sip_source_t*)elem->data;
}
return NULL;
}
/*
Poll() based implementation of event loop.
*/
static int belle_sip_event_to_poll(unsigned int events){
int ret=0;
if (events & BELLE_SIP_EVENT_READ)
ret|=POLLIN;
if (events & BELLE_SIP_EVENT_WRITE)
ret|=POLLOUT;
if (events & BELLE_SIP_EVENT_ERROR)
ret|=POLLERR;
return ret;
}
static unsigned int belle_sip_poll_to_event(short events){
unsigned int ret=0;
if (events & POLLIN)
ret|=BELLE_SIP_EVENT_READ;
if (events & POLLOUT)
ret|=BELLE_SIP_EVENT_WRITE;
if (events & POLLERR)
ret|=BELLE_SIP_EVENT_ERROR;
return ret;
void belle_sip_main_loop_cancel_source(belle_sip_main_loop_t *ml, unsigned long id){
belle_sip_source_t *s=belle_sip_main_loop_find_source(ml,id);
if (s) s->cancelled=TRUE;
}
void belle_sip_main_loop_iterate(belle_sip_main_loop_t *ml){
struct pollfd *pfd=(struct pollfd*)alloca(ml->nsources*sizeof(struct pollfd));
belle_sip_pollfd_t *pfd=(belle_sip_pollfd_t*)alloca(ml->nsources*sizeof(belle_sip_pollfd_t));
int i=0;
belle_sip_source_t *s;
belle_sip_list_t *elem,*next;
......@@ -216,11 +308,8 @@ void belle_sip_main_loop_iterate(belle_sip_main_loop_t *ml){
next=elem->next;
s=(belle_sip_source_t*)elem->data;
if (!s->cancelled){
if (s->fd!=-1){
pfd[i].fd=s->fd;
pfd[i].events=belle_sip_event_to_poll (s->events);
pfd[i].revents=0;
s->index=i;
if (s->fd!=(belle_sip_fd_t)-1){
belle_sip_source_to_poll(s,pfd,i);
++i;
}
if (s->timeout>=0){
......@@ -241,9 +330,8 @@ void belle_sip_main_loop_iterate(belle_sip_main_loop_t *ml){
duration=0;
}
/* do the poll */
ret=poll(pfd,i,duration);
if (ret==-1 && errno!=EINTR){
belle_sip_error("poll() error: %s",strerror(errno));
ret=belle_sip_poll(pfd,i,duration);
if (ret==-1){
return;
}
cur=belle_sip_time_ms();
......@@ -254,10 +342,8 @@ void belle_sip_main_loop_iterate(belle_sip_main_loop_t *ml){
s=(belle_sip_source_t*)elem->data;
if (!s->cancelled){
if (s->fd!=-1){
if (pfd[s->index].revents!=0){
revents=belle_sip_poll_to_event(pfd[s->index].revents);
}
if (s->fd!=(belle_sip_fd_t)-1){
revents=belle_sip_source_get_revents(s,pfd);
}
if (revents!=0 || (s->timeout>=0 && cur>=s->expire_ms)){
char *objdesc=belle_sip_object_to_string((belle_sip_object_t*)s);
......@@ -289,9 +375,6 @@ void belle_sip_main_loop_run(belle_sip_main_loop_t *ml){
int belle_sip_main_loop_quit(belle_sip_main_loop_t *ml){
ml->run=0;
//if (write(ml->control_fds[1],"a",1)==-1){
// belle_sip_error("Fail to write to main loop control fd.");
//}
return BELLE_SIP_STOP;
}
......@@ -299,5 +382,5 @@ void belle_sip_main_loop_sleep(belle_sip_main_loop_t *ml, int milliseconds){
unsigned long timer_id = belle_sip_main_loop_add_timeout(ml,(belle_sip_source_func_t)belle_sip_main_loop_quit,ml,milliseconds);
belle_sip_main_loop_run(ml);
belle_sip_main_loop_cancel_source(ml,timer_id);
}
......@@ -47,42 +47,44 @@ struct addrinfo * belle_sip_ip_address_to_addrinfo(const char *ipaddress, int po
}
void belle_sip_resolver_context_destroy(belle_sip_resolver_context_t *ctx){
static void belle_sip_resolver_context_destroy(belle_sip_resolver_context_t *ctx){
if (ctx->thread!=0){
if (!ctx->exited){
ctx->cancelled=1;
pthread_cancel(ctx->thread);
}
pthread_join(ctx->thread,NULL);
belle_sip_thread_join(ctx->thread,NULL);
}
if (ctx->name)
belle_sip_free(ctx->name);
if (ctx->ai){
freeaddrinfo(ctx->ai);
}
#ifndef WIN32
close(ctx->ctlpipe[0]);
close(ctx->ctlpipe[1]);
#endif
}
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);
static int resolver_callback(belle_sip_resolver_context_t *ctx){
char tmp;
ctx->cb(ctx->cb_data, ctx->name, ctx->ai);
ctx->ai=NULL;
if (read(ctx->source.fd,&tmp,1)!=1){
belle_sip_fatal("Unexpected read from resolver_callback");
belle_sip_message("resolver_callback() for %s called.",ctx->name);
if (!ctx->cancelled){
ctx->cb(ctx->cb_data, ctx->name, ctx->ai);
ctx->ai=NULL;
}
#ifndef WIN32
{
char tmp;
if (read(ctx->source.fd,&tmp,1)!=1){
belle_sip_fatal("Unexpected read from resolver_callback");
}
}
#endif
/*by returning stop, we'll be removed from main loop and destroyed. */
return BELLE_SIP_STOP;
}
belle_sip_resolver_context_t *belle_sip_resolver_context_new(){
belle_sip_resolver_context_t *ctx=belle_sip_object_new(belle_sip_resolver_context_t);
if (pipe(ctx->ctlpipe)==-1){
belle_sip_fatal("pipe() failed: %s",strerror(errno));
}
belle_sip_fd_source_init(&ctx->source,(belle_sip_source_func_t)resolver_callback,ctx,ctx->ctlpipe[0],BELLE_SIP_EVENT_READ,-1);
return ctx;
}
......@@ -93,9 +95,12 @@ static void *belle_sip_resolver_thread(void *ptr){
char serv[10];
int err;
/*the thread owns a ref on the resolver context*/
belle_sip_object_ref(ctx);
belle_sip_message("Resolver thread started.");
snprintf(serv,sizeof(serv),"%i",ctx->port);
hints.ai_family=(ctx->hints & BELLE_SIP_RESOLVER_HINT_IPV6) ? AF_INET6 : AF_INET;
hints.ai_family=ctx->family;
hints.ai_flags=AI_NUMERICSERV;
err=getaddrinfo(ctx->name,serv,&hints,&res);
if (err!=0){
......@@ -106,14 +111,30 @@ static void *belle_sip_resolver_thread(void *ptr){
belle_sip_message("%s has address %s.",ctx->name,host);