Commit 49e0dcb7 authored by Simon Morlat's avatar Simon Morlat

fix problem with udp channel duplicated

parent 461029db
......@@ -417,6 +417,12 @@ void belle_sip_channel_init(belle_sip_channel_t *obj, belle_sip_stack_t *stack,c
obj->local_ip=belle_sip_strdup(bindip);
obj->local_port=localport;
obj->simulated_recv_return=1;/*not set*/
if (peername){
/*check if we are given a real dns name or just an ip address*/
struct addrinfo *ai=belle_sip_ip_address_to_addrinfo(AF_UNSPEC,peername,peer_port);
if (ai) freeaddrinfo(ai);
else obj->has_name=TRUE;
}
belle_sip_channel_input_stream_reset(&obj->input_stream);
update_inactivity_timer(obj,FALSE);
}
......
......@@ -97,6 +97,7 @@ struct belle_sip_channel{
int simulated_recv_return; /* used to simulate network error. 0= no data (disconnected) >0= do nothing -1= network error*/
unsigned char force_close; /* when channel is intentionnaly disconnected, in order to prevent looping notifications*/
unsigned char learnt_ip_port;
unsigned char has_name; /*set when the name of the peer is known, which is not the case of inboud connections*/
};
#define BELLE_SIP_CHANNEL(obj) BELLE_SIP_CAST(obj,belle_sip_channel_t)
......
......@@ -45,14 +45,24 @@ static void belle_sip_listening_point_uninit(belle_sip_listening_point_t *lp){
void belle_sip_listening_point_add_channel(belle_sip_listening_point_t *lp, belle_sip_channel_t *chan){
chan->lp=lp;
belle_sip_channel_add_listener(chan,lp->channel_listener); /*add channel listener*/
lp->channels=belle_sip_list_append(lp->channels,chan);/*channel is already owned*/
/*channel is already owned, no ref needed - REVISIT: channel should be initally unowned probably.*/
/* The channel with names must be treated with higher priority by the get_channel() method so queued on front.
* This is to prevent the UDP listening point to dispatch incoming messages to channels that were created by inbound connection
* where name cannot be determined. When this arrives, there can be 2 channels for the same destination IP and strange problems can occur
* where requests are sent through name qualified channel and response received through name unqualified channel.
*/
if (chan->has_name)
lp->channels=belle_sip_list_prepend(lp->channels,chan);
else
lp->channels=belle_sip_list_append(lp->channels,chan);
}
belle_sip_channel_t *belle_sip_listening_point_create_channel(belle_sip_listening_point_t *obj, const belle_sip_hop_t *hop){
belle_sip_channel_t *chan=BELLE_SIP_OBJECT_VPTR(obj,belle_sip_listening_point_t)->create_channel(obj,hop);
if (chan){
chan->lp=obj;
belle_sip_listening_point_add_channel(obj,chan);
}
return chan;
......
......@@ -25,19 +25,20 @@ BELLE_SIP_DECLARE_CUSTOM_VPTR_END
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){
/*no close of the socket, because it is owned by the listerning point and shared between all channels*/
}
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->current_peer->ai_addr,obj->current_peer->ai_addrlen);
belle_sip_socket_t sock=belle_sip_source_get_socket((belle_sip_source_t*)chan);
err=sendto(sock,buf,buflen,0,obj->current_peer->ai_addr,obj->current_peer->ai_addrlen);
if (err==-1){
belle_sip_error("channel [%p]: could not send UDP packet because [%s]",obj,belle_sip_get_socket_error_string());
return -errno;
......@@ -50,7 +51,9 @@ static int udp_channel_recv(belle_sip_channel_t *obj, void *buf, size_t buflen){
int err;
struct sockaddr_storage addr;
socklen_t addrlen=sizeof(addr);
err=recvfrom(chan->sock,buf,buflen,0,(struct sockaddr*)&addr,&addrlen);
belle_sip_socket_t sock=belle_sip_source_get_socket((belle_sip_source_t*)chan);
err=recvfrom(sock,buf,buflen,0,(struct sockaddr*)&addr,&addrlen);
if (err==-1 && get_socket_error()!=BELLESIP_EWOULDBLOCK){
belle_sip_error("Could not receive UDP packet: %s",belle_sip_get_socket_error_string());
......@@ -86,38 +89,25 @@ BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_udp_channel_t)=
udp_channel_connect,
udp_channel_send,
udp_channel_recv
/*no close method*/
}
};
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,bindip,localport,NULL,dest,port);
obj->sock=sock;
belle_sip_channel_set_socket((belle_sip_channel_t*)obj,sock,NULL);
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,hints={0};
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,bindip,localport,NULL,name,atoi(serv));
hints.ai_family=peer->ai_family;
err=getaddrinfo(name,serv,&hints,&obj->base.current_peer); /*might be optimized someway ?*/
if (err!=0){
belle_sip_error("getaddrinfo() failed for udp channel [%p] error [%s]",obj,gai_strerror(err));
}
obj->base.peer_list=obj->base.current_peer;
belle_sip_channel_init_with_addr((belle_sip_channel_t*)obj,stack,peer->ai_addr, peer->ai_addrlen);
obj->base.local_port=localport;
belle_sip_channel_set_socket((belle_sip_channel_t*)obj,sock,NULL);
/*this lookups the local address*/
udp_channel_connect((belle_sip_channel_t*)obj,peer);
return (belle_sip_channel_t*)obj;
}
......@@ -158,7 +158,6 @@ static int on_udp_data(belle_sip_udp_listening_point_t *lp, unsigned int events)
,&ai);
if (chan!=NULL){
belle_sip_message("udp_listening_point: new channel created to %s:%i",chan->peer_name,chan->peer_port);
chan->lp=(belle_sip_listening_point_t*)lp; /*FIXME, exactly the same code as for channel creation from provider. might be good to factorize*/
belle_sip_listening_point_add_channel((belle_sip_listening_point_t*)lp,chan);
}
}
......
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