Ejemplo n.º 1
0
int network_write_data(network_socket * s, void* data, int len, struct sockaddr * write_addr)
{
	char * odata = (char*)data;
	int rv;

	// are we a tcp or a udp socket?
	// tcp we can use a nonblocking write.
	// udp we have to send() and block. unfortunately. :(
	//     however, it shouldn't be a long block as the data is just copied into the os's internal buffer for the 
	//     fd.

	if( write_addr == NULL )			// tcp.
	{
		// this will push out as much data as possible
		rv = send( s->fd, odata, len, 0 );

		if( rv >= 0 || errno == EAGAIN )
		{
			// save any additional data in our buffer.
			int copylen = len - rv;

			if( copylen > 0 )
			{
				if( s->outlen + copylen > s->outbuffer_size )
				{
					// buffer overflow, lets treat the socket liek it was dead
					return -1;
				}

				// copy into the obuf
				memcpy(&s->outbuffer[s->outlen], &odata[rv], copylen);
				s->outlen += copylen;
			}

			// avoid the if trigger if 0 bytes were written (this is ok with nonblocking)
			rv = 1;
			
			// switch the socket to writing mode
			network_mod(s->fd, EVFILT_WRITE, 1);
		}
	}
	else								// udp
	{
		rv = sendto(s->fd, odata, len, 0, write_addr, sizeof(struct sockaddr));
	}

	// error. :(
	if( rv <= 0 )
	{
		log_write(DEBUG, "send() returned %d on socket %u (%s).", rv, s->fd, write_addr ? "UDP" : "TCP");
		return -1;
	}

	g_bytesSent += rv;
	g_bytesSentTotal += rv;	

	// everything went ok
	return rv;
}
Ejemplo n.º 2
0
int network_io_poll()
{
	int nevents;
	struct kevent events[MAXEVENTS];
	struct timespec timeout;
	int fd;
	int evs;
	int n;
	network_socket * s;
	timeout.tv_sec = 1;
	timeout.tv_nsec = 0;

	// check size
	if( g_maxFd == 0 )
	{
		// just sleep, to simulate the delay
		usleep(SLEEPSEC * 1000000);
		return 0;
	}

	nevents = kevent(g_kqueue, 0, 0, events, MAXEVENTS, &timeout);

	if( nevents < 0 )
	{
		// some error occured.
		log_write(ERROR, "FATAL: kevent() returned %d", nevents);
		return -1;
	}

	// no events
	if( nevents == 0 )
		return 0;

	// loop each each socket and handle events on each of them
	for( n = 0; n < nevents; ++n )
	{
		fd = events[n].ident;
		evs = events[n].filter;
		s = g_fds[fd];
		if( s != NULL )
		{
			if( events[n].flags & EV_EOF || events[n].flags & EV_ERROR )
			{
				if( s->event_handler(s, IOEVENT_ERROR) != 0 )
				{
					network_close(s);
					continue;
				}
			}
			else
			{
				if( evs & EVFILT_READ )
				{
					if( s->event_handler(s, IOEVENT_READ) != 0 )
					{
						network_close(s);
						continue;
					}
				}
				
				if( evs & EVFILT_WRITE )
				{
					if( s->write_handler(s, IOEVENT_WRITE) != 0 )
					{
						network_close(s);
						continue;
					}
					else
					{
						// any data left?
						if( s->outlen == 0 )
						{
							// all data written, switch back to read mode
							network_mod(s->fd, EVFILT_READ, 0);
						}
						else
						{
							// still data left, reset write event
							network_mod(s->fd, EVFILT_WRITE, 1);
						}

						// don't have to do anything
					}
				}
			}
		}
	}
	
	// no errors
	return 0;
}
Ejemplo n.º 3
0
int network_io_poll()
{
	int nevents;
	struct epoll_event events[MAXEVENTS];
	int fd;
	int evs;
	int n;
	network_socket * s;

	// check size
	if( g_maxFd == 0 )
	{
		// just sleep, to simulate the delay
		usleep(SLEEPSEC * 1000000);
		return 0;
	}

	// use our blocking epoll()
	nevents = epoll_wait(g_epoll, events, MAXEVENTS, 1000);

	if( nevents < 0 )
	{
		// some error occured.
		log_write(ERROR, "FATAL: epoll_wait() returned %d", nevents);
		return -1;
	}

	// no events
	if( nevents == 0 )
		return 0;

	// loop each each socket and handle events on each of them
	for( n = 0; n < nevents; ++n )
	{
		fd = events[n].data.fd;
		evs = events[n].events;
		s = g_fds[fd];
		if( s != NULL )
		{
			if( evs & EPOLLHUP || evs & EPOLLERR )
			{
				if( s->event_handler(s, IOEVENT_ERROR) != 0 )
				{
					network_close(s);
					continue;
				}
			}
			else
			{
				if( evs & EPOLLIN )
				{
					if( s->event_handler(s, IOEVENT_READ) != 0 )
					{
						network_close(s);
						continue;
					}
				}
				
				if( evs & EPOLLOUT )
				{
					if( s->write_handler(s, IOEVENT_WRITE) != 0 )
					{
						network_close(s);
						continue;
					}
					else
					{
						// any data left?
						if( s->outlen == 0 )
						{
							// all data written, switch back to read mode
							network_mod(s->fd, EPOLLIN);
						}

						// don't have to do anything
					}
				}
			}
		}
	}
	
	// no errors
	return 0;
}