/*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; }
static int tls_process_data(belle_sip_channel_t *obj,unsigned int revents){ belle_sip_tls_channel_t* channel=(belle_sip_tls_channel_t*)obj; if (obj->state == BELLE_SIP_CHANNEL_CONNECTING ) { if (!channel->socket_connected) { channel->socklen=sizeof(channel->ss); if (finalize_stream_connection((belle_sip_stream_channel_t*)obj,revents,(struct sockaddr*)&channel->ss,&channel->socklen)) { goto process_error; } belle_sip_message("Channel [%p]: Connected at TCP level, now doing TLS handshake",obj); channel->socket_connected=1; belle_sip_source_set_events((belle_sip_source_t*)channel,BELLE_SIP_EVENT_READ|BELLE_SIP_EVENT_ERROR); belle_sip_source_set_timeout((belle_sip_source_t*)obj,belle_sip_stack_get_transport_timeout(obj->stack)); if (tls_process_handshake(obj)==-1) goto process_error; }else{ if (revents & BELLE_SIP_EVENT_READ){ if (tls_process_handshake(obj)==-1) goto process_error; }else if (revents==BELLE_SIP_EVENT_TIMEOUT){ belle_sip_error("channel [%p]: SSL handshake took too much time.",obj); goto process_error; }else{ belle_sip_warning("channeEHHCXCCCl [%p]: unexpected event [%i] during TLS handshake.",obj,revents); } } } else if ( obj->state == BELLE_SIP_CHANNEL_READY) { return belle_sip_channel_process_data(obj,revents); } else { belle_sip_warning("Unexpected event [%i], for channel [%p]",revents,channel); return BELLE_SIP_STOP; } return BELLE_SIP_CONTINUE; process_error: belle_sip_error("Cannot connect to [%s://%s:%i]",belle_sip_channel_get_transport_name(obj),obj->peer_name,obj->peer_port); channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR); return BELLE_SIP_STOP; }