Example #1
0
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){
		belle_sip_listening_point_add_channel(obj,chan);
	}
	return chan;
}
/*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 on_new_connection(void *userdata, unsigned int events){
	belle_sip_socket_t child;
	struct sockaddr_storage addr;
	socklen_t slen=sizeof(addr);
	belle_sip_stream_listening_point_t *lp=(belle_sip_stream_listening_point_t*)userdata;
	belle_sip_channel_t *chan;
	
	child=accept(lp->server_sock,(struct sockaddr*)&addr,&slen);
	if (child==(belle_sip_socket_t)-1){
		belle_sip_error("Listening point [%p] accept() failed on TCP server socket: %s",lp,belle_sip_get_socket_error_string());
		belle_sip_stream_listening_point_destroy_server_socket(lp);
		belle_sip_stream_listening_point_setup_server_socket(lp,on_new_connection);
		return BELLE_SIP_STOP;
	}
	belle_sip_message("New connection arriving !");
	chan=belle_sip_stream_channel_new_child(lp->base.stack,child,(struct sockaddr*)&addr,slen);
	if (chan) belle_sip_listening_point_add_channel((belle_sip_listening_point_t*)lp,chan);
	return BELLE_SIP_CONTINUE;
}