static int belle_sip_udp_listening_point_init_socket(belle_sip_udp_listening_point_t *lp){
int port=belle_sip_uri_get_listening_port(((belle_sip_listening_point_t*)lp)->listening_uri);
lp->sock=create_udp_socket(belle_sip_uri_get_host(((belle_sip_listening_point_t*)lp)->listening_uri)
,&port,&lp->base.ai_family);
if(lp->sock==(belle_sip_socket_t)-1){
return -1;
}
belle_sip_uri_set_port(((belle_sip_listening_point_t*)lp)->listening_uri,port);
if(lp->base.stack->dscp)belle_sip_socket_set_dscp(lp->sock,lp->base.ai_family,lp->base.stack->dscp);
lp->source=belle_sip_socket_source_new((belle_sip_source_func_t)on_udp_data,lp,lp->sock,BELLE_SIP_EVENT_READ,-1);
belle_sip_main_loop_add_source(((belle_sip_listening_point_t*)lp)->stack->ml,lp->source);
return 0;
}
/*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[4096];
struct sockaddr_storage addr;
socklen_t addrlen=sizeof(addr);
if (events & BELLE_SIP_EVENT_READ){
belle_sip_debug("udp_listening_point: data to read.");
err=recvfrom(lp->sock,(char*)buf,sizeof(buf),MSG_PEEK,(struct sockaddr*)&addr,&addrlen);
if (err==-1){
char *tmp=belle_sip_object_to_string((belle_sip_object_t*) ((belle_sip_listening_point_t*)lp)->listening_uri);
belle_sip_error("udp_listening_point: recvfrom() failed on [%s], : [%s] reopening server socket"
,tmp
,belle_sip_get_socket_error_string());
belle_sip_free(tmp);
belle_sip_udp_listening_point_uninit(lp);
/*cleanalludpchannelsthatareactuallysharingtheserversocketwiththelisteningpoints*/
belle_sip_listening_point_clean_channels((belle_sip_listening_point_t*)lp);
belle_sip_udp_listening_point_init_socket(lp);
}else{
belle_sip_channel_t *chan;
structaddrinfoai={0};
/*preservetheV4mapping*/
ai.ai_family=addr.ss_family;
ai.ai_addr=(struct sockaddr*)&addr;
ai.ai_addrlen=addrlen;
chan=_belle_sip_listening_point_get_channel((belle_sip_listening_point_t*)lp,NULL,&ai);
if(chan==NULL){
/*TODO: shouldrathercreatethechannelwithreallocalipandportandnotjust 0.0.0.0"*/
chan=belle_sip_channel_new_udp_with_addr(lp->base.stack
,lp->sock
,belle_sip_uri_get_host(lp->base.listening_uri)
,belle_sip_uri_get_port(lp->base.listening_uri)
,&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){
/*notifythechannel*/
/*belle_sip_debug("Notifying udp channel, local [%s:%i] remote [%s:%i]"
,chan->local_ip
,chan->local_port
,chan->peer_name
,chan->peer_port);*/
belle_sip_message("Notifying udp channel, local [%s:%i] remote [%s:%i]"
,chan->local_ip
,chan->local_port
,chan->peer_name
,chan->peer_port);
belle_sip_message("Knowchat: [1] belle_sip_channel_process_data");
belle_sip_channel_process_data(chan,events);
}
}
}
returnBELLE_SIP_CONTINUE;
}