Commit 5e726858 authored by Simon Morlat's avatar Simon Morlat

implement machinery for sending messages asynchronously

parent 5e9a9c7d
......@@ -11,6 +11,9 @@ bellesip_HEADERS=\
transport.h \
listeningpoint.h \
sipstack.h \
provider.h \
listener.h \
dialog.h \
belle-sip.h
EXTRA_DIST=$(bellesip_HEADERS)
......@@ -44,15 +44,19 @@ typedef enum belle_sip_type_id{
BELLE_SIP_TYPE_ID(belle_sip_transaction_t),
BELLE_SIP_TYPE_ID(belle_sip_server_transaction_t),
BELLE_SIP_TYPE_ID(belle_sip_client_transaction_t),
BELLE_SIP_TYPE_ID(belle_sip_transport_t),
BELLE_SIP_TYPE_ID(belle_sip_dialog_t),
BELLE_SIP_TYPE_ID(belle_sip_header_address_t),
BELLE_SIP_TYPE_ID(belle_sip_header_contact_t),
BELLE_SIP_TYPE_ID(belle_sip_header_from_t),
BELLE_SIP_TYPE_ID(belle_sip_header_to_t),
BELLE_SIP_TYPE_ID(belle_sip_header_via_t),
BELLE_SIP_TYPE_ID(belle_sip_uri_t),
BELLE_SIP_TYPE_ID(belle_sip_message_t),
BELLE_SIP_TYPE_ID(belle_sip_request_t),
BELLE_SIP_TYPE_ID(belle_sip_response_t),
BELLE_SIP_TYPE_ID(belle_sip_object_t),
BELLE_SIP_TYPE_ID(belle_sip_parameters_t),
BELLE_SIP_TYPE_ID(belle_sip_sender_task_t),
belle_sip_type_id_end
}belle_sip_type_id_t;
......@@ -99,6 +103,8 @@ BELLE_SIP_END_DECLS
typedef struct belle_sip_listening_point belle_sip_listening_point_t;
typedef struct belle_sip_stack belle_sip_stack_t;
typedef struct belle_sip_provider belle_sip_provider_t;
typedef struct belle_sip_listener belle_sip_listener_t;
typedef struct belle_sip_dialog belle_sip_dialog_t;
#include "belle-sip/list.h"
#include "belle-sip/mainloop.h"
......@@ -107,8 +113,11 @@ typedef struct belle_sip_provider belle_sip_provider_t;
#include "belle-sip/parameters.h"
#include "belle-sip/message.h"
#include "belle-sip/transaction.h"
#include "belle-sip/dialog.h"
#include "belle-sip/sipstack.h"
#include "belle-sip/listeningpoint.h"
#include "belle-sip/provider.h"
#include "belle-sip/listener.h"
#undef TRUE
#define TRUE 1
......
/*
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 3 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 <http://www.gnu.org/licenses/>.
*/
#ifndef belle_sip_dialog_h
#define belle_sip_dialog_h
enum belle_sip_dialog_state{
BELLE_SIP_DIALOG_NULL,
BELLE_SIP_DIALOG_EARLY,
BELLE_SIP_DIALOG_CONFIRMED,
BELLE_SIP_DIALOG_TERMINATED
};
typedef enum belle_sip_dialog_state belle_sip_dialog_state_t;
BELLE_SIP_BEGIN_DECLS
belle_sip_request_t *belle_sip_dialog_create_ack(belle_sip_dialog_t *dialog, unsigned int cseq);
belle_sip_request_t *belle_sip_dialog_create_request(belle_sip_dialog_t *dialog, const char *method);
void belle_sip_dialog_delete(belle_sip_dialog_t *dialog);
void *belle_sip_get_application_data(belle_sip_dialog_t *dialog);
void belle_sip_set_application_data(belle_sip_dialog_t *dialog, void *data);
const char *belle_sip_dialog_get_dialog_id(belle_sip_dialog_t *dialog);
const belle_sip_header_address_t *belle_sip_get_local_party(belle_sip_dialog_t *dialog);
const belle_sip_header_address_t *belle_sip_get_remote_party(belle_sip_dialog_t *dialog);
unsigned int belle_sip_dialog_get_local_seq_number(belle_sip_dialog_t *dialog);
unsigned int belle_sip_dialog_get_remote_seq_number(belle_sip_dialog_t *dialog);
const char *belle_sip_dialog_get_local_tag(belle_sip_dialog_t *dialog);
const char *belle_sip_dialog_get_remote_tag(belle_sip_dialog_t *dialog);
const belle_sip_header_address_t *belle_sip_dialog_get_remote_target(belle_sip_dialog_t *dialog);
const belle_sip_list_t belle_sip_dialog_get_route_set(belle_sip_dialog_t *dialog);
belle_sip_dialog_state_t belle_sip_dialog_get_state(belle_sip_dialog_t *dialog);
int belle_sip_dialog_is_server(belle_sip_dialog_t *dialog);
void belle_sip_dialog_send_ack(belle_sip_dialog_t *dialog, belle_sip_request_t *request);
void belle_sip_dialog_terminate_on_bye(belle_sip_dialog_t *dialog, int val);
BELLE_SIP_END_DECLS
#endif
/*
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 3 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 <http://www.gnu.org/licenses/>.
*/
#ifndef belle_sip_listener_h
#define belle_sip_listener_h
typedef struct belle_sip_dialog_terminated_event belle_sip_dialog_terminated_event_t;
typedef struct belle_sip_io_error_event belle_sip_io_error_event_t;
typedef struct belle_sip_request_event belle_sip_request_event_t;
typedef struct belle_sip_response_event belle_sip_response_event_t;
typedef struct belle_sip_timeout_event belle_sip_timeout_event_t;
typedef struct belle_sip_transaction_terminated_event belle_sip_transaction_terminated_event_t;
struct belle_sip_dialog_terminated_event{
belle_sip_provider_t *source;
belle_sip_dialog_t *dialog;
};
struct belle_sip_io_error_event{
belle_sip_provider_t *source;
char *transport;
char *host;
int port;
};
struct belle_sip_request_event{
belle_sip_provider_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_provider_t *source;
belle_sip_client_transaction_t *client_transaction;
belle_sip_dialog_t *dialog;
belle_sip_request_t *response;
};
struct belle_sip_timeout_event{
belle_sip_provider_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_listener{
void (*process_dialog_terminated)(void *user_ctx, const belle_sip_dialog_terminated_event_t *event);
void (*process_io_error)(void *user_ctx, const belle_sip_io_error_event_t *event);
void (*process_request_event)(void *user_ctx, const belle_sip_request_event_t *event);
void (*process_response_event)(void *user_ctx, const belle_sip_response_event_t *event);
void (*process_timeout)(void *user_ctx, const belle_sip_timeout_event_t *event);
void (*process_transaction_terminated)(void *user_ctx, const belle_sip_transaction_terminated_event_t *event);
};
#endif
......@@ -42,8 +42,6 @@ BELLE_SIP_BEGIN_DECLS
void belle_sip_main_loop_add_source(belle_sip_main_loop_t *ml, belle_sip_source_t *source);
void belle_sip_main_loop_remove_source(belle_sip_main_loop_t *ml, belle_sip_source_t *source);
/**
* Creates a mainloop.
**/
......@@ -68,6 +66,10 @@ unsigned long belle_sip_main_loop_add_timeout(belle_sip_main_loop_t *ml, belle_s
belle_sip_source_t * belle_sip_timeout_source_new(belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms);
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);
unsigned long belle_sip_source_get_id(belle_sip_source_t *s);
/**
* Executes the main loop forever (or until belle_sip_main_loop_quit() is called)
**/
......
......@@ -18,9 +18,15 @@
#ifndef BELLE_SIP_MESSAGE_H
#define BELLE_SIP_MESSAGE_H
typedef struct belle_sip_message bellesip_message_t;
typedef struct belle_sip_message belle_sip_message_t;
typedef struct belle_sip_request belle_sip_request_t;
typedef struct belle_sip_response belle_sip_response_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)
char *belle_sip_message_to_string(belle_sip_message_t *msg);
#endif
/*
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 3 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 <http://www.gnu.org/licenses/>.
*/
#ifndef belle_sip_provider_h
#define belle_sip_provider_h
BELLE_SIP_BEGIN_DECLS
int belle_sip_provider_add_listening_point(belle_sip_provider_t *p, belle_sip_listening_point_t *lp);
void belle_sip_provider_remove_listening_point(belle_sip_provider_t *p, belle_sip_listening_point_t *lp);
belle_sip_listening_point_t *belle_sip_provider_get_listening_point(belle_sip_provider_t *p, const char *transport);
const belle_sip_list_t *belle_sip_provider_get_listening_points(belle_sip_provider_t *p);
void belle_sip_provider_add_sip_listener(belle_sip_provider_t *p, belle_sip_listener_t *l, void *user_ctx);
void belle_sip_provider_remove_sip_listener(belle_sip_provider_t *p, belle_sip_listener_t *l, void *user_ctx);
belle_sip_client_transaction_t *belle_sip_provider_create_client_transaction(belle_sip_provider_t *p, belle_sip_request_t *req);
belle_sip_server_transaction_t *belle_sip_provider_create_server_transaction(belle_sip_provider_t *p, belle_sip_request_t *req);
belle_sip_stack_t *belle_sip_provider_get_sip_stack(belle_sip_provider_t *p);
void belle_sip_provider_send_request(belle_sip_provider_t *p, belle_sip_request_t *req);
void belle_sip_provider_send_response(belle_sip_provider_t *p, belle_sip_response_t *resp);
BELLE_SIP_END_DECLS
#endif
......@@ -20,6 +20,13 @@
#ifndef belle_sip_stack_h
#define belle_sip_stack_h
struct belle_sip_hop{
const char *host;
const char *transport;
int port;
};
typedef struct belle_sip_hop belle_sip_hop_t;
BELLE_SIP_BEGIN_DECLS
......@@ -27,6 +34,8 @@ belle_sip_stack_t * belle_sip_stack_new(const char *properties);
belle_sip_listening_point_t *belle_sip_stack_create_listening_point(belle_sip_stack_t *s, const char *ipaddress, int port, const char *transport);
void belle_sip_stack_delete_listening_point(belle_sip_stack_t *s, belle_sip_listening_point_t *lp);
belle_sip_provider_t *belle_sip_stack_create_provider(belle_sip_stack_t *s, belle_sip_listening_point_t *lp);
void belle_sip_stack_main(belle_sip_stack_t *stack);
......
......@@ -53,12 +53,6 @@ void belle_sip_client_transaction_send_request(belle_sip_client_transaction_t *t
#define BELLE_SIP_CLIENT_TRANSACTION(t) BELLE_SIP_CAST(t,belle_sip_client_transaction_t)
/*to be moved out when belle_sip_provider_t is implemented:*/
belle_sip_client_transaction_t * belle_sip_client_transaction_new(belle_sip_request_t *req);
belle_sip_server_transaction_t * belle_sip_server_transaction_new(belle_sip_request_t *req);
BELLE_SIP_END_DECLS
#endif
......
......@@ -38,7 +38,10 @@ libbellesip_la_SOURCES=clock_gettime.h \
belle_sip_parameters.c \
transaction.c \
listeningpoint.c \
sipstack.c
sipstack.c \
provider.c \
sender_task.c sender_task.h \
message.c
libbellesip_la_CFLAGS=$(STRICT_OPTIONS)
......
......@@ -62,6 +62,7 @@ struct _belle_sip_list {
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;
int fd;
......@@ -72,6 +73,7 @@ struct belle_sip_source{
int index; /* index in pollfd table */
belle_sip_source_func_t notify;
belle_sip_source_remove_callback_t on_remove;
int cancelled;
};
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);
......@@ -94,6 +96,8 @@ char * belle_sip_strdup(const char *s);
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_find_custom(belle_sip_list_t *list, belle_sip_compare_func compare_func, const void *user_data);
belle_sip_list_t *belle_sip_list_remove_custom(belle_sip_list_t *list, belle_sip_compare_func compare_func, const void *user_data);
belle_sip_list_t * belle_sip_list_free(belle_sip_list_t *list);
#define belle_sip_list_next(elem) ((elem)->next)
/***************/
......@@ -354,7 +358,45 @@ typedef struct belle_sip_udp_listening_point belle_sip_udp_listening_point_t;
belle_sip_listening_point_t * belle_sip_udp_listening_point_new(belle_sip_stack_t *s, const char *ipaddress, int port);
belle_sip_channel_t *belle_sip_listening_point_find_output_channel(belle_sip_listening_point_t *ip, const struct addrinfo *dest);
belle_sip_source_t *belle_sip_channel_create_source(belle_sip_channel_t *, unsigned int events, int timeout, belle_sip_source_func_t callback, void *data);
/*
belle_sip_stack_t
*/
struct belle_sip_stack{
belle_sip_object_t base;
belle_sip_main_loop_t *ml;
belle_sip_list_t *lp;/*list of listening points*/
};
void belle_sip_stack_get_next_hop(belle_sip_stack_t *stack, belle_sip_request_t *req, belle_sip_hop_t *hop);
/*
belle_sip_provider_t
*/
belle_sip_provider_t *belle_sip_provider_new(belle_sip_stack_t *s, belle_sip_listening_point_t *lp);
typedef struct listener_ctx{
belle_sip_listener_t *listener;
void *data;
}listener_ctx_t;
#define BELLE_SIP_PROVIDER_INVOKE_LISTENERS(provider,callback,event) \
{ \
belle_sip_list_t *_elem; \
for(_elem=(provider)->listeners;_elem!=NULL;_elem=_elem->next){ \
listener_ctx_t *_lctx=(listener_ctx_t*)_elem->data; \
_lctx->##callback(_lctx->data,event); \
} \
}
/*
belle_sip_transaction_t
*/
belle_sip_client_transaction_t * belle_sip_client_transaction_new(belle_sip_provider_t *prov,belle_sip_request_t *req);
belle_sip_server_transaction_t * belle_sip_server_transaction_new(belle_sip_provider_t *prov,belle_sip_request_t *req);
#ifdef __cplusplus
}
......@@ -362,5 +404,8 @@ belle_sip_channel_t *belle_sip_listening_point_find_output_channel(belle_sip_lis
/*include private headers */
#include "belle_sip_resolver.h"
#include "sender_task.h"
#define BELLE_SIP_SOCKET_TIMEOUT 30000
#endif
......@@ -33,6 +33,7 @@ static void belle_sip_source_destroy(belle_sip_source_t *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 unsigned long global_id=1;
s->node.data=s;
s->id=global_id++;
s->fd=fd;
s->events=events;
......@@ -41,7 +42,7 @@ void belle_sip_fd_source_init(belle_sip_source_t *s, belle_sip_source_func_t fun
s->notify=func;
}
static 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_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 *s=belle_sip_object_new(belle_sip_source_t, belle_sip_source_destroy);
belle_sip_fd_source_init(s,func,data,fd,events,timeout_value_ms);
return s;
......@@ -51,14 +52,29 @@ belle_sip_source_t * belle_sip_timeout_source_new(belle_sip_source_func_t func,
return belle_sip_fd_source_new(func,data,-1,0,timeout_value_ms);
}
unsigned long belle_sip_source_get_id(belle_sip_source_t *s){
return s->id;
}
struct belle_sip_main_loop{
belle_sip_source_t *sources;
belle_sip_object_t base;
belle_sip_list_t *sources;
belle_sip_source_t *control;
int nsources;
int run;
int control_fds[2];
};
static void belle_sip_main_loop_remove_source(belle_sip_main_loop_t *ml, belle_sip_source_t *source){
ml->sources=belle_sip_list_remove_link(ml->sources,&source->node);
ml->nsources--;
if (source->on_remove)
source->on_remove(source);
belle_sip_object_unref(source);
}
static void belle_sip_main_loop_destroy(belle_sip_main_loop_t *ml){
belle_sip_main_loop_remove_source (ml,ml->control);
belle_sip_source_destroy(ml->control);
......@@ -86,28 +102,37 @@ void belle_sip_main_loop_add_source(belle_sip_main_loop_t *ml, belle_sip_source_
belle_sip_fatal("Source is already linked somewhere else.");
return;
}
belle_sip_object_ref(source);
if (source->timeout>0){
source->expire_ms=belle_sip_time_ms()+source->timeout;
}
ml->sources=(belle_sip_source_t*)belle_sip_list_append_link((belle_sip_list_t*)ml->sources,(belle_sip_list_t*)source);
ml->sources=belle_sip_list_append_link(ml->sources,&source->node);
ml->nsources++;
}
void belle_sip_main_loop_remove_source(belle_sip_main_loop_t *ml, belle_sip_source_t *source){
ml->sources=(belle_sip_source_t*)belle_sip_list_remove_link((belle_sip_list_t*)ml->sources,(belle_sip_list_t*)source);
ml->nsources--;
if (source->on_remove)
source->on_remove(source);
}
unsigned long belle_sip_main_loop_add_timeout(belle_sip_main_loop_t *ml, belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms){
belle_sip_source_t * s=belle_sip_timeout_source_new(func,data,timeout_value_ms);
s->on_remove=belle_sip_source_destroy;
s->on_remove=(belle_sip_source_remove_callback_t)belle_sip_object_unref;
belle_sip_main_loop_add_source(ml,s);
return s->id;
}
static int match_source_id(const void *s, const void *pid){
if ( ((belle_sip_source_t*)s)->id==(unsigned long)pid){
return 0;
}
return -1;
}
void belle_sip_main_loop_cancel_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;
}
}
/*
Poll() based implementation of event loop.
*/
......@@ -137,26 +162,31 @@ static unsigned int belle_sip_poll_to_event(short events){
void belle_sip_main_loop_iterate(belle_sip_main_loop_t *ml){
struct pollfd *pfd=(struct pollfd*)alloca(ml->nsources*sizeof(struct pollfd));
int i=0;
belle_sip_source_t *s,*next;
belle_sip_source_t *s;
belle_sip_list_t *elem,*next;
uint64_t min_time_ms=(uint64_t)-1;
int duration=-1;
int ret;
uint64_t cur;
/*prepare the pollfd table */
for(s=ml->sources;s!=NULL;s=(belle_sip_source_t*)s->node.next){
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;
++i;
}
if (s->timeout>0){
if (min_time_ms>s->expire_ms){
min_time_ms=s->expire_ms;
for(elem=ml->sources;elem!=NULL;elem=next){
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;
++i;
}
if (s->timeout>0){
if (min_time_ms>s->expire_ms){
min_time_ms=s->expire_ms;
}
}
}
}else belle_sip_main_loop_remove_source (ml,s);
}
if (min_time_ms!=(uint64_t)-1 ){
......@@ -176,25 +206,28 @@ void belle_sip_main_loop_iterate(belle_sip_main_loop_t *ml){
}
cur=belle_sip_time_ms();
/* examine poll results*/
for(s=ml->sources;s!=NULL;s=next){
for(elem=ml->sources;elem!=NULL;elem=next){
unsigned revents=0;
next=(belle_sip_source_t*)s->node.next;
if (s->fd!=-1){
if (pfd[s->index].revents!=0){
revents=belle_sip_poll_to_event(pfd[s->index].revents);
s=(belle_sip_source_t*)elem->data;
next=elem->next;
if (!s->cancelled){
if (s->fd!=-1){
if (pfd[s->index].revents!=0){
revents=belle_sip_poll_to_event(pfd[s->index].revents);
}
}
}
if (revents!=0 || (s->timeout>0 && cur>=s->expire_ms)){
ret=s->notify(s->data,revents);
if (ret==0){
/*this source needs to be removed*/
belle_sip_main_loop_remove_source(ml,s);
}else if (revents==0){
/*timeout needs to be started again */
s->expire_ms+=s->timeout;
if (revents!=0 || (s->timeout>0 && cur>=s->expire_ms)){
ret=s->notify(s->data,revents);
if (ret==0){
/*this source needs to be removed*/
belle_sip_main_loop_remove_source(ml,s);
}else if (revents==0){
/*timeout needs to be started again */
s->expire_ms+=s->timeout;
}
}
}
}else belle_sip_main_loop_remove_source(ml,s);
}
}
......
......@@ -76,14 +76,36 @@ static void *belle_sip_resolver_thread(void *ptr){
}
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){
belle_sip_resolver_context_t *ctx=belle_sip_resolver_context_new();
ctx->cb_data=data;
ctx->cb=cb;
ctx->name=belle_sip_strdup(name);
ctx->port=port;
ctx->hints=hints;
belle_sip_main_loop_add_source(ml,(belle_sip_source_t*)ctx);
pthread_create(&ctx->thread,NULL,belle_sip_resolver_thread,ctx);
return ctx->source.id;
struct addrinfo *res=belle_sip_ip_address_to_addrinfo (name, port);
if (res==NULL){
/*then perform asynchronous DNS query */
belle_sip_resolver_context_t *ctx=belle_sip_resolver_context_new();
ctx->cb_data=data;
ctx->cb=cb;
ctx->name=belle_sip_strdup(name);
ctx->port=port;
ctx->hints=hints;
belle_sip_main_loop_add_source(ml,(belle_sip_source_t*)ctx);
pthread_create(&ctx->thread,NULL,belle_sip_resolver_thread,ctx);
return ctx->source.id;
}else{
cb(data,name,res);
return 0;
}
}
struct addrinfo * belle_sip_ip_address_to_addrinfo(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_flags=AI_NUMERICSERV|AI_NUMERICHOST;
err=getaddrinfo(ipaddress,serv,&hints,&res);
if (err!=0){
return NULL;
}
return res;
}
......@@ -55,7 +55,7 @@ struct belle_sip_resolver_context{
uint8_t exited;
};
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);
......
......@@ -271,6 +271,14 @@ belle_sip_list_t* belle_sip_list_find_custom(belle_sip_list_t* list, belle_sip_c
return NULL;
}
belle_sip_list_t *belle_sip_list_remove_custom(belle_sip_list_t *list, belle_sip_compare_func compare_func, const void *user_data){
belle_sip_list_t *elem=belle_sip_list_find_custom(list,compare_func,user_data);
if (elem!=NULL){
list=belle_sip_list_remove_link(list,elem);
}
return list;
}
void * belle_sip_list_nth_data(const belle_sip_list_t* list, int index){
int i;
for(i=0;list!=NULL;list=list->next,++i){
......
......@@ -38,6 +38,7 @@ struct belle_sip_channel{
typedef struct belle_sip_channel_vptr{
int (*channel_send)(belle_sip_channel_t *obj, const void *buf, size_t buflen);
int (*channel_recv)(belle_sip_channel_t *obj, void *buf, size_t buflen);
belle_sip_source_t *(*create_source)(belle_sip_channel_t *obj, unsigned int events, unsigned int timeout, belle_sip_source_func_t callback, void *data);
}belle_sip_channel_vptr_t;
static void belle_sip_channel_init(belle_sip_channel_t *obj){
......@@ -53,6 +54,11 @@ int belle_sip_channel_recv(belle_sip_channel_t *obj, void *buf, size_t buflen){
return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_vptr_t)->channel_recv(obj,buf,buflen);
}
belle_sip_source_t *belle_sip_channel_create_source(belle_sip_channel_t *obj, unsigned int events, int timeout, belle_sip_source_func_t callback, void *data){
return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_vptr_t)->create_source(obj,events,timeout,callback,data);
}
const struct addrinfo * belle_sip_channel_get_peer(belle_sip_channel_t *obj){
return &obj->peer;
}
......@@ -75,6 +81,7 @@ static int udp_channel_send(belle_sip_channel_t *obj, const void *buf, size_t bu
err=sendto(chan->sock,buf,buflen,0,obj->peer.ai_addr,obj->peer.ai_addrlen);
if (err==-1){
belle_sip_error("Could not send UDP packet: %s",strerror(errno));
return -errno;
}
return err;
}
......@@ -86,18 +93,20 @@ static int udp_channel_recv(belle_sip_channel_t *obj, void *buf, size_t buflen){
err=recvfrom(chan->sock,buf,buflen,MSG_DONTWAIT,obj->peer.ai_addr,&obj->peer.ai_addrlen);
if (err==-1 && errno!=EWOULDBLOCK){
belle_sip_error("Could not receive UDP packet: %s",strerror(errno));
return -errno;
}
return err;
}
void belle_sip_udp_channel_set_dest(belle_sip_udp_channel_t *chan, const struct addrinfo *ai){
memcpy(chan->base.peer.ai_addr,ai->ai_addr,ai->ai_addrlen);
chan->base.peer.ai_addrlen=ai->ai_addrlen;
static belle_sip_source_t *udp_channel_create_source(belle_sip_channel_t *obj, unsigned int events, unsigned int timeout, belle_sip_source_func_t callback, void *data){
belle_sip_udp_channel_t *chan=(belle_sip_udp_channel_t *)obj;
return belle_sip_fd_source_new(callback,data,chan->sock,events,