Commit 9c20abcc authored by jehan's avatar jehan

First tcp channel implementation

parent abe60cf6
......@@ -37,16 +37,13 @@ else
CFLAGS="-g"
fi
if test x$GCC = xyes ; then
STRICT_OPTIONS=" -Wall -Werror"
STRICT_OPTIONS=" -Wall -Werror"
dnl because of antlr3 we must accept a few warnings...
LESS_STRICT_OPTIONS= #more portable
# LESS_STRICT_OPTIONS="$STRICT_OPTIONS -Wno-error=unused-function \
# -Wno-error=uninitialized -Wno-error=unused-variable \
# -Wno-error=unused-but-set-variable "
fi
AC_SUBST(STRICT_OPTIONS)
AC_SUBST(LESS_STRICT_OPTIONS)
......
......@@ -38,8 +38,10 @@ BELLE_SIP_DECLARE_TYPES_BEGIN(belle_sip,1)
BELLE_SIP_TYPE_ID(belle_sip_listening_point_t),
BELLE_SIP_TYPE_ID(belle_sip_datagram_listening_point_t),
BELLE_SIP_TYPE_ID(belle_sip_udp_listening_point_t),
BELLE_SIP_TYPE_ID(belle_sip_stream_listening_point_t),
BELLE_SIP_TYPE_ID(belle_sip_channel_t),
BELLE_SIP_TYPE_ID(belle_sip_udp_channel_t),
BELLE_SIP_TYPE_ID(belle_sip_stream_channel_t),
BELLE_SIP_TYPE_ID(belle_sip_provider_t),
BELLE_SIP_TYPE_ID(belle_sip_main_loop_t),
BELLE_SIP_TYPE_ID(belle_sip_source_t),
......
......@@ -246,6 +246,7 @@ belle_sip_header_expires_t* belle_sip_header_expires_parse (const char* expires)
int belle_sip_header_expires_get_expires(const belle_sip_header_expires_t* expires);
void belle_sip_header_expires_set_expires(belle_sip_header_expires_t* expires,int value);
int belle_sip_header_expires_decrement_expires(belle_sip_header_expires_t* expires);
belle_sip_header_expires_t* belle_sip_header_expires_create(int expires);
#define BELLE_SIP_HEADER_EXPIRES(t) BELLE_SIP_CAST(t,belle_sip_header_expires_t)
/******************************
......
......@@ -38,43 +38,8 @@ BELLE_SIP_DECLARE_INTERFACE_END
#define BELLE_SIP_LISTENER(obj) BELLE_SIP_INTERFACE_CAST(obj,belle_sip_listener_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;
const char *transport;
const 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_response_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;
};
belle_sip_response_t* belle_sip_response_event_get_response(const belle_sip_response_event_t* event);
......
......@@ -31,5 +31,6 @@ int belle_sip_listening_point_is_reliable(const belle_sip_listening_point_t *lp)
BELLE_SIP_END_DECLS
#endif
......@@ -18,7 +18,46 @@
#ifndef BELLE_SIP_MAINLOOP_H
#define BELLE_SIP_MAINLOOP_H
#include <errno.h>
#include <sys/socket.h>
#include <unistd.h>
#if defined(WIN32) || defined(WIN32_WCE)
typedef SOCKET belle_sip_fd_t;
static inline void close_socket(belle_sip_fd_t s){
closesocket(s);
}
static inline int get_socket_error(void){
return WSAGetLastError();
}
const char *getSocketErrorString();
#define belle_sip_get_socket_error_string() getSocketErrorString()
#define usleep(us) Sleep((us)/1000)
static inline int inet_aton(const char *ip, struct in_addr *p){
*(long*)p=inet_addr(ip);
return 0;
}
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EINPROGRESS WSAEINPROGRESS
#else
typedef int belle_sip_fd_t;
static inline void close_socket(belle_sip_fd_t s){
close(s);
}
static inline int get_socket_error(void){
return errno;
}
#define belle_sip_get_socket_error_string() strerror(errno)
#endif
#define BELLE_SIP_EVENT_READ 1
#define BELLE_SIP_EVENT_WRITE (1<<1)
......@@ -27,6 +66,8 @@
typedef struct belle_sip_source belle_sip_source_t;
int belle_sip_source_set_event(belle_sip_source_t* source, int event_mask);
belle_sip_fd_t belle_sip_source_get_fd(const belle_sip_source_t* source);
/**
* Callback function prototype for main loop notifications.
......
......@@ -27,7 +27,8 @@ libbellesip_generated_la_CFLAGS=$(LESS_STRICT_OPTIONS) $(ANTLR_CFLAGS)
lib_LTLIBRARIES=libbellesip.la
libbellesip_la_SOURCES= clock_gettime.c clock_gettime.h \
libbellesip_la_SOURCES= \
clock_gettime.c clock_gettime.h \
belle_sip_uri_impl.c \
belle_sip_headers_impl.c \
belle_sip_utils.c belle_sip_internal.h \
......@@ -44,7 +45,11 @@ libbellesip_la_SOURCES= clock_gettime.c clock_gettime.h \
message.c \
md5.c \
auth_helper.c \
ict.c
ict.c \
transports/udp_listeningpoint.c \
transports/udp_channel.c \
transports/stream_channel.c \
transports/stream_listeningpoint.c
libbellesip_la_CFLAGS=$(STRICT_OPTIONS) $(ANTLR_CFLAGS)
......
......@@ -26,6 +26,7 @@
#include "belle_sip_messageParser.h"
#include "belle_sip_messageLexer.h"
#include "belle_sip_internal.h"
#include "listeningpoint_internal.h"
/************************
* header
......@@ -471,7 +472,7 @@ int belle_sip_header_cseq_marshal(belle_sip_header_cseq_t* cseq, char* buff,unsi
}
belle_sip_header_cseq_t * belle_sip_header_cseq_create(unsigned int number, const char *method){
belle_sip_header_cseq_t *cseq=belle_sip_header_cseq_new();
cseq->method=belle_sip_strdup(method);
belle_sip_header_cseq_set_method(cseq,method);
cseq->seq_number=number;
return cseq;
}
......@@ -598,7 +599,11 @@ int belle_sip_header_expires_marshal(belle_sip_header_expires_t* expires, char*
BELLE_SIP_NEW_HEADER(header_expires,header,"Expires")
BELLE_SIP_PARSE(header_expires)
GET_SET_INT(belle_sip_header_expires,expires,int)
belle_sip_header_expires_t* belle_sip_header_expires_create(int expires) {
belle_sip_header_expires_t* obj = belle_sip_header_expires_new();
belle_sip_header_expires_set_expires(obj,expires);
return obj;
}
/******************************
* Extension header hinerite from header
*
......@@ -624,6 +629,7 @@ int belle_sip_header_extension_marshal(belle_sip_header_extension_t* extension,
}
BELLE_SIP_NEW_HEADER(header_extension,header,NULL)
/**
* special case for this header. I don't know why
*/
......
......@@ -35,7 +35,6 @@
/* include all public headers*/
#include "belle-sip/belle-sip.h"
/*etc*/
#define BELLE_SIP_INTERFACE_GET_METHODS(obj,interface) \
......@@ -147,11 +146,14 @@ BELLE_SIP_DECLARE_VPTR(belle_sdp_mime_parameter_t);
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;
belle_sip_fd_t fd;
unsigned int events;
int timeout;
void *data;
......@@ -163,7 +165,7 @@ struct belle_sip_source{
unsigned char expired;
};
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);
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)
......@@ -376,23 +378,15 @@ 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
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_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);
/*
......@@ -594,6 +588,44 @@ belle_sdp_##object_type##_t* belle_sdp_##object_type##_parse (const char* value)
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;
const char *transport;
const 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_response_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;
};
#ifdef __cplusplus
......
......@@ -69,6 +69,7 @@ struct belle_sip_main_loop{
};
void belle_sip_main_loop_remove_source(belle_sip_main_loop_t *ml, belle_sip_source_t *source){
if (!source->node.next || !source->node.prev) return; /*nothing to do*/
ml->sources=belle_sip_list_remove_link(ml->sources,&source->node);
ml->nsources--;
......@@ -264,4 +265,10 @@ void belle_sip_main_loop_sleep(belle_sip_main_loop_t *ml, int milliseconds){
belle_sip_main_loop_add_timeout(ml,(belle_sip_source_func_t)belle_sip_main_loop_quit,ml,milliseconds);
belle_sip_main_loop_run(ml);
}
int belle_sip_source_set_event(belle_sip_source_t* source, int event_mask) {
source->events = event_mask;
return 0;
}
belle_sip_fd_t belle_sip_source_get_fd(const belle_sip_source_t* source) {
return source->fd;
}
......@@ -24,6 +24,7 @@
#include "belle_sip_messageParser.h"
#include "belle_sip_messageLexer.h"
#include "belle_sip_internal.h"
#include "listeningpoint_internal.h"
#define SIP_URI_GET_SET_STRING(attribute) GET_SET_STRING(belle_sip_uri,attribute)
......
......@@ -86,7 +86,7 @@ void belle_sip_channel_process_data(belle_sip_channel_t *obj,unsigned int revent
BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_event,obj,revents);
}
static void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_stack_t *stack, int fd, const char *bindip,int localport,const char *peername, int peer_port){
void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_stack_t *stack, int fd, belle_sip_source_func_t process_data,const char *bindip,int localport,const char *peername, int peer_port){
obj->peer_name=belle_sip_strdup(peername);
obj->peer_port=peer_port;
obj->peer=NULL;
......@@ -95,7 +95,9 @@ static void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_stack_t *
obj->local_ip=belle_sip_strdup(bindip);
obj->local_port=localport;
belle_sip_fd_source_init((belle_sip_source_t*)obj,(belle_sip_source_func_t)belle_sip_channel_process_data,obj,fd,BELLE_SIP_EVENT_READ|BELLE_SIP_EVENT_ERROR,-1);
if (process_data) {
belle_sip_fd_source_init((belle_sip_source_t*)obj,(belle_sip_source_func_t)process_data,obj,fd,BELLE_SIP_EVENT_READ|BELLE_SIP_EVENT_ERROR,-1);
}
}
void belle_sip_channel_add_listener(belle_sip_channel_t *obj, belle_sip_channel_listener_t *l){
......@@ -125,7 +127,17 @@ const char *belle_sip_channel_get_local_address(belle_sip_channel_t *obj, int *p
int belle_sip_channel_is_reliable(const belle_sip_channel_t *obj){
return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->reliable;
}
const char * belle_sip_channel_get_transport_name_lower_case(const belle_sip_channel_t *obj){
const char* transport = belle_sip_channel_get_transport_name(obj);
if (strcasecmp("udp",transport)==0) return "udp";
else if (strcasecmp("tcp",transport)==0) return "tcp";
else if (strcasecmp("tls",transport)==0) return "tls";
else if (strcasecmp("dtls",transport)==0) return "dtls";
else {
belle_sip_message("Cannot convert [%s] to lower case",transport);
return transport;
}
}
const char * belle_sip_channel_get_transport_name(const belle_sip_channel_t *obj){
return BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->transport;
}
......@@ -143,13 +155,12 @@ const struct addrinfo * belle_sip_channel_get_peer(belle_sip_channel_t *obj){
}
belle_sip_message_t* belle_sip_channel_pick_message(belle_sip_channel_t *obj) {
/*FIXME should be synchronized*/
belle_sip_message_t* result = obj->input_stream.msg;
obj->input_stream.msg=NULL;
return result;
}
static void channel_set_state(belle_sip_channel_t *obj, belle_sip_channel_state_t state){
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;
BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_state_changed,obj,state);
......@@ -171,7 +182,7 @@ static void send_message(belle_sip_channel_t *obj, belle_sip_message_t *msg){
}
static void channel_process_queue(belle_sip_channel_t *obj){
void channel_process_queue(belle_sip_channel_t *obj){
if (obj->msg){
switch(obj->state){
case BELLE_SIP_CHANNEL_INIT:
......@@ -192,7 +203,7 @@ static void channel_process_queue(belle_sip_channel_t *obj){
}
}
static void belle_sip_channel_set_ready(belle_sip_channel_t *obj, const struct sockaddr *addr, socklen_t slen){
void belle_sip_channel_set_ready(belle_sip_channel_t *obj, const struct sockaddr *addr, socklen_t slen){
char name[NI_MAXHOST];
char serv[NI_MAXSERV];
......@@ -222,15 +233,20 @@ static void channel_res_done(void *data, const char *name, struct addrinfo *res)
channel_process_queue(obj);
}
int belle_sip_channel_resolve(belle_sip_channel_t *obj){
void belle_sip_channel_resolve(belle_sip_channel_t *obj){
channel_set_state(obj,BELLE_SIP_CHANNEL_RES_IN_PROGRESS);
obj->resolver_id=belle_sip_resolve(obj->peer_name, obj->peer_port, 0, channel_res_done, obj, obj->stack->ml);
return 0;
return ;
}
int belle_sip_channel_connect(belle_sip_channel_t *obj){
int ret=BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->connect(obj,obj->peer->ai_addr,obj->peer->ai_addrlen);
return ret;
void belle_sip_channel_connect(belle_sip_channel_t *obj){
channel_set_state(obj,BELLE_SIP_CHANNEL_CONNECTING);
if(BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->connect(obj,obj->peer->ai_addr,obj->peer->ai_addrlen)) {
belle_sip_error("Cannot connect to [%s://%s:%s]",belle_sip_channel_get_transport_name(obj),obj->peer_name,obj->peer_port);
channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
channel_process_queue(obj);
}
return;
}
int belle_sip_channel_queue_message(belle_sip_channel_t *obj, belle_sip_message_t *msg){
......@@ -243,103 +259,5 @@ int belle_sip_channel_queue_message(belle_sip_channel_t *obj, belle_sip_message_
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){
struct sockaddr_storage laddr;
socklen_t lslen=sizeof(laddr);
if (obj->local_ip==NULL){
belle_sip_get_src_addr_for(addr,socklen,(struct sockaddr*)&laddr,&lslen);
if (lslen==sizeof(struct sockaddr_in6)){
struct sockaddr_in6 *sin6=(struct sockaddr_in6*)&laddr;
sin6->sin6_port=htons(obj->local_port);
}else{
struct sockaddr_in *sin=(struct sockaddr_in*)&laddr;
sin->sin_port=htons(obj->local_port);
}
}
belle_sip_channel_set_ready(obj,(struct sockaddr*)&laddr,lslen);
return 0;
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_udp_channel_t);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_udp_channel_t)=
{
{
{
BELLE_SIP_VPTR_INIT(belle_sip_udp_channel_t,belle_sip_channel_t,FALSE),
(belle_sip_object_destroy_t)udp_channel_uninit,
NULL,
NULL
},
"UDP",
0, /*is_reliable*/
udp_channel_connect,
udp_channel_send,
udp_channel_recv
}
};
belle_sip_channel_t * belle_sip_channel_new_udp(belle_sip_stack_t *stack, int sock, const char *bindip, int localport, 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,sock,bindip,localport,dest,port);
obj->sock=sock;
return (belle_sip_channel_t*)obj;
}
belle_sip_channel_t * belle_sip_channel_new_udp_with_addr(belle_sip_stack_t *stack, int sock, const char *bindip, int localport, const struct addrinfo *peer){
belle_sip_udp_channel_t *obj=belle_sip_object_new(belle_sip_udp_channel_t);
struct addrinfo *ai=belle_sip_new0(struct addrinfo);
char name[NI_MAXHOST];
char serv[NI_MAXSERV];
int err;
obj->sock=sock;
*ai=*peer;
err=getnameinfo(ai->ai_addr,ai->ai_addrlen,name,sizeof(name),serv,sizeof(serv),NI_NUMERICHOST|NI_NUMERICSERV);
if (err!=0){
belle_sip_error("belle_sip_channel_new_udp_with_addr(): getnameinfo() failed: %s",gai_strerror(err));
belle_sip_object_unref(obj);
return NULL;
}
belle_sip_channel_init((belle_sip_channel_t*)obj,stack,sock,bindip,localport,name,atoi(serv));
return (belle_sip_channel_t*)obj;
}
......@@ -88,7 +88,7 @@ belle_sip_channel_t * belle_sip_channel_new_udp(belle_sip_stack_t *stack, int so
belle_sip_channel_t * belle_sip_channel_new_udp_with_addr(belle_sip_stack_t *stack, int sock, const char *bindip, int localport, const struct addrinfo *ai);
belle_sip_channel_t * belle_sip_channel_new_tcp(belle_sip_stack_t *stack, const char *name, int port);
belle_sip_channel_t * belle_sip_channel_new_tcp(belle_sip_stack_t *stack, const char *bindip, int localport,const char *name, int port);
void belle_sip_channel_add_listener(belle_sip_channel_t *chan, belle_sip_channel_listener_t *l);
......@@ -96,13 +96,17 @@ void belle_sip_channel_remove_listener(belle_sip_channel_t *obj, belle_sip_chann
int belle_sip_channel_matches(const belle_sip_channel_t *obj, const char *peername, int peerport, const struct addrinfo *addr);
int belle_sip_channel_resolve(belle_sip_channel_t *obj);
void belle_sip_channel_resolve(belle_sip_channel_t *obj);
int belle_sip_channel_connect(belle_sip_channel_t *obj);
void 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);
/*only used by channels implementation*/
void belle_sip_channel_set_ready(belle_sip_channel_t *obj, const struct sockaddr *addr, socklen_t slen);
void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_stack_t *stack, int fd, belle_sip_source_func_t process_data, const char *bindip,int localport,const char *peername, int peer_port);
/*end of channel implementations*/
/**
* pickup last received message. This method take the ownership of the message.
*/
......@@ -113,6 +117,7 @@ int belle_sip_channel_queue_message(belle_sip_channel_t *obj, belle_sip_message_
int belle_sip_channel_is_reliable(const belle_sip_channel_t *obj);
const char * belle_sip_channel_get_transport_name(const belle_sip_channel_t *obj);
const char * belle_sip_channel_get_transport_name_lower_case(const belle_sip_channel_t *obj);
const struct addrinfo * belle_sip_channel_get_peer(belle_sip_channel_t *obj);
......@@ -120,6 +125,10 @@ const char *belle_sip_channel_get_local_address(belle_sip_channel_t *obj, int *p
#define belle_sip_channel_get_state(chan) ((chan)->state)
void channel_set_state(belle_sip_channel_t *obj, belle_sip_channel_state_t state);
void channel_process_queue(belle_sip_channel_t *obj);
/*just invokes the listeners to process data*/
void belle_sip_channel_process_data(belle_sip_channel_t *obj,unsigned int revents);
......@@ -131,7 +140,8 @@ BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_channel_t,belle_sip_source_t)
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
......@@ -16,21 +16,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "belle_sip_internal.h"
#include "listeningpoint_internal.h"
/*
Listening points: base, udp
*/
struct belle_sip_listening_point{
belle_sip_object_t base;
belle_sip_stack_t *stack;
belle_sip_list_t *channels;
char *addr;
int port;
};
static void belle_sip_listening_point_init(belle_sip_listening_point_t *lp, belle_sip_stack_t *s, const char *address, int port){
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,7 +32,7 @@ static void belle_sip_listening_point_uninit(belle_sip_listening_point_t *lp){
}
static void belle_sip_listening_point_add_channel(belle_sip_listening_point_t *lp, belle_sip_channel_t *chan){
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,belle_sip_object_ref(chan));
}
......@@ -93,7 +83,7 @@ int belle_sip_listening_point_get_well_known_port(const char *transport){
return -1;
}
static belle_sip_channel_t *_belle_sip_listening_point_get_channel(belle_sip_listening_point_t *lp,const char *peer_name, int peer_port, const struct addrinfo *addr){
belle_sip_channel_t *_belle_sip_listening_point_get_channel(belle_sip_listening_point_t *lp,const char *peer_name, int peer_port, const struct addrinfo *addr){
belle_sip_list_t *elem;
belle_sip_channel_t *chan;
......@@ -120,120 +110,6 @@ belle_sip_channel_t *belle_sip_listening_point_get_channel(belle_sip_listening_p
return chan;
}
struct belle_sip_udp_listening_point{
belle_sip_listening_point_t base;
int sock;
belle_sip_source_t *source;
};
static void belle_sip_udp_listening_point_uninit(belle_sip_udp_listening_point_t *lp){
if (lp->sock!=-1) close(lp->sock);
if (lp->source) belle_sip_main_loop_remove_source(lp->base.stack->ml,lp->source);
}
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,
lp->addr,lp->port,dest_ip,port);
return chan;
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_udp_listening_point_t);
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,FALSE),
(belle_sip_object_destroy_t)belle_sip_udp_listening_point_uninit,
NULL,
NULL
},
"UDP",
udp_create_channel
}
};
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];
snprintf(portnum,sizeof(portnum),"%i",port);
hints.ai_family=AF_UNSPEC;
hints.ai_socktype=SOCK_DGRAM;
hints.ai_protocol=IPPROTO_UDP;
hints.ai_flags=AI_NUMERICSERV;
err=getaddrinfo(addr,portnum,&hints,&res);
if (err!=0){
belle_sip_error("getaddrinfo() failed for %s port %i: %s",addr,port,gai_strerror(err));
return -1;
}
sock=socket(res->ai_family,res->ai_socktype,res->ai_protocol);
if (sock==-1){
belle_sip_error("Cannot create UDP socket: %s",strerror(errno));
freeaddrinfo(res);
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);
freeaddrinfo(res);
return -1;
}
freeaddrinfo(res);
return sock;
}
/*peek data from the master socket to see where it comes from, and dispatch to matching channel.
* If the channel does not exist, create it */
static int on_udp_data(belle_sip_udp_listening_point_t *lp, unsigned int events){
int err;
unsigned char buf[1];
struct sockaddr_storage addr;
socklen_t addrlen=sizeof(addr);
if (events & BELLE_SIP_EVENT_READ){
belle_sip_message("udp_listening_point: data to read.");
err=recvfrom(lp->sock,buf,sizeof(buf),MSG_PEEK,(struct sockaddr*)&addr,&addrlen);
if (err==-1){
belle_sip_error("udp_listening_point: recvfrom() failed: %s",strerror(errno));
}else{
belle_sip_channel_t *chan;
struct addrinfo ai={0};
ai.ai_addr=(struct sockaddr*)&addr;
ai.ai_addrlen=addrlen;
chan=_belle_sip_listening_point_get_channel((belle_sip_listening_point_t*)lp,NULL,0,&ai);
if (chan==NULL){
chan=belle_sip_channel_new_udp_with_addr(lp->base.stack,lp->sock,lp->base.addr,lp->base.port,&ai);
if (chan!=NULL){
belle_sip_message("udp_listening_point: new channel created to %s:%i",chan->peer_name,chan->peer_port);
belle_sip_listening_point_add_channel((belle_sip_listening_point_t*)lp,chan);
}
}
if (chan){
/*notify the channel*/