BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END 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; int err; struct sockaddr_storage saddr; socklen_t slen=sizeof(saddr); if (!origin) { belle_sip_warning("cannot fix via for message [%p], probably a test",msg); return; } belle_sip_address_remove_v4_mapping(origin->ai_addr, (struct sockaddr*)&saddr, &slen); err=getnameinfo((struct sockaddr*)&saddr,slen,received,sizeof(received), rport,sizeof(rport),NI_NUMERICHOST|NI_NUMERICSERV); if (err!=0){ belle_sip_error("fix_via: getnameinfo() failed: %s",gai_strerror(errno)); return; } via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header((belle_sip_message_t*)msg,"via")); if (via){ const char* host = belle_sip_header_via_get_host(via); if (strcmp(host,received)!=0) belle_sip_header_via_set_received(via,received); if (belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(via),"rport")){ int port = belle_sip_header_via_get_listening_port(via); int rport_int=atoi(rport); if (rport_int!=port) belle_sip_header_via_set_rport(via,atoi(rport)); } } }
/*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]; sockaddr_x addr; socklen_t addrlen=sizeof(sockaddr_x); if (events & BELLE_SIP_EVENT_READ){ belle_sip_debug("udp_listening_point: data to read."); err=Xrecvfrom(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); /*clean all udp channels that are actually sharing the server socket with the listening points*/ 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; struct addrinfo ai={0}; belle_sip_address_remove_v4_mapping((struct sockaddr*)&addr,(struct sockaddr*)&addr,&addrlen); ai.ai_family=((struct sockaddr*)&addr)->sa_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: should rather create the channel with real local ip and port and not just 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); 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); } } if (chan){ /*notify the channel*/ 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_channel_process_data(chan,events); } } } return BELLE_SIP_CONTINUE; }
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){ struct sockaddr_storage saddr; socklen_t slen2=sizeof(saddr); int err; belle_sip_address_remove_v4_mapping(addr,(struct sockaddr*) &saddr,&slen2); err=getnameinfo((struct sockaddr*)&saddr,slen,name,sizeof(name),serv,sizeof(serv),NI_NUMERICHOST|NI_NUMERICSERV); if (err!=0){ belle_sip_error("belle_sip_channel_set_ready(): 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); channel_end_send_background_task(obj); }