Exemple #1
0
int32 network_addlistener(bool v6,  const char *addr,  uint16 port)
{
	SESSION *s;
	int optval, fd;

#if !defined(ENABLE_IPV6)
	if(v6 == true) {
		ShowError(read_message("Source.common.network_addlistener"), (v6==true?'t':'f'),  addr, port);
		return -1;
	}
#endif


#ifdef ENABLE_IPV6
	if(v6 == true)
		fd = socket(AF_INET6, SOCK_STREAM, 0);
	else
#endif
		fd = socket(AF_INET, SOCK_STREAM, 0);

	// Error?
	if(fd == -1) {
		ShowError(read_message("Source.common.network_addlistener2"), (v6==true?'t':'f'),  addr, port,    errno, strerror(errno));
		return -1;
	}

	// Too many connections?
	if(fd >= MAXCONN) {
		ShowError(read_message("Source.common.network_addlistener3"), (v6==true?'t':'f'),  addr, port, MAXCONN);
		close(fd);
		return -1;
	}


	s = &g_Session[fd];
	if(s->type != NST_FREE) { // additional checks.. :)
		ShowError(read_message("Source.common.network_addlistener4"), (v6==true?'t':'f'),  addr, port, fd);
		close(fd);
		return -1;
	}


	// Fill ip addr structs
#ifdef ENABLE_IPV6
	if(v6 == true) {
		memset(&s->addr.v6, 0x00, sizeof(s->addr.v6));
		s->addr.v6.sin6_family = AF_INET6;
		s->addr.v6.sin6_port = htons(port);
		if(inet_pton(AF_INET6, addr, &s->addr.v6.sin6_addr) != 1) {
			ShowError(read_message("Source.common.network_addlistener5"), (v6==true?'t':'f'),  addr, port);
			close(fd);
			return -1;
		}

	} else {
#endif
		memset(&s->addr.v4, 0x00, sizeof(s->addr.v4));
		s->addr.v4.sin_family = AF_INET;
		s->addr.v4.sin_port = htons(port);
		s->addr.v4.sin_addr.s_addr = inet_addr(addr);
#ifdef ENABLE_IPV6
	}
#endif


	// if OS has support for SO_REUSEADDR, apply the flag
	// so the address could be used when there're still time_wait sockets outstanding from previous application run.
#ifdef SO_REUSEADDR
	optval=1;
	setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
#endif

	// Bind
#ifdef ENABLE_IPV6
	if(v6 == true) {
		if(bind(fd, (struct sockaddr *)&s->addr.v6,  sizeof(s->addr.v6)) == -1) {
			ShowError(read_message("Source.common.add_listener6"), (v6==true?'t':'f'),  addr, port, errno, strerror(errno));
			close(fd);
			return -1;
		}
	} else {
#endif
		if(bind(fd, (struct sockaddr *)&s->addr.v4,  sizeof(s->addr.v4)) == -1) {
			ShowError(read_message("Source.common.add_listener6"), (v6==true?'t':'f'),  addr, port, errno, strerror(errno));
			close(fd);
			return -1;
		}
#ifdef ENABLE_IPV6
	}
#endif

	if(listen(fd, l_ListenBacklog) == -1) {
		ShowError(read_message("Source.common.add_listener7"), (v6==true?'t':'f'),  addr, port, errno, strerror(errno));
		close(fd);
		return -1;
	}


	// Set to nonblock!
	if(_setnonblock(fd) == false) {
		ShowError(read_message("Source.common.addlistener8"), (v6==true?'t':'f'),  addr, port, errno, strerror(errno));
		close(fd);
		return -1;
	}


	// Rgister @ evdp.
	if(evdp_addlistener(fd, &s->evdp_data) != true) {
		ShowError(read_message("Source.common.addlistener9"), (v6==true?'t':'f'),  addr, port);
		close(fd);
		return -1;
	}


	// Apply flags on Session array for this conneciton.
	if(v6 == true)  s->v6 = true;
	else            s->v6 = false;

	s->type = NST_LISTENER;
	s->onRecv = _network_accept;

	ShowStatus(read_message("Source.common.add_listener10"), addr, port, (v6==true ? "(ipv6)":"(ipv4)"));

	return fd;
}//end: network_addlistener()
Exemple #2
0
int32 network_connect(bool v6,
                        const char *addr,
                        uint16 port,
                        const char *from_addr,
                        uint16 from_port,
                        bool (*onConnectionEstablishedHandler)(int32 fd),
                        void (*onConnectionLooseHandler)(int32 fd)
){
	register SESSION *s;
	int32 fd, optval, ret;
	struct sockaddr_in ip4;
#ifdef ENABLE_IPV6
	struct sockaddr_in6 ip6;
#endif

#ifdef ENABLE_IPV6
	if(v6 == true)
		fd = socket(AF_INET6, SOCK_STREAM, 0);
	else
#endif
		fd = socket(AF_INET, SOCK_STREAM, 0);

#ifndef ENABLE_IPV6
	// check..
	if(v6 == true){
		ShowError("network_connect(%c, '%s', %u...): tried to create an ipv6 connection, IPV6 is not supported in this release.\n", (v6==true?'t':'f'),  addr, port);
		return -1;
	}
#endif

	// check connection limits.
	if(fd >= MAXCONN){
		ShowError("network_connect(%c, '%s', %u...): cannot create new connection, exceeeds more than supported connections (%u)\n", (v6==true?'t':'f'),  addr, port );
		close(fd);
		return -1;
	}

	
	// Originating IP/Port pair given ?
	if(from_addr != NULL && *from_addr != 0){
		//.. 
		#ifdef SO_REUSEADDR
	    optval=1;
	    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
		#endif
		
		#ifdef ENABLE_IPV6
		if(v6 == true){
			memset(&ip6, 0x00, sizeof(ip6));
			ip6.sin6_family = AF_INET6;
			ip6.sin6_port = htons(from_port);
			
			if(inet_pton(AF_INET6, from_addr, &ip6.sin6_addr) != 1){
				ShowError("network_connect(%c, '%s', %u...): cannot parse originating (from) IPV6 address (errno: %u / %s)\n", (v6==true?'t':'f'),  addr, port, errno, strerror(errno));
				close(fd);
				return -1;
 			}
		
 			ret = bind(fd, (struct sockaddr*)&ip6, sizeof(ip6));
		}else{
		#endif
			memset(&ip4, 0x00, sizeof(ip4));
			
			ip4.sin_family = AF_INET;
			ip4.sin_port = htons(from_port);
			ip4.sin_addr.s_addr = inet_addr(from_addr);
			ret = bind(fd, (struct sockaddr*)&ip4, sizeof(ip4));
		#ifdef ENABLE_IPV6
		}
		#endif
		
	}
	

	// Set non block
	if(_setnonblock(fd) == false){
		ShowError("network_connect(%c, '%s', %u...): cannot set socket to nonblocking (errno: %u / %s)\n", (v6==true?'t':'f'),  addr, port, errno, strerror(errno));
		close(fd);
		return -1;
	}


	// Create ip addr block to connect to .. 
#ifdef ENABLE_IPV6
	if(v6 == true){
		memset(&ip6, 0x00, sizeof(ip6));
		ip6.sin6_family = AF_INET6;
		ip6.sin6_port = htons(port);
		
		if(inet_pton(AF_INET6, addr, &ip6.sin6_addr) != 1){
			 ShowError("network_connect(%c, '%s', %u...): cannot parse destination IPV6 address (errno: %u / %s)\n", (v6==true?'t':'f'),  addr, port, errno, strerror(errno));
			 close(fd);
			 return -1;
		}
	
	}else{
#endif
	memset(&ip4, 0x00, sizeof(ip4));
	
	ip4.sin_family = AF_INET;
	ip4.sin_port = htons(port);
	ip4.sin_addr.s_addr = inet_addr(addr);	
#ifdef ENABLE_IPV6
	}
#endif


	// Assign Session..
	s = &g_Session[fd];
	s->type = NST_OUTGOING;
	s->v6 = v6;
	s->onConnect = onConnectionEstablishedHandler;
	s->onDisconnect = onConnectionLooseHandler;
	s->onRecv = NULL;
	s->onSend = _network_connect_establishedHandler;
#ifdef ENABLE_IPV6
	if(v6 == true)
		memcpy(&s->addr.v6, &ip6, sizeof(ip6));
	else
#endif
		memcpy(&s->addr.v4, &ip4, sizeof(ip4));
	
	// Register @ EVDP. as outgoing (see doc of the function)
	if(evdp_addconnecting(fd, &s->evdp_data) == false){
		ShowError("network_connect(%c, '%s', %u...): eventdispatcher subsystem returned an error.\n", (v6==true?'t':'f'),  addr, port);
		
		// cleanup session x.x.. 
		s->type = NST_FREE;
		s->onConnect = NULL;
		s->onDisconnect = NULL;
		s->onSend = NULL;
		
		// close, return error code.
		close(fd);
		return -1;
	}


#ifdef ENABLE_IPV6
	if(v6 == true)
		ret = connect(fd, (struct sockaddr*)&ip6, sizeof(ip6));
	else
#endif
		ret = connect(fd, (struct sockaddr*)&ip4, sizeof(ip4));


	// 
	if(ret != 0 && errno != EINPROGRESS){
		ShowWarning("network_connect(%c, '%s', %u...): connection failed (errno: %u / %s)\n", (v6==true?'t':'f'),  addr, port, errno, strerror(errno));
		
		// Cleanup session ..
		s->type = NST_FREE;
		s->onConnect = NULL;
		s->onDisconnect = NULL;
		s->onSend = NULL;
		
		// .. remove from evdp and close fd.	
		evdp_remove(fd, &s->evdp_data);
		close(fd);
		return -1;
	}


	// ! The Info Message :~D
	ShowStatus("network_connect fd#%u (%s:%u) in progress.. \n", fd, addr, port);

return fd;	
}//end: network_connect()
Exemple #3
0
static bool _network_accept(int32 fd)
{
	SESSION *listener = &g_Session[fd];
	SESSION *s;
	union {
		struct sockaddr_in v4;
#ifdef ENABLE_IPV6
		struct sockaddr_in6 v6;
#endif
	} _addr;
	int newfd;
	socklen_t addrlen;
	struct sockaddr *addr;

	// Accept until OS returns - nothing to accept anymore
	// - this is required due to our EVDP abstraction. (which handles on listening sockets similar to epoll's EPOLLET flag.)
	while(1) {
#ifdef ENABLE_IPV6
		if(listener->v6 == true) {
			addrlen = sizeof(_addr.v6);
			addr = (struct sockaddr *)&_addr.v6;
		} else {
#endif
			addrlen = sizeof(_addr.v4);
			addr = (struct sockaddr *)&_addr.v4;
#ifdef ENABLE_IPV6
		}
#endif

#ifdef HAVE_ACCEPT4
		newfd = accept4(fd, addr, &addrlen, SOCK_NONBLOCK);
#else
		newfd = accept(fd, addr, &addrlen);
#endif

		if(newfd == -1) {
			if(errno == EAGAIN || errno == EWOULDBLOCK)
				break; // this is fully valid & whished., se explaination on top of while(1)

			// Otherwis .. we have serious problems :( seems tahat our listner has gone away..
			// @TODO handle this ..
			ShowError(read_message("Source.common.network_accept"), errno, strerror(errno));

			return false; // will call disconnect after return.
			//break;
		}

#ifndef HAVE_ACCEPT4 // no accept4 means, we have to set nonblock by ourself. ..
		if(_setnonblock(newfd) == false) {
			ShowError(read_message("Source.common.network_accept2"), errno, strerror(errno));
			close(newfd);
			continue;
		}
#endif

		// Check connection limits.
		if(newfd >= MAXCONN) {
			ShowError(read_message("network_accept3"), MAXCONN);
			close(newfd);
			continue; // we have to loop over the events (and disconnect them too ..) but otherwise we would leak event notifications.
		}


		// Create new Session.
		s = &g_Session[newfd];
		s->type = NST_CLIENT;

		// The new connection inherits listenr's handlers.
		s->onDisconnect = listener->onDisconnect;
		s->onConnect = listener->onConnect; // maybe useless but .. fear the future .. :~

		// Register the new connection @ EVDP
		if(evdp_addclient(newfd, &s->evdp_data) == false) {
			ShowError(read_message("Source.common.network_accept3"));
			close(newfd);
			s->type = NST_FREE;
		}

		// Call the onConnect handler on the listener.
		if(listener->onConnect(newfd) == false) {
			// Resfused by onConnect handler..
			evdp_remove(newfd, &s->evdp_data);

			close(newfd);
			s->type = NST_FREE;

			s->data = NULL; // be on the safe side ~ !
			continue;
		}


	}

	return true;
}//end: _network_accept()
Exemple #4
0
int32 network_addlistener(bool v6,  const char *addr,  uint16 port){
	SESSION *s;
	int optval, fd;

#if !defined(ENABLE_IPV6)
	if(v6 == true){
		 ShowError("network_addlistener(%c, '%s', %u):  this release has no IPV6 support.\n",  (v6==true?'t':'f'),  addr, port);
		 return -1;
	}
#endif


#ifdef ENABLE_IPV6
	if(v6 == true)
		fd = socket(AF_INET6, SOCK_STREAM, 0);
	else
#endif
		fd = socket(AF_INET, SOCK_STREAM, 0);

	// Error?
	if(fd == -1){
		ShowError("network_addlistener(%c, '%s', %u):  socket() failed (errno: %u / %s)\n",  (v6==true?'t':'f'),  addr, port,    errno, strerror(errno));
		return -1;
	}
	
	// Too many connections?
	if(fd >= MAXCONN){
		ShowError("network_addlistener(%c, '%s', %u):  cannot create listener, exceeds more than supported connections (%u).\n", (v6==true?'t':'f'),  addr, port, MAXCONN);
		close(fd);
		return -1;
	}
	
	
	s = &g_Session[fd];
	if(s->type != NST_FREE){ // additional checks.. :)
			ShowError("network_addlistener(%c, '%s', %u): failed, got fd #%u which is already in use in local session table?!\n", (v6==true?'t':'f'),  addr, port, fd);
			close(fd);
			return -1;
	}
	
	
	// Fill ip addr structs
#ifdef ENABLE_IPV6
	if(v6 == true){
		memset(&s->addr.v6, 0x00, sizeof(s->addr.v6));
		s->addr.v6.sin6_family = AF_INET6;
		s->addr.v6.sin6_port = htons(port);
		if(inet_pton(AF_INET6, addr, &s->addr.v6.sin6_addr) != 1){
			ShowError("network_addlistener(%c, '%s', %u): failed to parse the given IPV6 address.\n",  (v6==true?'t':'f'),  addr, port);
			close(fd);
			return -1;
		}
		
	}else{
#endif
		memset(&s->addr.v4, 0x00, sizeof(s->addr.v4));
		s->addr.v4.sin_family = AF_INET;
		s->addr.v4.sin_port = htons(port);
		s->addr.v4.sin_addr.s_addr = inet_addr(addr);
#ifdef ENABLE_IPV6
	}
#endif
		 

	// if OS has support for SO_REUSEADDR, apply the flag
	// so the address could be used when there're still time_wait sockets outstanding from previous application run.
#ifdef SO_REUSEADDR
	optval=1;
	setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
#endif

	// Bind
#ifdef ENABLE_IPV6
	if(v6 == true){
		if( bind(fd, (struct sockaddr*)&s->addr.v6,  sizeof(s->addr.v6)) == -1) {
			ShowError("network_addlistener(%c, '%s', %u): bind failed (errno: %u / %s)\n",  (v6==true?'t':'f'),  addr, port, errno, strerror(errno));
			close(fd);
			return -1;
		}
	}else{
#endif
		if( bind(fd, (struct sockaddr*)&s->addr.v4,  sizeof(s->addr.v4)) == -1) {
            ShowError("network_addlistener(%c, '%s', %u): bind failed (errno: %u / %s)\n",  (v6==true?'t':'f'),  addr, port, errno, strerror(errno));
			close(fd);
			return -1;
		}		
#ifdef ENABLE_IPV6
	}
#endif

	if( listen(fd, l_ListenBacklog) == -1){
		ShowError("network_addlistener(%c, '%s', %u): listen failed (errno: %u / %s)\n",  (v6==true?'t':'f'),  addr, port, errno, strerror(errno));
		close(fd);
		return -1;
	}
		

	// Set to nonblock!
	if(_setnonblock(fd) == false){
		ShowError("network_addlistener(%c, '%s', %u): cannot set to nonblock (errno: %u / %s)\n",  (v6==true?'t':'f'),  addr, port, errno, strerror(errno));
		close(fd);
		return -1;
	}	


	// Rgister @ evdp.
	if( evdp_addlistener(fd, &s->evdp_data) != true){
		ShowError("network_addlistener(%c, '%s', %u): eventdispatcher subsystem returned an error.\n",  (v6==true?'t':'f'),  addr, port);
		close(fd);
		return -1;
	}
	
	
	// Apply flags on Session array for this conneciton.
	if(v6 == true)	s->v6 = true;
	else			s->v6 = false;
	
	s->type = NST_LISTENER;
	s->onRecv = _network_accept;

	ShowStatus("Added Listener on '%s':%u\n", addr, port, (v6==true ? "(ipv6)":"(ipv4)") );

	return fd;
}//end: network_addlistener()