Commit ac7ae248 authored by Simon Morlat's avatar Simon Morlat

channel are able to send requests.

add weak refs.
parent e4aed285
......@@ -102,7 +102,8 @@ typedef enum belle_sip_type_id{
typedef enum belle_sip_interface_id{
belle_sip_interface_id_first=1,
BELLE_SIP_INTERFACE_ID(belle_sip_channel_listener_t)
BELLE_SIP_INTERFACE_ID(belle_sip_channel_listener_t),
BELLE_SIP_INTERFACE_ID(belle_sip_listener_t)
}belle_sip_interface_id_t;
/**
......@@ -128,6 +129,22 @@ belle_sip_object_t * belle_sip_object_ref(void *obj);
* Decrements the reference counter. When it drops to zero, the object is destroyed.
**/
void belle_sip_object_unref(void *obj);
typedef void (*belle_sip_object_destroy_notify_t)(void *userpointer, belle_sip_object_t *obj_being_destroyed);
/**
* Add a weak reference to object.
* When object will be destroyed, then the destroy_notify callback will be called.
* This allows another object to be informed when object is destroyed, and then possibly
* cleanups pointer it holds to this object.
**/
belle_sip_object_t *belle_sip_object_weak_ref(void *obj, belle_sip_object_destroy_notify_t destroy_notify, void *userpointer);
/**
* Remove a weak reference to object.
**/
void belle_sip_object_weak_unref(void *obj, belle_sip_object_destroy_notify_t destroy_notify, void *userpointer);
/**
* Set object name.
**/
......@@ -172,13 +189,39 @@ BELLE_SIP_END_DECLS
#define BELLE_SIP_OBJECT(obj) BELLE_SIP_CAST(obj,belle_sip_object_t)
#define BELLE_SIP_IS_INSTANCE_OF(obj,_type) belle_sip_object_is_instance_of((belle_sip_object_t*)obj,_type##_id)
#define BELLE_SIP_INTERFACE_METHODS_TYPE(interface_name) methods_##interface_name
#define BELLE_SIP_DECLARE_INTERFACE_BEGIN(interface_name) \
typedef struct struct##interface_name interface_name;\
typedef struct struct_methods_##interface_name BELLE_SIP_INTERFACE_METHODS_TYPE(interface_name);\
struct struct_methods_##interface_name {\
belle_sip_interface_id_t id;
#define BELLE_SIP_DECLARE_INTERFACE_END };
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;
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;
BELLE_SIP_DECLARE_INTERFACE_BEGIN(belle_sip_listener_t)
void (*process_dialog_terminated)(belle_sip_listener_t *user_ctx, const belle_sip_dialog_terminated_event_t *event);
void (*process_io_error)(belle_sip_listener_t *user_ctx, const belle_sip_io_error_event_t *event);
void (*process_request_event)(belle_sip_listener_t *user_ctx, const belle_sip_request_event_t *event);
void (*process_response_event)(belle_sip_listener_t *user_ctx, const belle_sip_response_event_t *event);
void (*process_timeout)(belle_sip_listener_t *user_ctx, const belle_sip_timeout_event_t *event);
void (*process_transaction_terminated)(belle_sip_listener_t *user_ctx, const belle_sip_transaction_terminated_event_t *event);
BELLE_SIP_DECLARE_INTERFACE_END
#include "belle-sip/utils.h"
#include "belle-sip/list.h"
#include "belle-sip/mainloop.h"
......@@ -190,8 +233,9 @@ typedef struct belle_sip_dialog belle_sip_dialog_t;
#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"
#include "belle-sip/provider.h"
#undef TRUE
#define TRUE 1
......
......@@ -21,17 +21,6 @@
#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;
......@@ -71,14 +60,7 @@ struct belle_sip_transaction_terminated_event{
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
......
......@@ -20,6 +20,8 @@
#ifndef BELLE_SIP_TRANSPORT_H
#define BELLE_SIP_TRANSPORT_H
BELLE_SIP_BEGIN_DECLS
const char *belle_sip_listening_point_get_ip_address(const belle_sip_listening_point_t *lp);
int belle_sip_listening_point_get_port(const belle_sip_listening_point_t *lp);
const char *belle_sip_listening_point_get_transport(const belle_sip_listening_point_t *ip);
......
......@@ -31,9 +31,9 @@ belle_sip_listening_point_t *belle_sip_provider_get_listening_point(belle_sip_pr
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_add_sip_listener(belle_sip_provider_t *p, belle_sip_listener_t *l);
void belle_sip_provider_remove_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);
belle_sip_header_call_id_t * belle_sip_provider_create_call_id(belle_sip_provider_t *prov);
......
......@@ -84,15 +84,6 @@ extern belle_sip_object_vptr_t belle_sip_object_t_vptr;
(belle_sip_object_marshal_t)marshal\
}
#define BELLE_SIP_INTERFACE_METHODS_TYPE(interface_name) methods_##interface_name
#define BELLE_SIP_DECLARE_INTERFACE_BEGIN(interface_name) \
typedef struct struct##interface_name interface_name;\
typedef struct struct_methods_##interface_name BELLE_SIP_INTERFACE_METHODS_TYPE(interface_name);\
struct struct_methods_##interface_name {\
belle_sip_interface_id_t id;
#define BELLE_SIP_DECLARE_INTERFACE_END };
#define BELLE_SIP_IMPLEMENT_INTERFACE_BEGIN(object_type,interface_name) \
static BELLE_SIP_INTERFACE_METHODS_TYPE(interface_name) methods_##object_type##_##interface_name={\
......@@ -123,11 +114,51 @@ extern belle_sip_object_vptr_t belle_sip_object_t_vptr;
#define BELLE_SIP_INTERFACE_GET_METHODS(obj,interface) \
((BELLE_SIP_INTERFACE_METHODS_TYPE(interface)*)belle_sip_object_get_interface_methods((belle_sip_object_t*)obj,BELLE_SIP_INTERFACE_ID(interface)))
#define __BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name) \
if (list!=NULL) {\
const belle_sip_list_t *__elem=list;\
do{\
interface_name *__obj=(interface_name*)__elem->data;\
BELLE_SIP_INTERFACE_GET_METHODS(__obj,interface_name)->
#define __BELLE_SIP_INVOKE_LISTENER_END \
__elem=__elem->next;\
}while(__elem!=NULL);\
}
#define BELLE_SIP_INVOKE_LISTENERS_VOID(list,interface_name,method) \
__BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name)\
method(__obj);\
__BELLE_SIP_INVOKE_LISTENER_END
#define BELLE_SIP_INVOKE_LISTENERS_ARG(list,interface_name,method,arg) \
__BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name)\
method(__obj,arg);\
__BELLE_SIP_INVOKE_LISTENER_END
#define BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(list,interface_name,method,arg1,arg2) \
__BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name)\
method(__obj,arg1,arg2);\
__BELLE_SIP_INVOKE_LISTENER_END
#define BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2_ARG3(list,interface_name,method,arg1,arg2,arg3) \
__BELLE_SIP_INVOKE_LISTENER_BEGIN(list,interface_name)\
method(__obj,arg1,arg2,arg3);\
__BELLE_SIP_INVOKE_LISTENER_END
typedef struct weak_ref{
struct weak_ref *next;
belle_sip_object_destroy_notify_t notify;
void *userpointer;
}weak_ref_t;
struct _belle_sip_object{
belle_sip_object_vptr_t *vptr;
size_t size;
int ref;
char* name;
weak_ref_t *weak_refs;
};
belle_sip_object_t * _belle_sip_object_new(size_t objsize, belle_sip_object_vptr_t *vptr, int initially_unowed);
......@@ -142,12 +173,8 @@ void *belle_sip_object_get_interface_methods(belle_sip_object_t *obj, belle_sip_
/*list of all vptrs (classes) used in belle-sip*/
BELLE_SIP_DECLARE_VPTR(belle_sip_object_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_stack_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_listening_point_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_datagram_listening_point_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_udp_listening_point_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_provider_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_main_loop_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_source_t);
......@@ -228,6 +255,7 @@ void belle_sip_fd_source_init(belle_sip_source_t *s, belle_sip_source_func_t fun
/* include private headers */
#include "channel.h"
#ifdef __cplusplus
extern "C"{
#endif
......@@ -240,7 +268,6 @@ extern "C"{
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_delete_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);
......@@ -511,15 +538,22 @@ void belle_sip_parameters_init(belle_sip_parameters_t *obj);
* Listening points
*/
typedef struct belle_sip_udp_listening_point belle_sip_udp_listening_point_t;
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
typedef struct belle_sip_udp_listening_point belle_sip_udp_listening_point_t;
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_udp_listening_point_t,belle_sip_listening_point_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
#define BELLE_SIP_LISTENING_POINT(obj) BELLE_SIP_CAST(obj,belle_sip_listening_point_t)
#define BELLE_SIP_UDP_LISTENING_POINT(obj) BELLE_SIP_CAST(obj,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_channel_t *belle_sip_listening_point_get_channel(belle_sip_listening_point_t *ip, const char *dest, int port);
belle_sip_channel_t *belle_sip_listening_point_create_channel(belle_sip_listening_point_t *ip, const char *dest, int port);
int belle_sip_listening_point_get_well_known_port(const char *transport);
......@@ -558,13 +592,8 @@ typedef struct listener_ctx{
}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->listener->callback(_lctx->data,(event)); \
} \
}
BELLE_SIP_INVOKE_LISTENERS_ARG(((provider)->listeners),belle_sip_listener_t,callback,(event))
/*
belle_sip_transaction_t
......
......@@ -79,8 +79,8 @@ static void belle_sip_main_loop_remove_source(belle_sip_main_loop_t *ml, belle_s
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);
belle_sip_main_loop_remove_source(ml,ml->control);
belle_sip_object_unref(ml->control);
close(ml->control_fds[0]);
close(ml->control_fds[1]);
}
......@@ -99,7 +99,7 @@ belle_sip_main_loop_t *belle_sip_main_loop_new(void){
if (pipe(m->control_fds)==-1){
belle_sip_fatal("Could not create control pipe.");
}
m->control=belle_sip_fd_source_new (main_loop_done,NULL,m->control_fds[0],BELLE_SIP_EVENT_READ,-1);
m->control=belle_sip_fd_source_new(main_loop_done,NULL,m->control_fds[0],BELLE_SIP_EVENT_READ,-1);
belle_sip_main_loop_add_source(m,m->control);
return m;
}
......
......@@ -62,6 +62,51 @@ void belle_sip_object_unref(void *ptr){
}
}
static weak_ref_t *weak_ref_new(belle_sip_object_destroy_notify_t destroy_notify, void *userpointer){
weak_ref_t *r=belle_sip_new(weak_ref_t);
r->next=NULL;
r->notify=destroy_notify;
r->userpointer=userpointer;
return r;
}
belle_sip_object_t *belle_sip_object_weak_ref(void *obj, belle_sip_object_destroy_notify_t destroy_notify, void *userpointer){
belle_sip_object_t *o=BELLE_SIP_OBJECT(obj);
weak_ref_t *old=o->weak_refs;
o->weak_refs=weak_ref_new(destroy_notify,userpointer);
o->weak_refs->next=old;
return o;
}
void belle_sip_object_weak_unref(void *obj, belle_sip_object_destroy_notify_t destroy_notify, void *userpointer){
belle_sip_object_t *o=BELLE_SIP_OBJECT(obj);
weak_ref_t *ref,*prevref=NULL,*next=NULL;
if (o->ref==-1) return; /*too late and avoid recursions*/
for(ref=o->weak_refs;ref!=NULL;ref=next){
next=ref->next;
if (ref->notify==destroy_notify && ref->userpointer==userpointer){
if (prevref==NULL) o->weak_refs=next;
else prevref->next=next;
belle_sip_free(ref);
return;
}else{
prevref=ref;
}
}
belle_sip_fatal("Could not find weak_ref, you're a looser.");
}
static void belle_sip_object_loose_weak_refs(belle_sip_object_t *obj){
weak_ref_t *ref,*next;
for(ref=obj->weak_refs;ref!=NULL;ref=next){
next=ref->next;
ref->notify(ref->userpointer,obj);
belle_sip_free(ref);
}
obj->weak_refs=NULL;
}
static void _belle_sip_object_uninit(belle_sip_object_t *obj){
if (obj->name)
belle_sip_free(obj->name);
......@@ -83,15 +128,18 @@ belle_sip_object_vptr_t belle_sip_object_t_vptr={
void belle_sip_object_delete(void *ptr){
belle_sip_object_t *obj=BELLE_SIP_OBJECT(ptr);
belle_sip_object_vptr_t *vptr;
if (obj->ref!=0){
belle_sip_error("Destroying referenced object !");
vptr=obj->vptr;
while(vptr!=NULL){
if (vptr->destroy) vptr->destroy(obj);
vptr=vptr->parent;
}
belle_sip_free(obj);
}
obj->ref=-1;
belle_sip_object_loose_weak_refs(obj);
vptr=obj->vptr;
while(vptr!=NULL){
if (vptr->destroy) vptr->destroy(obj);
vptr=vptr->parent;
}
belle_sip_free(obj);
}
belle_sip_object_t *belle_sip_object_clone(const belle_sip_object_t *obj){
......
......@@ -262,7 +262,6 @@ belle_sip_list_t* belle_sip_list_remove_link(belle_sip_list_t* list, belle_sip_l
elem->prev=NULL;
elem->next=NULL;
if (ret!=NULL) ret->prev=NULL;
free(elem);
return ret;
}
elem->prev->next=elem->next;
......@@ -274,7 +273,7 @@ belle_sip_list_t* belle_sip_list_remove_link(belle_sip_list_t* list, belle_sip_l
belle_sip_list_t * belle_sip_list_delete_link(belle_sip_list_t* list, belle_sip_list_t* elem){
belle_sip_list_t *ret=belle_sip_list_remove_link(list,elem);
belle_sip_list_free(elem);
belle_sip_free(elem);
return ret;
}
......@@ -292,14 +291,6 @@ 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;
}
belle_sip_list_t *belle_sip_list_delete_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){
......
......@@ -19,10 +19,22 @@
#include "belle_sip_internal.h"
void belle_sip_channel_listener_on_state_changed(belle_sip_channel_listener_t *obj,
belle_sip_channel_t *chan,
belle_sip_channel_state_t state){
BELLE_SIP_INTERFACE_GET_METHODS(obj,belle_sip_channel_listener_t)->on_state_changed(obj,chan,state);
static const char *channel_state_to_string(belle_sip_channel_state_t state){
switch(state){
case BELLE_SIP_CHANNEL_INIT:
return "INIT";
case BELLE_SIP_CHANNEL_RES_IN_PROGRESS:
return "RES_IN_PROGRESS";
case BELLE_SIP_CHANNEL_RES_DONE:
return "RES_DONE";
case BELLE_SIP_CHANNEL_CONNECTING:
return "CONNECTING";
case BELLE_SIP_CHANNEL_READY:
return "READY";
case BELLE_SIP_CHANNEL_ERROR:
return "ERROR";
}
return "BAD";
}
static void belle_sip_channel_destroy(belle_sip_channel_t *obj){
......@@ -50,9 +62,31 @@ static void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_stack_t *
obj->stack=stack;
}
void belle_sip_channel_add_listener(belle_sip_channel_t *obj, belle_sip_channel_listener_t *l){
obj->listeners=belle_sip_list_append(obj->listeners,
belle_sip_object_weak_ref(l,
(belle_sip_object_destroy_notify_t)belle_sip_channel_remove_listener,obj));
}
void belle_sip_channel_remove_listener(belle_sip_channel_t *obj, belle_sip_channel_listener_t *l){
belle_sip_object_weak_unref(l,(belle_sip_object_destroy_notify_t)belle_sip_channel_remove_listener,obj);
obj->listeners=belle_sip_list_remove(obj->listeners,l);
}
int belle_sip_channel_matches(const belle_sip_channel_t *obj, const char *peername, int peerport, struct addrinfo *addr){
if (strcmp(peername,obj->peer_name)==0 && peerport==obj->peer_port)
return 1;
if (addr && obj->peer)
return addr->ai_addrlen==obj->peer->ai_addrlen && memcmp(addr->ai_addr,obj->peer->ai_addr,addr->ai_addrlen)==0;
return 0;
}
int belle_sip_channel_is_reliable(const belle_sip_channel_t *obj){
return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->reliable;
}
int belle_sip_channel_matches(const belle_sip_channel_t *obj, const char *peername, int peerport){
return strcmp(peername,obj->peer_name)==0 && peerport==obj->peer_port;
const char * chain_sip_channel_get_transport_name(const belle_sip_channel_t *obj){
return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->transport;
}
int belle_sip_channel_send(belle_sip_channel_t *obj, const void *buf, size_t buflen){
......@@ -68,9 +102,9 @@ const struct addrinfo * belle_sip_channel_get_peer(belle_sip_channel_t *obj){
}
static void channel_set_state(belle_sip_channel_t *obj, belle_sip_channel_state_t state){
belle_sip_message("channel %p: state %s",obj,channel_state_to_string(state));
obj->state=state;
if (obj->listener)
belle_sip_channel_listener_on_state_changed(obj->listener,obj,state);
BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_state_changed,obj,state);
}
static void send_message(belle_sip_channel_t *obj, belle_sip_message_t *msg){
......@@ -80,6 +114,8 @@ static void send_message(belle_sip_channel_t *obj, belle_sip_message_t *msg){
int ret=belle_sip_channel_send(obj,buffer,len);
if (ret==-1){
channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
}else{
belle_sip_message("channel %p: message sent: \n%s",obj,buffer);
}
}
}
......@@ -129,7 +165,7 @@ int belle_sip_channel_connect(belle_sip_channel_t *obj){
}
int belle_sip_channel_queue_message(belle_sip_channel_t *obj, belle_sip_message_t *msg){
if (msg!=NULL){
if (obj->msg!=NULL){
belle_sip_error("Queue is not a queue.");
return -1;
}
......@@ -192,52 +228,19 @@ BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_udp_channel_t)=
NULL
},
"UDP",
0, /*is_reliable*/
udp_channel_connect,
udp_channel_send,
udp_channel_recv
}
};
static int create_udp_socket(const char *addr, int port){
struct addrinfo hints={0};
struct addrinfo *res=NULL;
int err;
int sock;
char portnum[10];
sock=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
if (sock==-1){
belle_sip_error("Cannot create UDP socket: %s",strerror(errno));
return -1;
}
snprintf(portnum,sizeof(portnum),"%i",port);
err=getaddrinfo(addr,portnum,&hints,&res);
if (err!=0){
belle_sip_error("getaddrinfo() failed for %s port %i: %s",addr,port,strerror(errno));
close(sock);
return -1;
}
err=bind(sock,res->ai_addr,res->ai_addrlen);
if (err==-1){
belle_sip_error("udp bind() failed for %s port %i: %s",addr,port,strerror(errno));
close(sock);
return -1;
}
return sock;
}
belle_sip_channel_t * belle_sip_channel_new_udp_master(belle_sip_stack_t *stack, const char *localname, int localport){
belle_sip_channel_t * belle_sip_channel_new_udp(belle_sip_stack_t *stack, int sock, const char *dest, int port){
belle_sip_udp_channel_t *obj=belle_sip_object_new(belle_sip_udp_channel_t);
belle_sip_channel_init((belle_sip_channel_t*)obj,stack,"",-1);
obj->sock=create_udp_socket(localname, localport);
belle_sip_channel_init((belle_sip_channel_t*)obj,stack,dest,port);
obj->sock=sock;
return (belle_sip_channel_t*)obj;
}
belle_sip_channel_t * belle_sip_channel_new_udp_slave(belle_sip_channel_t *master, const char *peername, int peerport){
belle_sip_udp_channel_t *obj=belle_sip_object_new(belle_sip_udp_channel_t);
belle_sip_channel_init((belle_sip_channel_t*)obj,master->stack,peername,peerport);
obj->sock=((belle_sip_udp_channel_t*)master)->sock;
return (belle_sip_channel_t*)obj;
}
......@@ -48,13 +48,11 @@ BELLE_SIP_DECLARE_INTERFACE_BEGIN(belle_sip_channel_listener_t)
void (*on_state_changed)(belle_sip_channel_listener_t *obj, belle_sip_channel_t *, belle_sip_channel_state_t state);
BELLE_SIP_DECLARE_INTERFACE_END
void belle_sip_channel_listener_on_state_changed(belle_sip_channel_listener_t *obj, belle_sip_channel_t *, belle_sip_channel_state_t state);
struct belle_sip_channel{
belle_sip_source_t base;
belle_sip_stack_t *stack;
belle_sip_channel_state_t state;
belle_sip_channel_listener_t *listener;
belle_sip_list_t *listeners;
char *peer_name;
int peer_port;
unsigned long resolver_id;
......@@ -64,15 +62,15 @@ struct belle_sip_channel{
#define BELLE_SIP_CHANNEL(obj) BELLE_SIP_CAST(obj,belle_sip_channel_t)
belle_sip_channel_t * belle_sip_channel_new_udp_master(belle_sip_stack_t *stack, const char *locname, int locport);
belle_sip_channel_t * belle_sip_channel_new_udp_slave(belle_sip_channel_t *master, const char *peername, int peerport);
belle_sip_channel_t * belle_sip_channel_new_udp(belle_sip_stack_t *stack, int sock, const char *peername, int peerport);
belle_sip_channel_t * belle_sip_channel_new_tcp(belle_sip_stack_t *stack, const char *name, int port);
void belle_sip_channel_add_listener(belle_sip_channel_t *chan, belle_sip_channel_listener_t *l);
int belle_sip_channel_matches(const belle_sip_channel_t *obj, const char *peername, int peerport);
void belle_sip_channel_remove_listener(belle_sip_channel_t *obj, belle_sip_channel_listener_t *l);
int belle_sip_channel_matches(const belle_sip_channel_t *obj, const char *peername, int peerport, struct addrinfo *addr);
int belle_sip_channel_resolve(belle_sip_channel_t *obj);
......@@ -84,11 +82,16 @@ int belle_sip_channel_recv(belle_sip_channel_t *obj, void *buf, size_t buflen);
int belle_sip_channel_queue_message(belle_sip_channel_t *obj, belle_sip_message_t *msg);
int belle_sip_channel_is_reliable(const belle_sip_channel_t *obj);
const char * chain_sip_channel_get_transport_name(const belle_sip_channel_t *obj);
const struct addrinfo * belle_sip_channel_get_peer(belle_sip_channel_t *obj);
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_channel_t,belle_sip_source_t)
char *transport;
const char *transport;
int reliable;
int (*connect)(belle_sip_channel_t *obj, const struct sockaddr *, socklen_t socklen);
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);
......
......@@ -26,14 +26,11 @@ struct belle_sip_listening_point{
belle_sip_object_t base;
belle_sip_stack_t *stack;
belle_sip_list_t *channels;
char *transport;
char *addr;
int port;
int is_reliable;
};
static void belle_sip_listening_point_init(belle_sip_listening_point_t *lp, belle_sip_stack_t *s, const char *transport, const char *address, int port){
lp->transport=belle_sip_strdup(transport);
static void belle_sip_listening_point_init(belle_sip_listening_point_t *lp, belle_sip_stack_t *s, const char *address, int port){
lp->port=port;
lp->addr=belle_sip_strdup(address);
lp->stack=s;
......@@ -42,21 +39,39 @@ static void belle_sip_listening_point_init(belle_sip_listening_point_t *lp, bell
static void belle_sip_listening_point_uninit(belle_sip_listening_point_t *lp){
belle_sip_list_free_with_data(lp->channels,(void (*)(void*))belle_sip_object_unref);
belle_sip_free(lp->addr);
belle_sip_free(lp->transport);
}
#if 0
static void belle_sip_listening_point_add_channel(belle_sip_listening_point_t *lp, belle_sip_channel_t *chan){
lp->channels=belle_sip_list_append(lp->channels,chan);
lp->channels=belle_sip_list_append(lp->channels,belle_sip_object_ref(chan));
}
belle_sip_channel_t *belle_sip_listening_point_create_channel(belle_sip_listening_point_t *obj, const char *dest, int port){
belle_sip_channel_t *chan=BELLE_SIP_OBJECT_VPTR(obj,belle_sip_listening_point_t)->create_channel(obj,dest,port);
if (chan){
belle_sip_listening_point_add_channel(obj,chan);
}
return chan;
}
#if 0
static void belle_sip_listening_point_remove_channel(belle_sip_listening_point_t *lp, belle_sip_channel_t *chan){
lp->channels=belle_sip_list_remove(lp->channels,chan);
belle_sip_object_unref(chan);
}
#endif
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_listening_point_t);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_listening_point_t,belle_sip_object_t,belle_sip_listening_point_uninit,NULL,NULL);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_listening_point_t)={
{
BELLE_SIP_VPTR_INIT(belle_sip_listening_point_t, belle_sip_object_t),
(belle_sip_object_destroy_t)belle_sip_listening_point_uninit,
NULL,
NULL
},
NULL,
NULL
};
const char *belle_sip_listening_point_get_ip_address(const belle_sip_listening_point_t *lp){
return lp->addr;
......@@ -67,12 +82,9 @@ int belle_sip_listening_point_get_port(const belle_sip_listening_point_t *lp){
}
const char *belle_sip_listening_point_get_transport(const belle_sip_listening_point_t *lp){
return lp->transport;
return BELLE_SIP_OBJECT_VPTR(lp,belle_sip_listening_point_t)->transport;
}
int belle_sip_listening_point_is_reliable(const belle_sip_listening_point_t *lp){
return lp->is_reliable;
}
int belle_sip_listening_point_get_well_known_port(const char *transport){
if (strcasecmp(transport,"UDP")==0 || strcasecmp(transport,"TCP")==0 ) return 5060;
......@@ -81,36 +93,94 @@ int belle_sip_listening_point_get_well_known_port(const char *transport){
return -1;
}
belle_sip_channel_t *belle_sip_listening_point_find_channel (belle_sip_listening_point_t *lp,const char *peer_name, int peer_port){
belle_sip_channel_t *belle_sip_listening_point_get_channel(belle_sip_listening_point_t *lp,const char *peer_name, int peer_port){
belle_sip_list_t *elem;
belle_sip_channel_t *chan;
struct addrinfo *res=NULL;
struct addrinfo hints={0};
char portstr[20];
hints.ai_flags=AI_NUMERICHOST|AI_NUMERICSERV;
snprintf(portstr,sizeof(portstr),"%i",peer_port);
getaddrinfo(peer_name,portstr,&hints,&res);
for(elem=lp->channels;elem!=NULL;elem=elem->next){
belle_sip_channel_t *chan=(belle_sip_channel_t*)elem->data;
if (belle_sip_channel_matches(chan,peer_name,peer_port))
chan=(belle_sip_channel_t*)elem->data;
if (belle_sip_channel_matches(chan,peer_name,peer_port,res)){
if (res) freeaddrinfo(res);
return chan;
}
}
if (res) freeaddrinfo(res);
return NULL;
}
struct belle_sip_udp_listening_point{
belle_sip_listening_point_t base;
belle_sip_channel_t *channel;
int sock;
};
static void belle_sip_udp_listening_point_uninit(belle_sip_udp_listening_point_t *lp){
belle_sip_object_unref(lp->channel);
if (lp->sock!=-1) close(lp->sock);
}
static belle_sip_channel_t *udp_create_channel(belle_sip_listening_point_t *lp, const char *dest_ip, int port){
belle_sip_channel_t *chan=belle_sip_channel_new_udp(lp->stack,((belle_sip_udp_listening_point_t*)lp)->sock,dest_ip,port);
return chan;
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_udp_listening_point_t);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_udp_listening_point_t,belle_sip_listening_point_t,belle_sip_udp_listening_point_uninit,NULL,NULL);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_udp_listening_point_t)={
{
{
BELLE_SIP_VPTR_INIT(belle_sip_udp_listening_point_t, belle_sip_listening_point_t),
(belle_sip_object_destroy_t)belle_sip_udp_listening_point_uninit,
NULL,
NULL
},
"UDP",
udp_create_channel
}