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

start implementing listening points and sip stack objects.

parent 356cc400
......@@ -3,10 +3,14 @@ bellesipdir=$(includedir)/belle-sip
bellesip_HEADERS=\
uri.h \
list.h \
headers.h \
parameters.h \
mainloop.h \
transaction.h \
message.h \
transport.h \
listeningpoint.h \
sipstack.h \
belle-sip.h
EXTRA_DIST=$(bellesip_HEADERS)
......@@ -20,10 +20,27 @@
#include <stdlib.h>
#ifdef __cplusplus
#define BELLE_SIP_BEGIN_DECLS extern "C"{
#define BELLE_SIP_END_DECLS }
#else
#define BELLE_SIP_BEGIN_DECLS
#define BELLE_SIP_END_DECLS
#endif
#define BELLE_SIP_TYPE_ID(_type) _type##_id
typedef enum belle_sip_type_id{
belle_sip_type_id_first=1,
BELLE_SIP_TYPE_ID(belle_sip_stack_t),
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_channel_t),
BELLE_SIP_TYPE_ID(belle_sip_udp_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),
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),
......@@ -49,33 +66,40 @@ typedef enum belle_sip_type_id{
typedef struct _belle_sip_object belle_sip_object_t;
BELLE_SIP_BEGIN_DECLS
int belle_sip_object_is_unowed(const belle_sip_object_t *obj);
/**
* Increments reference counter, which prevents the object from being destroyed.
* If the object is initially unowed, this acquires the first reference.
**/
#define belle_sip_object_ref(obj) _belle_sip_object_ref((belle_sip_object_t*)obj)
belle_sip_object_t * _belle_sip_object_ref(belle_sip_object_t *obj);
belle_sip_object_t * belle_sip_object_ref(void *obj);
/**
* Decrements the reference counter. When it drops to zero, the object is destroyed.
**/
#define belle_sip_object_unref(obj) _belle_sip_object_unref((belle_sip_object_t*)obj)
void _belle_sip_object_unref(belle_sip_object_t *obj);
void belle_sip_object_unref(void *obj);
/**
* Destroy the object: this function is intended for unowed object, that is objects
* that were created with a 0 reference count.
**/
#define belle_sip_object_destroy(obj) _belle_sip_object_destroy((belle_sip_object_t*)obj)
void _belle_sip_object_destroy(belle_sip_object_t *obj);
void belle_sip_object_destroy(void *obj);
void *belle_sip_object_cast(belle_sip_object_t *obj, belle_sip_type_id_t id, const char *castname, const char *file, int fileno);
#define BELLE_SIP_CAST(obj,_type) (_type*)belle_sip_object_cast((belle_sip_object_t *)(obj), _type##_id, #_type, __FILE__, __LINE__)
BELLE_SIP_END_DECLS
#define BELLE_SIP_CAST(obj,_type) ((_type*)belle_sip_object_cast((belle_sip_object_t *)(obj), _type##_id, #_type, __FILE__, __LINE__))
#define BELLE_SIP_OBJECT(obj) BELLE_SIP_CAST(obj,belle_sip_object_t)
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;
#include "belle-sip/list.h"
#include "belle-sip/mainloop.h"
#include "belle-sip/uri.h"
......@@ -83,6 +107,9 @@ void *belle_sip_object_cast(belle_sip_object_t *obj, belle_sip_type_id_t id, con
#include "belle-sip/parameters.h"
#include "belle-sip/message.h"
#include "belle-sip/transaction.h"
#include "belle-sip/sipstack.h"
#include "belle-sip/listeningpoint.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_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),
* 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);
const char *belle_sip_listening_point_get_ip_address(const belle_sip_listening_point_t *ip);
BELLE_SIP_END_DECLS
#endif
......@@ -38,6 +38,7 @@ typedef int (*belle_sip_source_func_t)(void *user_data, unsigned int events);
typedef struct belle_sip_main_loop belle_sip_main_loop_t;
BELLE_SIP_BEGIN_DECLS
void belle_sip_main_loop_add_source(belle_sip_main_loop_t *ml, belle_sip_source_t *source);
......@@ -87,4 +88,6 @@ void belle_sip_main_loop_quit(belle_sip_main_loop_t *ml);
**/
void belle_sip_main_loop_cancel_source(belle_sip_main_loop_t *ml, unsigned long id);
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_stack_h
#define belle_sip_stack_h
BELLE_SIP_BEGIN_DECLS
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);
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);
void belle_sip_stack_sleep(belle_sip_stack_t *stack, unsigned int milliseconds);
BELLE_SIP_END_DECLS
#endif
......@@ -33,6 +33,7 @@ typedef enum belle_sip_transaction_state{
BELLE_SIP_TRANSACTION_TERMINATED
}belle_sip_transaction_state_t;
BELLE_SIP_BEGIN_DECLS
void *belle_sip_transaction_get_application_data(const belle_sip_transaction_t *t);
void belle_sip_transaction_set_application_data(belle_sip_transaction_t *t, void *data);
......@@ -58,5 +59,7 @@ belle_sip_client_transaction_t * belle_sip_client_transaction_new(belle_sip_requ
belle_sip_server_transaction_t * belle_sip_server_transaction_new(belle_sip_request_t *req);
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_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
......@@ -10,8 +10,12 @@ generated_src= \
belle_sip_messageParser.c belle_sip_messageParser.h \
belle_sip_messageLexer.c belle_sip_messageLexer.h
$(generated_src) : $(grammar_files)
$(builddir)/generated_src_stamp : $(grammar_files)
$(ANTLR) -make -fo $(builddir) $(grammar_files)
touch $(builddir)/generated_src_stamp
$(generated_src) : $(builddir)/generated_src_stamp
BUILT_SOURCES=$(generated_src)
......@@ -24,13 +28,17 @@ libbellesip_generated_la_CFLAGS=$(LESS_STRICT_OPTIONS)
lib_LTLIBRARIES=libbellesip.la
libbellesip_la_SOURCES=belle_sip_uri_impl.c \
libbellesip_la_SOURCES=clock_gettime.h \
belle_sip_uri_impl.c \
belle_sip_headers_impl.c \
belle_sip_utils.c belle_sip_internal.h \
belle_sip_object.c \
belle_sip_loop.c \
belle_sip_resolver.c belle_sip_resolver.h \
transaction.c
belle_sip_parameters.c \
transaction.c \
listeningpoint.c \
sipstack.c
libbellesip_la_CFLAGS=$(STRICT_OPTIONS)
......@@ -40,4 +48,4 @@ INCLUDES=-I$(top_srcdir)/include
EXTRA_DIST=$(grammar_files)
CLEANFILES=$(generated_src) *.tokens
CLEANFILES=$(generated_src) *.tokens generated_src_stamp
......@@ -34,18 +34,25 @@ typedef void (*belle_sip_object_destroy_t)(belle_sip_object_t*);
struct _belle_sip_object{
uint8_t type_ids[8]; /*table of belle_sip_type_id_t for all inheritance chain*/
int ref;
void *vptr;
belle_sip_object_destroy_t destroy;
};
belle_sip_object_t * _belle_sip_object_new(size_t objsize, belle_sip_type_id_t id, belle_sip_object_destroy_t destroy_func, int initially_unowed);
belle_sip_object_t * _belle_sip_object_new(size_t objsize, belle_sip_type_id_t id, void *vptr, belle_sip_object_destroy_t destroy_func, int initially_unowed);
void _belle_sip_object_init_type(belle_sip_object_t *obj, belle_sip_type_id_t id);
void belle_sip_object_init(belle_sip_object_t *obj);
#define belle_sip_object_new(_type,destroy) (_type*)_belle_sip_object_new(sizeof(_type),BELLE_SIP_TYPE_ID(_type),destroy,0)
#define belle_sip_object_new_unowed(_type,destroy) (_type*)_belle_sip_object_new(sizeof(_type),BELLE_SIP_TYPE_ID(_type),destroy,1)
#define belle_sip_object_new(_type,destroy) (_type*)_belle_sip_object_new(sizeof(_type),BELLE_SIP_TYPE_ID(_type),NULL,(belle_sip_object_destroy_t)destroy,0)
#define belle_sip_object_new_unowed(_type,destroy) (_type*)_belle_sip_object_new(sizeof(_type),BELLE_SIP_TYPE_ID(_type),NULL,(belle_sip_object_destroy_t)destroy,1)
#define belle_sip_object_init_type(obj, _type) _belle_sip_object_init_type((belle_sip_object_t*)obj, BELLE_SIP_TYPE_ID(_type))
#define belle_sip_object_new_with_vptr(_type,vptr,destroy) (_type*)_belle_sip_object_new(sizeof(_type),BELLE_SIP_TYPE_ID(_type),vptr,(belle_sip_object_destroy_t)destroy,0)
#define belle_sip_object_new_unowed_with_vptr(_type,vptr,destroy) (_type*)_belle_sip_object_new(sizeof(_type),BELLE_SIP_TYPE_ID(_type),vptr,(belle_sip_object_destroy_t)destroy,1)
#define BELLE_SIP_OBJECT_VPTR(obj,vptr_type) ((vptr_type*)(((belle_sip_object_t*)obj)->vptr))
struct _belle_sip_list {
struct _belle_sip_list *next;
struct _belle_sip_list *prev;
......@@ -339,6 +346,16 @@ struct _belle_sip_parameters {
void belle_sip_parameters_init(belle_sip_parameters_t *obj);
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);
#ifdef __cplusplus
}
#endif
......
......@@ -23,13 +23,14 @@
#include <poll.h>
void belle_sip_source_destroy(belle_sip_source_t *obj){
static void belle_sip_source_destroy(belle_sip_source_t *obj){
if (obj->node.next || obj->node.prev){
belle_sip_fatal("Destroying source currently used in main loop !");
}
belle_sip_free(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->id=global_id++;
......@@ -41,7 +42,7 @@ void belle_sip_fd_source_init(belle_sip_source_t *s, belle_sip_source_func_t fun
}
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 *s=belle_sip_new0(belle_sip_source_t);
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;
}
......@@ -58,13 +59,20 @@ struct belle_sip_main_loop{
int control_fds[2];
};
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);
close(ml->control_fds[0]);
close(ml->control_fds[1]);
}
static int main_loop_done(void *data, unsigned int events){
belle_sip_debug("Got data on control fd...");
return TRUE;
}
belle_sip_main_loop_t *belle_sip_main_loop_new(void){
belle_sip_main_loop_t*m=belle_sip_new0(belle_sip_main_loop_t);
belle_sip_main_loop_t*m=belle_sip_object_new(belle_sip_main_loop_t, belle_sip_main_loop_destroy);
if (pipe(m->control_fds)==-1){
belle_sip_fatal("Could not create control pipe.");
}
......@@ -207,10 +215,3 @@ void belle_sip_main_loop_sleep(belle_sip_main_loop_t *ml, int milliseconds){
belle_sip_main_loop_run(ml);
}
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);
close(ml->control_fds[0]);
close(ml->control_fds[1]);
belle_sip_free(ml);
}
......@@ -35,10 +35,11 @@ void _belle_sip_object_init_type(belle_sip_object_t *obj, belle_sip_type_id_t id
*t=id;
}
belle_sip_object_t * _belle_sip_object_new(size_t objsize, belle_sip_type_id_t id, belle_sip_object_destroy_t destroy_func, int initially_unowed){
belle_sip_object_t * _belle_sip_object_new(size_t objsize, belle_sip_type_id_t id, void *vptr, belle_sip_object_destroy_t destroy_func, int initially_unowed){
belle_sip_object_t *obj=(belle_sip_object_t *)belle_sip_malloc0(objsize);
obj->type_ids[0]=id;
obj->ref=initially_unowed ? 0 : 1;
obj->vptr=vptr;
obj->destroy=destroy_func;
return obj;
}
......@@ -47,12 +48,13 @@ int belle_sip_object_is_unowed(const belle_sip_object_t *obj){
return obj->ref==0;
}
belle_sip_object_t * _belle_sip_object_ref(belle_sip_object_t *obj){
obj->ref++;
belle_sip_object_t * belle_sip_object_ref(void *obj){
BELLE_SIP_OBJECT(obj)->ref++;
return obj;
}
void _belle_sip_object_unref(belle_sip_object_t *obj){
void belle_sip_object_unref(void *ptr){
belle_sip_object_t *obj=BELLE_SIP_OBJECT(ptr);
if (obj->ref==0){
belle_sip_warning("Destroying unowed object");
belle_sip_object_destroy(obj);
......@@ -64,7 +66,8 @@ void _belle_sip_object_unref(belle_sip_object_t *obj){
}
}
void _belle_sip_object_destroy(belle_sip_object_t *obj){
void belle_sip_object_destroy(void *ptr){
belle_sip_object_t *obj=BELLE_SIP_OBJECT(ptr);
if (obj->ref!=0){
belle_sip_error("Destroying referenced object !");
if (obj->destroy) obj->destroy(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/>.
*/
#include "belle_sip_internal.h"
#ifndef WIN32
#include <sys/types.h>
#include <sys/socket.h>
#else
#endif
/*
Channels: udp
*/
struct belle_sip_channel{
belle_sip_object_t base;
struct addrinfo peer;
struct sockaddr_storage peer_addr;
};
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_channel_vptr_t;
static void belle_sip_channel_init(belle_sip_channel_t *obj){
belle_sip_object_init_type(obj,belle_sip_channel_t);
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);
}
const struct addrinfo * belle_sip_channel_get_peer(belle_sip_channel_t *obj){
return &obj->peer;
}
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_error("Could not send UDP packet: %s",strerror(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;
obj->peer.ai_addrlen=sizeof(obj->peer_addr);
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 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_channel_vptr_t udp_channel_vptr={
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_udp_channel_t *belle_sip_udp_channel_new(const char *addr, int port){
belle_sip_udp_channel_t *obj=belle_sip_object_new_with_vptr(belle_sip_udp_channel_t,&udp_channel_vptr,udp_channel_uninit);
belle_sip_channel_init((belle_sip_channel_t*)obj);
obj->sock=create_udp_socket(addr,port);
if (obj->sock==-1){
belle_sip_object_unref(obj);
return NULL;
}
return obj;
}
/*
Listening points: base, udp
*/
struct belle_sip_listening_point{
belle_sip_object_t base;
belle_sip_stack_t *stack;
char *transport;
char *addr;
int port;
};
typedef struct belle_sip_listening_point_vptr{
belle_sip_channel_t * (*find_output_channel)(belle_sip_listening_point_t *lp,const struct addrinfo *dest);
} belle_sip_listening_point_vptr_t;
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){
belle_sip_object_init_type(lp,belle_sip_listening_point_t);
lp->transport=belle_sip_strdup(transport);
lp->port=port;
lp->addr=belle_sip_strdup(address);
lp->stack=s;
}
static void belle_sip_listening_point_uninit(belle_sip_listening_point_t *lp){
belle_sip_free(lp->addr);
belle_sip_free(lp->transport);
}
const char *belle_sip_listening_point_get_ip_address(const belle_sip_listening_point_t *lp){
return lp->addr;
}
int belle_sip_listening_point_get_port(const belle_sip_listening_point_t *lp){
return lp->port;
}
const char *belle_sip_listening_point_get_transport(const belle_sip_listening_point_t *lp){
return lp->transport;
}
belle_sip_channel_t *belle_sip_listening_point_find_output_channel (belle_sip_listening_point_t *lp,const struct addrinfo *dest){
return ((belle_sip_listening_point_vptr_t*)lp->base.vptr)->find_output_channel(lp,dest);
}
struct belle_sip_udp_listening_point{
belle_sip_listening_point_t base;
belle_sip_udp_channel_t *channel;
};
static belle_sip_channel_t *udp_listening_point_find_output_channel(belle_sip_listening_point_t* obj,const struct addrinfo *dest){
belle_sip_udp_listening_point_t *lp=(belle_sip_udp_listening_point_t*)obj;
belle_sip_udp_channel_set_dest(lp->channel,dest);
return BELLE_SIP_CHANNEL(lp);
}
static void belle_sip_udp_listening_point_uninit(belle_sip_udp_listening_point_t *lp){
belle_sip_object_unref(lp->channel);
belle_sip_listening_point_uninit((belle_sip_listening_point_t*)lp);
}
static belle_sip_listening_point_vptr_t udp_listening_point_vptr={
udp_listening_point_find_output_channel
};
belle_sip_listening_point_t * belle_sip_udp_listening_point_new(belle_sip_stack_t *s, const char *ipaddress, int port){
belle_sip_udp_listening_point_t *lp=belle_sip_object_new_with_vptr(belle_sip_udp_listening_point_t,&udp_listening_point_vptr,belle_sip_udp_listening_point_uninit);
belle_sip_listening_point_init((belle_sip_listening_point_t*)lp,s,"UDP",ipaddress,port);
lp->channel=belle_sip_udp_channel_new(ipaddress,port);
if (lp->channel==NULL){
belle_sip_object_unref(lp);
lp=NULL;
}
return BELLE_SIP_LISTENING_POINT(lp);
}
/*
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"
struct belle_sip_stack{
belle_sip_main_loop_t *ml;
belle_sip_list_t *lp;/*list of listening points*/
};
static void belle_sip_stack_destroy(belle_sip_stack_t *stack){
belle_sip_object_unref(stack->ml);
belle_sip_list_for_each (stack->lp,belle_sip_object_unref);
belle_sip_list_free(stack->lp);
}
belle_sip_stack_t * belle_sip_stack_new(const char *properties){
belle_sip_stack_t *stack=belle_sip_object_new(belle_sip_stack_t,belle_sip_stack_destroy);
stack->ml=belle_sip_main_loop_new ();
return stack;
}
belle_sip_listening_point_t *belle_sip_stack_create_listening_point(belle_sip_stack_t *s, const char *ipaddress, int port, const char *transport){
belle_sip_listening_point_t *lp=NULL;
if (strcasecmp(transport,"UDP")==0){
lp=belle_sip_udp_listening_point_new (s,ipaddress,port);
}else{
belle_sip_fatal("Unsupported transport %s",transport);
}
if