Commit f42c9d12 authored by Simon Morlat's avatar Simon Morlat

resolver and main loop in progress.

parent e25a3bdc
......@@ -80,6 +80,8 @@ belle_sip_source_t * belle_sip_socket_source_new(belle_sip_source_func_t func, v
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
......
......@@ -148,8 +148,10 @@ const char* belle_sip_version_to_string();
#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
......
......@@ -178,7 +178,7 @@ struct belle_sip_source{
belle_sip_object_t base;
belle_sip_list_t node;
unsigned long id;
belle_sip_socket_t fd;
belle_sip_fd_t fd;
unsigned int events;
int timeout;
void *data;
......@@ -188,12 +188,11 @@ struct belle_sip_source{
belle_sip_source_remove_callback_t on_remove;
unsigned char cancelled;
unsigned char expired;
#ifdef WIN32
WSAEVENT wsaevent;
#endif
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);
#define belle_list_next(elem) ((elem)->next)
/* include private headers */
......
......@@ -77,12 +77,35 @@ static unsigned int belle_sip_source_get_revents(belle_sip_source_t *s,belle_sip
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){
pfd[i]=s->wsaevent;
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){
return 0;
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){
......@@ -104,14 +127,14 @@ static void belle_sip_source_destroy(belle_sip_source_t *obj){
belle_sip_fatal("Destroying source currently used in main loop !");
}
#ifdef WIN32
if (obj->wsaevent!=(WSAEVENT)-1){
WSACloseEvent(obj->wsaevent);
obj->wsaevent=(WSAEVENT)-1;
if (obj->sock!=(belle_sip_socket_t)-1){
WSACloseEvent(obj->fd);
obj->fd=(WSAEVENT)-1;
}
#endif
}
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){
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++;
......@@ -120,20 +143,40 @@ void belle_sip_socket_source_init(belle_sip_source_t *s, belle_sip_source_func_t
s->timeout=timeout_value_ms;
s->data=data;
s->notify=func;
}
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
if (fd!=(belle_sip_socket_t)-1)
s->wsaevent=WSACreateEvent();
/*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
s->wsaevent=(WSAEVENT)-1;
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_socket_source_new(belle_sip_source_func_t func, void *data, belle_sip_socket_t 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,fd,events,timeout_value_ms);
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;
}
......@@ -151,7 +194,7 @@ int belle_sip_source_set_events(belle_sip_source_t* source, int event_mask) {
}
belle_sip_socket_t belle_sip_source_get_socket(const belle_sip_source_t* source) {
return source->fd;
return source->sock;
}
......@@ -230,12 +273,17 @@ 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;
}
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){
......@@ -254,7 +302,7 @@ 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!=(belle_sip_socket_t)-1){
if (s->fd!=(belle_sip_fd_t)-1){
belle_sip_source_to_poll(s,pfd,i);
++i;
}
......@@ -288,7 +336,7 @@ 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!=(belle_sip_socket_t)-1){
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)){
......
......@@ -47,12 +47,8 @@ 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;
belle_sip_thread_cancel(ctx->thread);
}
belle_sip_thread_join(ctx->thread,NULL);
}
if (ctx->name)
......@@ -63,8 +59,6 @@ void belle_sip_resolver_context_destroy(belle_sip_resolver_context_t *ctx){
#ifndef WIN32
close(ctx->ctlpipe[0]);
close(ctx->ctlpipe[1]);
#else
CloseEvent(ctx->ctlevent);
#endif
}
......@@ -72,27 +66,25 @@ 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;
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
if (read(ctx->source.fd,&tmp,1)!=1){
belle_sip_fatal("Unexpected read from resolver_callback");
{
char tmp;
if (read(ctx->source.fd,&tmp,1)!=1){
belle_sip_fatal("Unexpected read from resolver_callback");
}
}
#else
#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);
#ifndef WIN32
if (pipe(ctx->ctlpipe)==-1){
belle_sip_fatal("pipe() failed: %s",strerror(errno));
}
#else
#endif
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;
}
......@@ -103,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){
......@@ -120,13 +115,26 @@ static void *belle_sip_resolver_thread(void *ptr){
if (write(ctx->ctlpipe[1],"q",1)==-1){
belle_sip_error("belle_sip_resolver_thread(): Fail to write on pipe.");
}
#else
SetEvent(ctx->ctlevent);
#endif
belle_sip_object_unref(ctx);
return NULL;
}
unsigned long belle_sip_resolve(const char *name, int port, unsigned int hints, belle_sip_resolver_callback_t cb , void *data, belle_sip_main_loop_t *ml){
static void belle_sip_resolver_context_start(belle_sip_resolver_context_t *ctx){
belle_sip_fd_t fd=(belle_sip_fd_t)-1;
belle_sip_thread_create(&ctx->thread,NULL,belle_sip_resolver_thread,ctx);
#ifndef WIN32
if (pipe(ctx->ctlpipe)==-1){
belle_sip_fatal("pipe() failed: %s",strerror(errno));
}
fd=ctx->ctlpipe[0];
#else
fd=(HANDLE)ctx->thread;
#endif
belle_sip_fd_source_init(&ctx->source,(belle_sip_source_func_t)resolver_callback,ctx,fd,BELLE_SIP_EVENT_READ,-1);
}
unsigned long belle_sip_resolve(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);
if (res==NULL){
/*then perform asynchronous DNS query */
......@@ -135,10 +143,13 @@ unsigned long belle_sip_resolve(const char *name, int port, unsigned int hints,
ctx->cb=cb;
ctx->name=belle_sip_strdup(name);
ctx->port=port;
ctx->hints=hints;
if (family==0) family=AF_UNSPEC;
ctx->family=family;
belle_sip_resolver_context_start(ctx);
/*the resolver context must never be removed manually from the main loop*/
belle_sip_main_loop_add_source(ml,(belle_sip_source_t*)ctx);
belle_sip_object_unref(ctx);
belle_sip_thread_create(&ctx->thread,NULL,belle_sip_resolver_thread,ctx);
belle_sip_object_unref(ctx);/*the main loop and the thread have a ref on it*/
return ctx->source.id;
}else{
cb(data,name,res);
......@@ -146,6 +157,16 @@ unsigned long belle_sip_resolve(const char *name, int port, unsigned int hints,
}
}
void belle_sip_resolve_cancel(belle_sip_main_loop_t *ml, unsigned long id){
if (id!=0){
belle_sip_source_t *s=belle_sip_main_loop_find_source(ml,id);
if (s){
belle_sip_resolver_context_t *res=BELLE_SIP_RESOLVER_CONTEXT(s);
res->cancelled=1;
}
}
}
void belle_sip_get_src_addr_for(const struct sockaddr *dest, socklen_t destlen, struct sockaddr *src, socklen_t *srclen){
int af_type=(destlen==sizeof(struct sockaddr_in6)) ? AF_INET6 : AF_INET;
int sock=socket(af_type,SOCK_DGRAM,IPPROTO_UDP);
......
......@@ -25,6 +25,8 @@
typedef struct belle_sip_resolver_context belle_sip_resolver_context_t;
#define BELLE_SIP_RESOLVER_CONTEXT(obj) BELLE_SIP_CAST(obj,belle_sip_resolver_context_t)
/**
* Callback prototype for asynchronous DNS resolution. The result addrinfo must be taken and (possibly later) freed by
* the callee, using freeaddrinfo().
......@@ -39,7 +41,7 @@ struct belle_sip_resolver_context{
char *name;
int port;
struct addrinfo *ai;
unsigned int hints;
int family;
belle_sip_thread_t thread;
#ifndef WIN32
int ctlpipe[2];
......@@ -51,7 +53,8 @@ struct belle_sip_resolver_context{
};
struct addrinfo * belle_sip_ip_address_to_addrinfo(const char *ipaddress, int port);
unsigned long belle_sip_resolve(const char *name, int port, unsigned int hints, belle_sip_resolver_callback_t cb , void *data, belle_sip_main_loop_t *ml);
unsigned long belle_sip_resolve(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);
......
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