Commit c848bbc3 authored by Simon Morlat's avatar Simon Morlat

implement automatic via generation

parent ff070124
......@@ -20,6 +20,7 @@
#ifndef belle_sip_provider_h
#define belle_sip_provider_h
#define BELLE_SIP_BRANCH_MAGIC_COOKIE "z9hG4bK"
BELLE_SIP_BEGIN_DECLS
......
......@@ -127,3 +127,25 @@ unsigned long belle_sip_resolve(const char *name, int port, unsigned int hints,
}
}
void belle_sip_get_src_addr_for(const struct sockaddr *dest, socklen_t destlen, struct sockaddr *src, socklen_t *srclen){
int af_type=(destlen==sizeof(struct sockaddr_in6)) ? AF_INET6 : AF_INET;
int sock=socket(af_type,SOCK_DGRAM,IPPROTO_UDP);
memset(src,0,*srclen);
if (sock==-1){
belle_sip_fatal("Could not create socket: %s",strerror(errno));
return;
}
if (connect(sock,dest,destlen)==-1){
belle_sip_error("belle_sip_get_src_addr_for: connect() failed: %s",strerror(errno));
close(sock);
return;
}
if (getsockname(sock,src,srclen)==-1){
belle_sip_error("belle_sip_get_src_addr_for: getsockname() failed: %s",strerror(errno));
close(sock);
return;
}
}
......@@ -58,6 +58,7 @@ struct belle_sip_resolver_context{
struct addrinfo * belle_sip_ip_address_to_addrinfo(const char *ipaddress, int port);
unsigned long belle_sip_resolve(const char *name, int port, unsigned int hints, belle_sip_resolver_callback_t cb , void *data, belle_sip_main_loop_t *ml);
void belle_sip_get_src_addr_for(const struct sockaddr *dest, socklen_t destlen, struct sockaddr *src, socklen_t *srclen);
#endif
......@@ -40,6 +40,7 @@ static const char *channel_state_to_string(belle_sip_channel_state_t state){
static void belle_sip_channel_destroy(belle_sip_channel_t *obj){
if (obj->peer) freeaddrinfo(obj->peer);
belle_sip_free(obj->peer_name);
if (obj->local_ip) belle_sip_free(obj->local_ip);
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_channel_t);
......@@ -58,11 +59,15 @@ 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 *peername, int peer_port){
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){
obj->peer_name=belle_sip_strdup(peername);
obj->peer_port=peer_port;
obj->peer=NULL;
obj->stack=stack;
if (strcmp(bindip,"::0")!=0 && strcmp(bindip,"0.0.0.0")!=0)
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);
}
......@@ -85,11 +90,16 @@ int belle_sip_channel_matches(const belle_sip_channel_t *obj, const char *peerna
return 0;
}
const char *belle_sip_channel_get_local_address(belle_sip_channel_t *obj, int *port){
if (port) *port=obj->local_port;
return obj->local_ip;
}
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 * chain_sip_channel_get_transport_name(const belle_sip_channel_t *obj){
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;
}
......@@ -105,6 +115,8 @@ const struct addrinfo * belle_sip_channel_get_peer(belle_sip_channel_t *obj){
return obj->peer;
}
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;
......@@ -113,7 +125,9 @@ static void channel_set_state(belle_sip_channel_t *obj, belle_sip_channel_state_
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));
int len;
BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_sending,obj,msg);
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){
......@@ -146,6 +160,24 @@ 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){
char name[NI_MAXHOST];
char serv[NI_MAXSERV];
if (obj->local_ip==NULL){
int err=getnameinfo(addr,slen,name,sizeof(name),serv,sizeof(serv),NI_NUMERICHOST|NI_NUMERICSERV);
if (err!=0){
belle_sip_error("belle_sip_channel_connect(): getnameinfo() failed: %s",gai_strerror(err));
}else{
obj->local_ip=belle_sip_strdup(name);
obj->local_port=atoi(serv);
belle_sip_message("Channel has local address %s:%s",name,serv);
}
}
channel_set_state(obj,BELLE_SIP_CHANNEL_READY);
channel_process_queue(obj);
}
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;
......@@ -165,7 +197,8 @@ int belle_sip_channel_resolve(belle_sip_channel_t *obj){
}
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 ret=BELLE_SIP_OBJECT_VPTR(obj,belle_sip_channel_t)->connect(obj,obj->peer->ai_addr,obj->peer->ai_addrlen);
return ret;
}
int belle_sip_channel_queue_message(belle_sip_channel_t *obj, belle_sip_message_t *msg){
......@@ -215,8 +248,19 @@ static int udp_channel_recv(belle_sip_channel_t *obj, void *buf, size_t buflen){
}
int udp_channel_connect(belle_sip_channel_t *obj, const struct sockaddr *addr, socklen_t socklen){
channel_set_state(obj,BELLE_SIP_CHANNEL_READY);
channel_process_queue(obj);
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;
}
......@@ -239,14 +283,14 @@ BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_udp_channel_t)=
}
};
belle_sip_channel_t * belle_sip_channel_new_udp(belle_sip_stack_t *stack, int sock, const char *dest, int port){
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,dest,port);
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 struct addrinfo *peer){
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];
......@@ -261,7 +305,7 @@ belle_sip_channel_t * belle_sip_channel_new_udp_with_addr(belle_sip_stack_t *sta
belle_sip_object_unref(obj);
return NULL;
}
belle_sip_channel_init((belle_sip_channel_t*)obj,stack,sock,name,atoi(serv));
belle_sip_channel_init((belle_sip_channel_t*)obj,stack,sock,bindip,localport,name,atoi(serv));
return (belle_sip_channel_t*)obj;
}
......
......@@ -47,6 +47,7 @@ typedef struct belle_sip_channel belle_sip_channel_t;
BELLE_SIP_DECLARE_INTERFACE_BEGIN(belle_sip_channel_listener_t)
void (*on_state_changed)(belle_sip_channel_listener_t *l, belle_sip_channel_t *, belle_sip_channel_state_t state);
int (*on_event)(belle_sip_channel_listener_t *l, belle_sip_channel_t *obj, unsigned revents);
void (*on_sending)(belle_sip_channel_listener_t *l, belle_sip_channel_t *obj, belle_sip_message_t *msg);
BELLE_SIP_DECLARE_INTERFACE_END
#define BELLE_SIP_CHANNEL_LISTENER(obj) BELLE_SIP_INTERFACE_CAST(obj,belle_sip_channel_listener_t)
......@@ -58,6 +59,8 @@ struct belle_sip_channel{
belle_sip_list_t *listeners;
char *peer_name;
int peer_port;
char *local_ip;
int local_port;
unsigned long resolver_id;
struct addrinfo *peer;
belle_sip_message_t *msg;
......@@ -65,9 +68,9 @@ 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(belle_sip_stack_t *stack, int sock, const char *peername, int peerport);
belle_sip_channel_t * belle_sip_channel_new_udp(belle_sip_stack_t *stack, int sock, const char *bindip, int localport, const char *peername, int peerport);
belle_sip_channel_t * belle_sip_channel_new_udp_with_addr(belle_sip_stack_t *stack, int sock, const struct addrinfo *ai);
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);
......@@ -89,10 +92,12 @@ 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 * chain_sip_channel_get_transport_name(const belle_sip_channel_t *obj);
const char * belle_sip_channel_get_transport_name(const belle_sip_channel_t *obj);
const struct addrinfo * belle_sip_channel_get_peer(belle_sip_channel_t *obj);
const char *belle_sip_channel_get_local_address(belle_sip_channel_t *obj, int *port);
/*just invokes the listeners to process data*/
void belle_sip_channel_process_data(belle_sip_channel_t *obj,unsigned int revents);
......
......@@ -133,7 +133,8 @@ static void belle_sip_udp_listening_point_uninit(belle_sip_udp_listening_point_t
}
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);
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;
}
......@@ -206,7 +207,7 @@ static int on_udp_data(belle_sip_udp_listening_point_t *lp, unsigned int events)
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,&ai);
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);
......
......@@ -355,6 +355,9 @@ belle_sip_request_t* belle_sip_request_create(belle_sip_uri_t *requri, const cha
int max_forward /*FIXME*/)
{
belle_sip_request_t *ret=belle_sip_request_new();
belle_sip_header_max_forwards_t *mf=belle_sip_header_max_forwards_new();
if (max_forward==0) max_forward=70;
belle_sip_header_max_forwards_set_max_forwards(mf,max_forward);
belle_sip_request_set_uri(ret,requri);
belle_sip_request_set_method(ret,method);
......@@ -363,7 +366,7 @@ belle_sip_request_t* belle_sip_request_create(belle_sip_uri_t *requri, const cha
belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(to));
belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(cseq));
belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(callid));
belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(mf));
return ret;
}
......
......@@ -48,7 +48,7 @@ static void belle_sip_provider_dispatch_message(belle_sip_provider_t *prov, bell
}
}
static void fix_via(belle_sip_request_t *msg, const struct addrinfo* origin){
static void fix_incoming_via(belle_sip_request_t *msg, const struct addrinfo* origin){
char received[NI_MAXHOST];
char rport[NI_MAXSERV];
belle_sip_header_via_t *via;
......@@ -65,6 +65,25 @@ static void fix_via(belle_sip_request_t *msg, const struct addrinfo* origin){
}
}
static void fix_outgoing_via(belle_sip_provider_t *p, belle_sip_channel_t *chan, belle_sip_message_t *msg){
belle_sip_header_via_t *via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header(msg,"via"));
belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(via),"rport",NULL);
if (belle_sip_header_via_get_host(via)==NULL){
const char *local_ip;
int local_port;
local_ip=belle_sip_channel_get_local_address(chan,&local_port);
belle_sip_header_via_set_host(via,local_ip);
belle_sip_header_via_set_port(via,local_port);
belle_sip_header_via_set_protocol(via,"SIP/2.0");
belle_sip_header_via_set_transport(via,belle_sip_channel_get_transport_name(chan));
}
if (belle_sip_header_via_get_branch(via)==NULL){
char *branchid=belle_sip_strdup_printf(BELLE_SIP_BRANCH_MAGIC_COOKIE "%x",belle_sip_random());
belle_sip_header_via_set_branch(via,branchid);
belle_sip_free(branchid);
}
}
static void belle_sip_provider_read_message(belle_sip_provider_t *prov, belle_sip_channel_t *chan){
char buffer[belle_sip_network_buffer_size];
int err;
......@@ -72,10 +91,10 @@ static void belle_sip_provider_read_message(belle_sip_provider_t *prov, belle_si
if (err>0){
belle_sip_message_t *msg;
buffer[err]='\0';
belle_sip_message("provider %p read message from %s:%i\n%s",chan->peer_name,chan->peer_port,buffer);
belle_sip_message("provider %p read message from %s:%i\n%s",prov,chan->peer_name,chan->peer_port,buffer);
msg=belle_sip_message_parse(buffer);
if (msg){
if (belle_sip_message_is_request(msg)) fix_via(BELLE_SIP_REQUEST(msg),chan->peer);
if (belle_sip_message_is_request(msg)) fix_incoming_via(BELLE_SIP_REQUEST(msg),chan->peer);
belle_sip_provider_dispatch_message(prov,msg);
}else{
belle_sip_error("Could not parse this message.");
......@@ -90,9 +109,14 @@ static int channel_on_event(belle_sip_channel_listener_t *obj, belle_sip_channel
return 0;
}
static void channel_on_sending(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, belle_sip_message_t *msg){
fix_outgoing_via((belle_sip_provider_t*)obj,chan,msg);
}
BELLE_SIP_IMPLEMENT_INTERFACE_BEGIN(belle_sip_provider_t,belle_sip_channel_listener_t)
channel_state_changed,
channel_on_event
channel_on_event,
channel_on_sending
BELLE_SIP_IMPLEMENT_INTERFACE_END
BELLE_SIP_DECLARE_IMPLEMENTED_INTERFACES_1(belle_sip_provider_t,belle_sip_channel_listener_t);
......@@ -175,13 +199,14 @@ belle_sip_channel_t * belle_sip_provider_get_channel(belle_sip_provider_t *p, co
return NULL;
}
void belle_sip_provider_send_request(belle_sip_provider_t *p, belle_sip_request_t *req){
belle_sip_hop_t hop={0};
belle_sip_channel_t *chan;
belle_sip_stack_get_next_hop(p->stack,req,&hop);
chan=belle_sip_provider_get_channel(p,hop.host, hop.port, hop.transport);
if (chan) belle_sip_channel_queue_message(chan,BELLE_SIP_MESSAGE(req));
if (chan) {
belle_sip_channel_queue_message(chan,BELLE_SIP_MESSAGE(req));
}
}
void belle_sip_provider_send_response(belle_sip_provider_t *p, belle_sip_response_t *resp){
......
......@@ -36,9 +36,7 @@ int main(int argc, char *argv[]){
belle_sip_header_cseq_create(20,"REGISTER"),
belle_sip_header_from_create("Tester <sip:tester@test.linphone.org>","a0dke45"),
belle_sip_header_to_create("Tester <sip:tester@test.linphone.org>",NULL),
belle_sip_header_via_create(belle_sip_listening_point_get_ip_address(lp),
belle_sip_listening_point_get_port(lp),
belle_sip_listening_point_get_transport(lp),"67687djeij"),
belle_sip_header_via_new(),
70);
char *tmp=belle_sip_object_to_string(BELLE_SIP_OBJECT(req));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment