/**
 * Accepts an incoming connection by forking a receiver process.
 * @param server_sock - socket that this connection came in to
 * @param new_sock - socket to be update with the value of the accepter socket
 * @returns 1 on success, 0 on error
 */
inline static int accept_connection(int server_sock,int *new_sock)
{
	unsigned int length;
	struct sockaddr_in remote;
	int pid;
		
	/* do accept */
	length = sizeof( struct sockaddr_in);
	*new_sock = accept( server_sock, (struct sockaddr*)&remote, &length);

	if (*new_sock==-1) {
		LOG(L_ERR,"ERROR:accept_connection(): accept failed!\n");
		goto error;
	} else {
		LOG(L_INFO,"INFO:accept_connection(): new tcp connection accepted!\n");
		
	}
	
	/* initialise stuff for the new socket, to handle later. */
	receiver_init(*new_sock,0);

	#ifdef CDP_FOR_SER
		pid = fork_process(server_sock,"receiver R",0);
	#else
		pid = fork();
	#endif	
	if (pid<0){
		LOG(L_ERR,"ERROR:accept_connection(): fork() failed > %s\n",strerror(errno));
		goto error;
	}
	if (pid==0){		
		/* child */
		if (listening_socks) {
			pkg_free(listening_socks);
			listening_socks=0;
		}
		dp_add_pid(pid);
		
		/* jump to this method in recieve.c */
		receiver_process(*new_sock);
		LOG(L_CRIT,"ERROR:accept_connection(): receiver_process finished without exit!\n");
		exit(-1);
	}else{
		/* parent */
		LOG(L_INFO,"INFO:accept_connection(): Receiver process forked [%d]\n",pid);
	}
	
	return 1;
error:
	return 0;
}
Beispiel #2
0
/**
 * Start the CDiameterPeer operations.
 * It forks all the processes required.
 * @param blocking - if this is set, use the calling processes for the timer and never
 * return; else fork a new one for the timer and return
 * @returns 1 on success, 0 on error, never if blocking
 */
int diameter_peer_start(int blocking)
{
	int pid;
	int k=0;
	peer *p;

	/* fork workers */
	for(k=0;k<config->workers;k++){
		pid = fork_process(1001+k,"cdp_worker",1);
		if (pid==-1){
			LM_CRIT("init_diameter_peer(): Error on fork() for worker!\n");
			return 0;
		}
		if (pid==0) {
			srandom(time(0)*k);
			snprintf(pt[process_no].desc, MAX_PT_DESC,"cdp worker child=%d", k );
			if (cfg_child_init()) return 0;
			worker_process(k);
			LM_CRIT("init_diameter_peer(): worker_process finished without exit!\n");
			exit(-1);
		}else{
			dp_add_pid(pid);
		}
	}

	/* init the fd_exchange pipes */
	receiver_init(NULL);
	for(p = peer_list->head,k=0;p;p=p->next,k++)
		receiver_init(p);


	/* fork receiver for unknown peers */

	pid = fork_process(1001+k,"cdp_receiver_peer_unkown",1);

	if (pid==-1){
		LM_CRIT("init_diameter_peer(): Error on fork() for unknown peer receiver!\n");
		return 0;
	}
	if (pid==0) {
		srandom(time(0)*k);
		snprintf(pt[process_no].desc, MAX_PT_DESC,
				"cdp receiver peer unknown");
		if (cfg_child_init()) return 0;
		receiver_process(NULL);
		LM_CRIT("init_diameter_peer(): receiver_process finished without exit!\n");
		exit(-1);
	}else{
		dp_add_pid(pid);
	}

	/* fork receivers for each pre-configured peers */
	lock_get(peer_list_lock);
	for(p = peer_list->head,k=-1;p;p = p->next,k--){
		pid = fork_process(1001+k,"cdp_receiver_peer",1);
		if (pid==-1){
			LM_CRIT("init_diameter_peer(): Error on fork() for peer receiver!\n");
			return 0;
		}
		if (pid==0) {
			srandom(time(0)*k);
				snprintf(pt[process_no].desc, MAX_PT_DESC,
					"cdp_receiver_peer=%.*s", p->fqdn.len,p->fqdn.s );
			if (cfg_child_init()) return 0;
			receiver_process(p);
			LM_CRIT("init_diameter_peer(): receiver_process finished without exit!\n");
			exit(-1);
		}else{
			dp_add_pid(pid);
		}
	}
	lock_release(peer_list_lock);


	/* Fork the acceptor process (after receivers, so it inherits all the right sockets) */
	pid = fork_process(1000,"cdp_acceptor",1);

	if (pid==-1){
		LM_CRIT("init_diameter_peer(): Error on fork() for acceptor!\n");
		return 0;
	}
	if (pid==0) {
		if (cfg_child_init()) return 0;
		acceptor_process(config);
		LM_CRIT("init_diameter_peer(): acceptor_process finished without exit!\n");
		exit(-1);
	}else{
		dp_add_pid(pid);
	}

	/* fork/become timer */
	if (blocking) {
		dp_add_pid(getpid());
		if (cfg_child_init()) return 0;
		timer_process(1);
	}
	else{
		pid = fork_process(1001,"cdp_timer",1);
		if (pid==-1){
			LM_CRIT("init_diameter_peer(): Error on fork() for timer!\n");
			return 0;
		}
		if (pid==0) {
			if (cfg_child_init()) return 0;
			timer_process(0);
			LM_CRIT("init_diameter_peer(): timer_process finished without exit!\n");
			exit(-1);
		}else{
			dp_add_pid(pid);
		}
	}

	return 1;
}
Beispiel #3
0
/**
 * Initiate a connection to a peer.
 * @param p - peer to connect to
 * @returns socket if OK, -1 on error
 */
int peer_connect(peer *p)
{
	int sock;
	int pid;
	unsigned char servip[4];
	struct sockaddr_in servaddr;
	unsigned int option = 1;
	struct hostent *host=0;

	host = gethostbyname(p->fqdn.s);
	if (!host){
		LOG(L_WARN,"WARNING:peer_connect(): Error opening connection to %.*s:%d >%s\n",
			p->fqdn.len,p->fqdn.s,p->port,strerror(h_errno));
		goto error;
	}
		
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if ( sock==-1) {
		LOG(L_ERR,"ERROR:peer_connect(): cannot connect, failed to create "
				"new socket\n");
		goto error;
	}
	memset( &servip, 0, sizeof(servip) );
	memcpy( &servip, host->h_addr_list[0], 4);
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(p->port);
	servaddr.sin_addr.s_addr = *(unsigned int*)servip;

	if (connect(sock,(struct sockaddr*)&servaddr, sizeof(struct sockaddr_in))!=0) {
		LOG(L_WARN,"WARNING:peer_connect(): Error opening connection to %.*s:%d >%s\n",
			p->fqdn.len,p->fqdn.s,p->port,strerror(errno));		
		goto error;
	}
	
	setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&option,sizeof(option));
	
	LOG(L_INFO,"INFO:peer_connect(): Peer %.*s:%d connected\n",p->fqdn.len,p->fqdn.s,p->port);

	
	receiver_init(sock,p);
	
	#ifdef CDP_FOR_SER
		pid = fork_process(p->port,"receiver I",0);
	#else
		pid = fork();
	#endif
	if (pid<0){
		LOG(L_ERR,"ERROR:peer_connect(): fork() failed > %s\n",strerror(errno));
		goto error;
	}
	if (pid==0){
		/* child */
		receiver_process(sock);
		LOG(L_CRIT,"ERROR:peer_connect(): receiver_process finished without exit!\n");
		exit(-1);
	}else{
		/* parent */
		LOG(L_INFO,"INFO:peer_connect(): Receiver process forked [%d]\n",pid);
		
		dp_add_pid(pid);
	}
		
	return sock;
error:
	return -1;	
}
Beispiel #4
0
/**
 * Initiate a connection to a peer.
 * @param p - peer to connect to
 * @returns socket if OK, -1 on error
 */
int peer_connect(peer *p)
{
	int sock;
	int pid;
	unsigned int option = 1;
	
	struct addrinfo *ainfo=0,*res=0,hints;		
	char buf[256],host[256],serv[256];
	int error;

	memset (&hints, 0, sizeof(hints));
	//hints.ai_protocol = IPPROTO_SCTP;
 	//hints.ai_protocol = IPPROTO_TCP;
 	hints.ai_flags = AI_ADDRCONFIG;
	hints.ai_socktype = SOCK_STREAM;
	
	sprintf(buf,"%d",p->port);

	error = getaddrinfo(p->fqdn.s, buf, &hints, &res);

	if (error!=0){
		LOG(L_WARN,"WARNING:peer_connect(): Error opening connection to %.*s:%d >%s\n",
			p->fqdn.len,p->fqdn.s,p->port,gai_strerror(error));
		goto error;
	}
		
	for(ainfo = res;ainfo;ainfo = ainfo->ai_next)
	{
		if (getnameinfo(ainfo->ai_addr,ainfo->ai_addrlen,
			host,256,serv,256,NI_NUMERICHOST|NI_NUMERICSERV)==0){
				LOG(L_WARN,"INFO:peer_connect(): Trying to connect to %s port %s\n",
					host,serv);
		}				

		if ((sock = socket(ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol)) == -1) {
			LOG(L_ERR,"ERROR:create_socket(): error creating client socket to %s port %s >"
				" %s\n",host,serv,strerror(errno));
			continue;
		}

		if (connect(sock,ainfo->ai_addr,ainfo->ai_addrlen)!=0) {
			LOG(L_WARN,"WARNING:peer_connect(): Error opening connection to to %s port %s >%s\n",
				host,serv,strerror(errno));
			close(sock);		
			continue;
		}
	
		setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&option,sizeof(option));
	
		LOG(L_INFO,"INFO:peer_connect(): Peer %.*s:%d connected\n",p->fqdn.len,p->fqdn.s,p->port);

	
		receiver_init(sock,p);
	
		#ifdef CDP_FOR_SER
			pid = fork_process(p->port,"receiver I",0);
		#else
			pid = fork();
		#endif
		if (pid<0){
			LOG(L_ERR,"ERROR:peer_connect(): fork() failed > %s\n",strerror(errno));
			goto error;
		}
		if (pid==0){
			/* child */
			receiver_process(sock);
			LOG(L_CRIT,"ERROR:peer_connect(): receiver_process finished without exit!\n");
			exit(-1);
		}else{
			/* parent */
			LOG(L_INFO,"INFO:peer_connect(): Receiver process forked [%d]\n",pid);
			
			dp_add_pid(pid);
		}
		
		if (res) freeaddrinfo(res);			
		return sock;
	}
error:
	if (res) freeaddrinfo(res);	
	return -1;	
}
/**
 * Start the CDiameterPeer operations.
 * It forks all the processes required.
 * @param blocking - if this is set, use the calling processes for the timer and never 
 * return; else fork a new one for the timer and return
 * @returns 1 on success, 0 on error, never if blocking
 */ 
int diameter_peer_start(int blocking)
{
	int pid;
	int k=0;


	
	/* Fork the acceptor process */
	#ifdef CDP_FOR_SER		
		pid = fork_process(1000,"cdp_acceptor",1);
	#else
		pid = fork();
	#endif
	
	if (pid==-1){
		LOG(L_CRIT,"ERROR:init_diameter_peer(): Error on fork() for acceptor!\n");
		return 0;
	}
	
	if (pid==0) {
		acceptor_process(config);
		LOG(L_CRIT,"ERROR:init_diameter_peer(): acceptor_process finished without exit!\n");
		exit(-1);		
	}else{
		dp_add_pid(pid);
	}

	/* fork workers */
	for(k=0;k<config->workers;k++){
		#ifdef CDP_FOR_SER		
			pid = fork_process(1001+k,"cdp_worker",1);
		#else
			pid = fork();
		#endif
		if (pid==-1){
			LOG(L_CRIT,"ERROR:init_diameter_peer(): Error on fork() for worker!\n");
			return 0;
		}
		if (pid==0) {
			srandom(time(0)*k);
			#ifdef CDP_FOR_SER
				snprintf(pt[process_no].desc, MAX_PT_DESC,
					"cdp worker child=%d", k );
			#endif	
			worker_process(k);
			LOG(L_CRIT,"ERROR:init_diameter_peer(): worker_process finished without exit!\n");
			exit(-1);		
		}else{
			dp_add_pid(pid);
		}
	}
				
	/* fork/become timer */
	if (blocking) {
		dp_add_pid(getpid());
		timer_process(1);
		
	}		
	else{		
		
		#ifdef CDP_FOR_SER		
			pid = fork_process(1001,"cdp_timer",1);
		#else
			pid = fork();
		#endif
		if (pid==-1){
			LOG(L_CRIT,"ERROR:init_diameter_peer(): Error on fork() for timer!\n");
			return 0;
		}
		if (pid==0) {
			timer_process(0);
			LOG(L_CRIT,"ERROR:init_diameter_peer(): timer_process finished without exit!\n");
			exit(-1);		
		}else{			
			dp_add_pid(pid);
		}
	}
	
	return 1;
}