Commit f25a7246 authored by Simon Morlat's avatar Simon Morlat

refactor channels, listening points, and deprecate send_task

parent d6d85bf7
......@@ -8,12 +8,13 @@ bellesip_HEADERS=\
mainloop.h \
transaction.h \
message.h \
transport.h \
listeningpoint.h \
sipstack.h \
provider.h \
listener.h \
dialog.h \
utils.h \
belle-sdp.h \
belle-sip.h
EXTRA_DIST=$(bellesip_HEADERS)
......@@ -63,7 +63,6 @@ typedef enum belle_sip_type_id{
BELLE_SIP_TYPE_ID(belle_sip_header_call_id_t),
BELLE_SIP_TYPE_ID(belle_sip_header_cseq_t),
BELLE_SIP_TYPE_ID(belle_sip_header_content_type_t),
BELLE_SIP_TYPE_ID(belle_sip_sender_task_t),
BELLE_SIP_TYPE_ID(belle_sip_header_route_t),
BELLE_SIP_TYPE_ID(belle_sip_header_record_route_t),
BELLE_SIP_TYPE_ID(belle_sip_header_user_agent_t),
......
......@@ -36,6 +36,9 @@ void belle_sip_list_for_each2(const belle_sip_list_t * list, void (*func)(void *
belle_sip_list_t * belle_sip_list_remove_link(belle_sip_list_t * list, belle_sip_list_t * elem);
belle_sip_list_t * belle_sip_list_delete_link(belle_sip_list_t * list, belle_sip_list_t * elem);
belle_sip_list_t * belle_sip_list_find(belle_sip_list_t * list, void *data);
belle_sip_list_t * belle_sip_list_free(belle_sip_list_t *list);
/*frees list elements and associated data, using the supplied function pointer*/
belle_sip_list_t * belle_sip_list_free_with_data(belle_sip_list_t *list, void (*freefunc)(void*));
typedef int (*belle_sip_compare_func)(const void *, const void*);
belle_sip_list_t * belle_sip_list_find_custom(belle_sip_list_t * list, belle_sip_compare_func cmp, const void *user_data);
......
......@@ -20,34 +20,6 @@
#ifndef BELLE_SIP_TRANSPORT_H
#define BELLE_SIP_TRANSPORT_H
#ifndef WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#else
#endif
typedef struct belle_sip_channel belle_sip_channel_t;
BELLE_SIP_BEGIN_DECLS
/**
* belle_sip_transport_t is an object representing a single communication channel (=unix socket or file descriptor),
* unlike the belle_sip_listening_point_t that can owns several channels for TCP or TLS (incoming server child sockets or
* outgoing client sockets).
**/
int belle_sip_channel_send(belle_sip_channel_t *t, const void *buf, size_t buflen);
int belle_sip_channel_recv(belle_sip_channel_t *t, void *buf, size_t buflen);
const struct addrinfo * belle_sip_channel_get_peer(belle_sip_channel_t *t);
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);
......
/*
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_TRANSPORT_H
#define BELLE_SIP_TRANSPORT_H
typedef struct belle_sip_transport belle_sip_transport_t;
struct belle_sip_transport_class{
char *name; /*udp,tcp*/
int is_reliable;
int (*connect)(belle_sip_transport_t *t, const struct sockaddr *addr, socklen_t addrlen);
int (*recvfrom)(belle_sip_transport_t *t, void *buf, size_t buflen, struct sockaddr *addr, socklen_t *addrlen);
int (*sendto)(belle_sip_transport_t *t, const void *buf, size_t buflen, const struct sockaddr *addr, socklen_t addrlen);
/**
* Method to know if this transport is suitable for supplied transport name and address.
* Should return 1 if suitable, 0 otherwise.
**/
int (*matches)(belle_sip_transport_t *, const char *name, const struct sockaddr *addr, socklen_t addrlen);
void (*close)(belle_sip_transport_t *);
};
typedef struct belle_sip_transport_class belle_sip_transport_class_t;
struct belle_sip_transport{
int magic;
belle_sip_transport_class_t *klass;
int refcnt;
};
const char *belle_sip_transport_get_name(const belle_sip_transport_t *t);
int belle_sip_transport_is_reliable(const belle_sip_transport_t *t);
int belle_sip_transport_matches(belle_sip_transport_t *t, const char *name, const struct sockaddr *addr, socklen_t addrlen);
int belle_sip_transport_sendto(belle_sip_transport_t *t, const void *buf, size_t buflen, const struct sockaddr *addr, socklen_t addrlen);
int belle_sip_transport_recvfrom(belle_sip_transport_t *t, void *buf, size_t buflen, struct sockaddr *addr, socklen_t *addrlen);
void belle_sip_transport_ref(belle_sip_transport_t *t);
void belle_sip_transport_unref(belle_sip_transport_t *t);
BELLE_SIP_DECLARE_CAST(belle_sip_transport_t);
#define BELLE_SIP_TRANSPORT(obj) BELLE_SIP_CAST(obj,belle_sip_transport_t)
#endif
......@@ -41,7 +41,7 @@ libbellesip_la_SOURCES=clock_gettime.h \
listeningpoint.c \
sipstack.c \
provider.c \
sender_task.c sender_task.h \
channel.c channel.h \
message.c
libbellesip_la_CFLAGS=$(STRICT_OPTIONS)
......
......@@ -40,13 +40,12 @@ typedef void (*belle_sip_object_clone_t)(belle_sip_object_t* obj, const belle_si
typedef int (*belle_sip_object_marshal_t)(belle_sip_object_t* obj, char* buff,unsigned int offset,size_t buff_size);
struct _belle_sip_object_vptr{
belle_sip_type_id_t id;
belle_sip_type_id_t id;
struct _belle_sip_object_vptr *parent;
void *interfaces; /*unused for the moment*/
belle_sip_object_destroy_t destroy;
belle_sip_object_clone_t clone;
belle_sip_object_marshal_t marshal;
};
typedef struct _belle_sip_object_vptr belle_sip_object_vptr_t;
......@@ -55,24 +54,31 @@ extern belle_sip_object_vptr_t belle_sip_object_t_vptr;
#define BELLE_SIP_OBJECT_VPTR_NAME(object_type) object_type##_vptr
#define BELLE_SIP_OBJECT_VPTR_TYPE(object_type) object_type##_vptr_t
#define BELLE_SIP_DECLARE_VPTR(object_type) \
extern belle_sip_object_vptr_t BELLE_SIP_OBJECT_VPTR_NAME(object_type);
typedef belle_sip_object_vptr_t BELLE_SIP_OBJECT_VPTR_TYPE(object_type);\
extern BELLE_SIP_OBJECT_VPTR_TYPE(object_type) BELLE_SIP_OBJECT_VPTR_NAME(object_type);
#define BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(object_type, parent_type) \
typedef struct object_type##_vptr_struct BELLE_SIP_OBJECT_VPTR_TYPE(object_type);\
struct object_type##_vptr_struct{\
BELLE_SIP_OBJECT_VPTR_TYPE(parent_type) base;
#define BELLE_SIP_DECLARE_CUSTOM_VPTR_END };
#define BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(object_type) \
BELLE_SIP_OBJECT_VPTR_TYPE(object_type) BELLE_SIP_OBJECT_VPTR_NAME(object_type)
#define BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(vptr_type,object_type, parent_type, destroy, clone) \
vptr_type object_type##_vptr={ {\
#define BELLE_SIP_VPTR_INIT(object_type,parent_type) \
BELLE_SIP_TYPE_ID(object_type), \
(belle_sip_object_vptr_t*)&BELLE_SIP_OBJECT_VPTR_NAME(parent_type), \
NULL, \
(belle_sip_object_destroy_t)destroy, \
(belle_sip_object_clone_t)clone },
NULL
#define BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END };
#define BELLE_SIP_INSTANCIATE_VPTR(object_type,parent_type,destroy,clone,marshal) \
belle_sip_object_vptr_t object_type##_vptr={ \
BELLE_SIP_TYPE_ID(object_type), \
(belle_sip_object_vptr_t*)&BELLE_SIP_OBJECT_VPTR_NAME(parent_type), \
NULL, \
BELLE_SIP_OBJECT_VPTR_TYPE(object_type) BELLE_SIP_OBJECT_VPTR_NAME(object_type)={ \
BELLE_SIP_VPTR_INIT(object_type,parent_type), \
(belle_sip_object_destroy_t)destroy, \
(belle_sip_object_clone_t)clone, \
(belle_sip_object_marshal_t)marshal\
......@@ -94,16 +100,69 @@ int belle_sip_object_marshal(belle_sip_object_t* obj, char* buff,unsigned int of
#define belle_sip_object_new(_type) (_type*)_belle_sip_object_new(sizeof(_type),(belle_sip_object_vptr_t*)&BELLE_SIP_OBJECT_VPTR_NAME(_type),0)
#define belle_sip_object_new_unowed(_type)(_type*)_belle_sip_object_new(sizeof(_type),(belle_sip_object_vptr_t*)&BELLE_SIP_OBJECT_VPTR_NAME(_type),1)
#define BELLE_SIP_OBJECT_VPTR(obj,vptr_type) ((vptr_type*)(((belle_sip_object_t*)obj)->vptr))
#define BELLE_SIP_OBJECT_VPTR(obj,object_type) ((BELLE_SIP_OBJECT_VPTR_TYPE(object_type)*)(((belle_sip_object_t*)obj)->vptr))
#define belle_sip_object_init(obj) /*nothing*/
/*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);
BELLE_SIP_DECLARE_VPTR(belle_sip_resolver_context_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_transaction_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_server_transaction_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_client_transaction_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_dialog_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_address_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_contact_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_from_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_to_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_via_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_uri_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_message_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_request_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_response_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_parameters_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_contact_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_call_id_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_cseq_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_content_type_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_route_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_record_route_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_user_agent_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_content_length_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_extension_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_authorization_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_www_authenticate_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_proxy_authorization_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_max_forwards_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_expires_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_allow_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_attribute_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_bandwidth_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_connection_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_email_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_info_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_key_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_media_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_media_description_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_origin_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_phone_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_repeate_time_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_session_description_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_session_name_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_time_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_time_description_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_uri_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_version_t);
BELLE_SIP_DECLARE_VPTR(belle_sdp_base_description_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_source_t);
......@@ -131,7 +190,7 @@ void belle_sip_fd_source_init(belle_sip_source_t *s, belle_sip_source_func_t fun
#define belle_list_next(elem) ((elem)->next)
/* include private headers */
#include "sender_task.h"
#include "channel.h"
#ifdef __cplusplus
extern "C"{
......@@ -148,6 +207,7 @@ belle_sip_list_t *belle_sip_list_find_custom(belle_sip_list_t *list, belle_sip_c
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);
#define belle_sip_list_next(elem) ((elem)->next)
extern belle_sip_log_function_t belle_sip_logv_out;
......@@ -407,25 +467,18 @@ struct _belle_sip_parameters {
void belle_sip_parameters_init(belle_sip_parameters_t *obj);
/*
* Listening points and channels
* Listening points
*/
struct belle_sip_channel{
belle_sip_object_t base;
belle_sip_listening_point_t *lp; /* the listening point this channel belongs */
struct addrinfo peer;
struct sockaddr_storage peer_addr;
};
typedef struct belle_sip_udp_listening_point belle_sip_udp_listening_point_t;
#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)
#define BELLE_SIP_CHANNEL(obj) BELLE_SIP_CAST(obj,belle_sip_channel_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);
int belle_sip_listening_point_get_well_known_port(const char *transport);
......@@ -456,6 +509,7 @@ struct belle_sip_provider{
belle_sip_provider_t *belle_sip_provider_new(belle_sip_stack_t *s, belle_sip_listening_point_t *lp);
void belle_sip_provider_set_transaction_terminated(belle_sip_provider_t *p, belle_sip_transaction_t *t);
belle_sip_channel_t * belle_sip_provider_get_channel(belle_sip_provider_t *p, const char *name, int port, const char *transport);
typedef struct listener_ctx{
belle_sip_listener_t *listener;
......@@ -483,7 +537,6 @@ struct belle_sip_transaction{
belle_sip_response_t *final_response;
char *branch_id;
belle_sip_transaction_state_t state;
belle_sip_sender_task_t *stask;
uint64_t start_time;
belle_sip_source_t *timer;
int interval;
......@@ -567,7 +620,6 @@ belle_sdp_##object_type##_t* belle_sdp_##object_type##_parse (const char* value)
/*include private headers */
#include "belle_sip_resolver.h"
#include "sender_task.h"
#define BELLE_SIP_SOCKET_TIMEOUT 30000
......
......@@ -208,6 +208,22 @@ belle_sip_list_t* belle_sip_list_free(belle_sip_list_t* list){
return NULL;
}
belle_sip_list_t * belle_sip_list_free_with_data(belle_sip_list_t *list, void (*freefunc)(void*)){
belle_sip_list_t* elem = list;
belle_sip_list_t* tmp;
if (list==NULL) return NULL;
while(elem->next!=NULL) {
tmp = elem;
elem = elem->next;
freefunc(tmp->data);
belle_sip_free(tmp);
}
freefunc(elem->data);
belle_sip_free(elem);
return NULL;
}
belle_sip_list_t* belle_sip_list_remove(belle_sip_list_t* first, void *data){
belle_sip_list_t* it;
it=belle_sip_list_find(first,data);
......
/*
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/>.
*/
#include "belle_sip_internal.h"
static void belle_sip_channel_destroy(belle_sip_channel_t *obj){
if (obj->peer) freeaddrinfo(obj->peer);
belle_sip_free(obj->peer_name);
}
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_channel_t)=
{
{
BELLE_SIP_VPTR_INIT(belle_sip_channel_t,belle_sip_source_t),
(belle_sip_object_destroy_t)belle_sip_channel_destroy,
NULL, /*clone*/
NULL, /*marshall*/
}
};
static void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_provider_t *prov, const char *peername, int peer_port){
obj->peer_name=belle_sip_strdup(peername);
obj->peer_port=peer_port;
obj->peer=NULL;
obj->prov=prov;
}
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;
}
int belle_sip_channel_send(belle_sip_channel_t *obj, const void *buf, size_t buflen){
return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->channel_send(obj,buf,buflen);
}
int belle_sip_channel_recv(belle_sip_channel_t *obj, void *buf, size_t buflen){
return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->channel_recv(obj,buf,buflen);
}
const struct addrinfo * belle_sip_channel_get_peer(belle_sip_channel_t *obj){
return obj->peer;
}
static void send_message(belle_sip_channel_t *obj, belle_sip_message_t *msg){
char buffer[belle_sip_network_buffer_size];
int len=belle_sip_object_marshal((belle_sip_object_t*)msg,buffer,0,sizeof(buffer));
if (len>0){
int ret=belle_sip_channel_send(obj,buffer,len);
if (ret==-1){
belle_sip_io_error_event_t ev;
obj->state=BELLE_SIP_CHANNEL_ERROR;
ev.transport=BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->transport;
ev.source=obj->prov;
ev.port=obj->peer_port;
ev.host=obj->peer_name;
BELLE_SIP_PROVIDER_INVOKE_LISTENERS(obj->prov,process_io_error,&ev);
}
}
}
static void channel_process_queue(belle_sip_channel_t *obj){
if (obj->msg){
switch(obj->state){
case BELLE_SIP_CHANNEL_INIT:
belle_sip_channel_resolve(obj);
break;
case BELLE_SIP_CHANNEL_RES_DONE:
belle_sip_channel_connect(obj);
break;
case BELLE_SIP_CHANNEL_READY:
send_message(obj, obj->msg);
case BELLE_SIP_CHANNEL_ERROR:
belle_sip_object_unref(obj->msg);
obj->msg=NULL;
break;
default:
break;
}
}
}
static void channel_res_done(void *data, const char *name, struct addrinfo *res){
belle_sip_channel_t *obj=(belle_sip_channel_t*)data;
obj->resolver_id=0;
if (res){
obj->peer=res;
obj->state=BELLE_SIP_CHANNEL_RES_DONE;
}else{
belle_sip_io_error_event_t ev;
obj->state=BELLE_SIP_CHANNEL_ERROR;
ev.transport=BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->transport;
ev.source=obj->prov;
ev.port=obj->peer_port;
ev.host=obj->peer_name;
BELLE_SIP_PROVIDER_INVOKE_LISTENERS(obj->prov,process_io_error,&ev);
}
channel_process_queue(obj);
}
int belle_sip_channel_resolve(belle_sip_channel_t *obj){
obj->state=BELLE_SIP_CHANNEL_RES_IN_PROGRESS;
obj->resolver_id=belle_sip_resolve(obj->peer_name, obj->peer_port, 0, channel_res_done, obj, obj->prov->stack->ml);
return 0;
}
int belle_sip_channel_connect(belle_sip_channel_t *obj){
return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->connect(obj,obj->peer->ai_addr,obj->peer->ai_addrlen);
}
int belle_sip_channel_queue_message(belle_sip_channel_t *obj, belle_sip_message_t *msg){
if (msg!=NULL){
belle_sip_error("Queue is not a queue.");
return -1;
}
obj->msg=(belle_sip_message_t*)belle_sip_object_ref(msg);
channel_process_queue(obj);
return 0;
}
struct belle_sip_udp_channel{
belle_sip_channel_t base;
int sock;
};
typedef struct belle_sip_udp_channel belle_sip_udp_channel_t;
static void udp_channel_uninit(belle_sip_udp_channel_t *obj){
if (obj->sock!=-1)
close(obj->sock);
}
static int udp_channel_send(belle_sip_channel_t *obj, const void *buf, size_t buflen){
belle_sip_udp_channel_t *chan=(belle_sip_udp_channel_t *)obj;
int err;
err=sendto(chan->sock,buf,buflen,0,obj->peer->ai_addr,obj->peer->ai_addrlen);
if (err==-1){
belle_sip_fatal("Could not send UDP packet: %s",strerror(errno));
return -errno;
}
return err;
}
static int udp_channel_recv(belle_sip_channel_t *obj, void *buf, size_t buflen){
belle_sip_udp_channel_t *chan=(belle_sip_udp_channel_t *)obj;
int err;
struct sockaddr_storage addr;
socklen_t addrlen=sizeof(addr);
err=recvfrom(chan->sock,buf,buflen,MSG_DONTWAIT,(struct sockaddr*)&addr,&addrlen);
if (err==-1 && errno!=EWOULDBLOCK){
belle_sip_error("Could not receive UDP packet: %s",strerror(errno));
return -errno;
}
return err;
}
int udp_channel_connect(belle_sip_channel_t *obj, const struct sockaddr *addr, socklen_t socklen){
obj->state=BELLE_SIP_CHANNEL_READY;
channel_process_queue(obj);
return 0;
}
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_udp_channel_t)=
{
{
{
BELLE_SIP_VPTR_INIT(belle_sip_udp_channel_t,belle_sip_channel_t),
(belle_sip_object_destroy_t)udp_channel_uninit,
NULL,
NULL
},
"UDP",
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_provider_t *prov, const char *localname, int localport){
belle_sip_udp_channel_t *obj=belle_sip_object_new(belle_sip_udp_channel_t);
belle_sip_channel_init((belle_sip_channel_t*)obj,prov,"",-1);
obj->sock=create_udp_socket(localname, localport);
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->prov,peername,peerport);
obj->sock=((belle_sip_udp_channel_t*)master)->sock;
return (belle_sip_channel_t*)obj;
}
/*
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_CHANNEL_H
#define BELLE_SIP_CHANNEL_H
#ifndef WIN32
#include <sys/types.h>
#include <sys/socket.h>
#else
#endif
static const int belle_sip_network_buffer_size=64535;
typedef enum belle_sip_channel_state{
BELLE_SIP_CHANNEL_INIT,
BELLE_SIP_CHANNEL_RES_IN_PROGRESS,
BELLE_SIP_CHANNEL_RES_DONE,
BELLE_SIP_CHANNEL_CONNECTING,
BELLE_SIP_CHANNEL_READY,
BELLE_SIP_CHANNEL_ERROR
}belle_sip_channel_state_t;
/**
* belle_sip_channel_t is an object representing a single communication channel ( socket or file descriptor),
* unlike the belle_sip_listening_point_t that can owns several channels for TCP or TLS (incoming server child sockets or
* outgoing client sockets).
**/
typedef struct belle_sip_channel belle_sip_channel_t;
struct belle_sip_channel{
belle_sip_source_t base;
belle_sip_channel_state_t state;
belle_sip_provider_t *prov;/*we need the provider to notify connection errors*/
char *peer_name;
int peer_port;
unsigned long resolver_id;
struct addrinfo *peer;
belle_sip_message_t *msg;
};
#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_provider_t *prov, 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_tcp(belle_sip_provider_t *prov, const char *name, int port);
int belle_sip_channel_matches(const belle_sip_channel_t *obj, const char *peername, int peerport);
int belle_sip_channel_resolve(belle_sip_channel_t *obj);
int belle_sip_channel_connect(belle_sip_channel_t *obj);
int belle_sip_channel_send(belle_sip_channel_t *obj, const void *buf, size_t buflen);
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);
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;
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);
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_udp_channel_t,belle_sip_channel_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
#endif
......@@ -18,134 +18,6 @@
#include "belle_sip_internal.h"
#ifndef WIN32
#include <sys/types.h>
#include <sys/socket.h>
#else
#endif
/*
Channels: udp
*/
typedef struct belle_sip_channel_vptr{
belle_sip_object_vptr_t base;
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;
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_channel_vptr_t,belle_sip_channel_t,belle_sip_object_t,NULL,NULL)
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
static void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_listening_point_t *lp){
obj->lp=lp;
obj->peer.ai_addr=(struct sockaddr*)&obj->peer_addr;
}
int belle_sip_channel_send(belle_sip_channel_t *obj, const void *buf, size_t buflen){
return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_vptr_t)->channel_send(obj,buf,buflen);
}
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