Пример #1
0
/** call timeouts handlers, and return how long to wait for next one or -1 */
static void handle_timeouts(struct event_base* base, struct timeval* now, 
	struct timeval* wait)
{
	struct event* p;
#ifndef S_SPLINT_S
	wait->tv_sec = (time_t)-1;
#endif

	while((rbnode_t*)(p = (struct event*)rbtree_first(base->times))
		!=RBTREE_NULL) {
#ifndef S_SPLINT_S
		if(p->ev_timeout.tv_sec > now->tv_sec ||
			(p->ev_timeout.tv_sec==now->tv_sec && 
		 	p->ev_timeout.tv_usec > now->tv_usec)) {
			/* there is a next larger timeout. wait for it */
			wait->tv_sec = p->ev_timeout.tv_sec - now->tv_sec;
			if(now->tv_usec > p->ev_timeout.tv_usec) {
				wait->tv_sec--;
				wait->tv_usec = 1000000 - (now->tv_usec -
					p->ev_timeout.tv_usec);
			} else {
				wait->tv_usec = p->ev_timeout.tv_usec 
					- now->tv_usec;
			}
			return;
		}
#endif
		/* event times out, remove it */
		(void)rbtree_delete(base->times, p);
		p->ev_events &= ~EV_TIMEOUT;
		fptr_ok(fptr_whitelist_event(p->ev_callback));
		(*p->ev_callback)(p->ev_fd, EV_TIMEOUT, p->ev_arg);
	}
}
Пример #2
0
/** handle is_signal events and see if signalled */
static void _getdns_handle_signal(struct _getdns_event* ev)
{
	DWORD ret;
	//log_assert(ev->is_signal && ev->hEvent);
	/* see if the event is signalled */
	ret = WSAWaitForMultipleEvents(1, &ev->hEvent, 0 /* any object */,
		0 /* return immediately */, 0 /* not alertable for IOcomple*/);
	if(ret == WSA_WAIT_IO_COMPLETION || ret == WSA_WAIT_FAILED) {
		log_err("getdns: WSAWaitForMultipleEvents(signal) failed: %s",
			wsa_strerror(WSAGetLastError()));
		return;
	}
	if(ret == WSA_WAIT_TIMEOUT) {
		/* not signalled */
		return;
	}

	/* reset the signal */
	if(!WSAResetEvent(ev->hEvent))
		log_err("getdns: WSAResetEvent failed: %s",
			wsa_strerror(WSAGetLastError()));
	/* do the callback (which may set the signal again) */
	fptr_ok(fptr_whitelist_event(ev->ev_callback));
	(*ev->ev_callback)(ev->ev_fd, ev->ev_events, ev->ev_arg);
}
Пример #3
0
/** signal handler */
static RETSIGTYPE sigh(int sig)
{
	struct event* ev;
	if(!signal_base || sig < 0 || sig >= MAX_SIG)
		return;
	ev = signal_base->signals[sig];
	if(!ev)
		return;
	fptr_ok(fptr_whitelist_event(ev->ev_callback));
	(*ev->ev_callback)(sig, EV_SIGNAL, ev->ev_arg);
}
Пример #4
0
/** set content of event */
void event_set(struct event* ev, int fd, short bits, 
	void (*cb)(int, short, void *), void* arg)
{
	ev->node.key = ev;
	ev->ev_fd = fd;
	ev->ev_events = bits;
	ev->ev_callback = cb;
	fptr_ok(fptr_whitelist_event(ev->ev_callback));
	ev->ev_arg = arg;
	ev->added = 0;
}
Пример #5
0
/** call select and callbacks for that */
static int handle_select(struct event_base* base, struct timeval* wait)
{
	fd_set r, w;
	int ret, i;

#ifndef S_SPLINT_S
	if(wait->tv_sec==(time_t)-1)
		wait = NULL;
#endif
	memmove(&r, &base->reads, sizeof(fd_set));
	memmove(&w, &base->writes, sizeof(fd_set));
	memmove(&base->ready, &base->content, sizeof(fd_set));

	if((ret = select(base->maxfd+1, &r, &w, NULL, wait)) == -1) {
		ret = errno;
		if(settime(base) < 0)
			return -1;
		errno = ret;
		if(ret == EAGAIN || ret == EINTR)
			return 0;
		return -1;
	}
	if(settime(base) < 0)
		return -1;
	
	for(i=0; i<base->maxfd+1; i++) {
		short bits = 0;
		if(!base->fds[i] || !(FD_ISSET(i, &base->ready))) {
			continue;
		}
		if(FD_ISSET(i, &r)) {
			bits |= EV_READ;
			ret--;
		}
		if(FD_ISSET(i, &w)) {
			bits |= EV_WRITE;
			ret--;
		}
		bits &= base->fds[i]->ev_events;
		if(bits) {
			fptr_ok(fptr_whitelist_event(
				base->fds[i]->ev_callback));
			(*base->fds[i]->ev_callback)(base->fds[i]->ev_fd, 
				bits, base->fds[i]->ev_arg);
			if(ret==0)
				break;
		}
	}
	return 0;
}
Пример #6
0
/** call timeouts handlers, and return how long to wait for next one or -1 */
void _getdns_handle_timeouts(struct _getdns_event_base* base, struct timeval* now,
        struct timeval* wait)
{
        struct _getdns_event* p;
#ifndef S_SPLINT_S
        wait->tv_sec = (time_t)-1;
#endif
	//verbose(VERB_CLIENT, "winsock_event handle_timeouts");

        while((_getdns_rbnode_t*)(p = (struct _getdns_event*)_getdns_rbtree_first(base->times))
                !=RBTREE_NULL) {
#ifndef S_SPLINT_S
                if(p->ev_timeout.tv_sec > now->tv_sec ||
                        (p->ev_timeout.tv_sec==now->tv_sec &&
                        p->ev_timeout.tv_usec > now->tv_usec)) {
                        /* there is a next larger timeout. wait for it */
                        wait->tv_sec = p->ev_timeout.tv_sec - now->tv_sec;
                        if(now->tv_usec > p->ev_timeout.tv_usec) {
                                wait->tv_sec--;
                                wait->tv_usec = 1000000 - (now->tv_usec -
                                        p->ev_timeout.tv_usec);
                        } else {
                                wait->tv_usec = p->ev_timeout.tv_usec
                                        - now->tv_usec;
                        }
			//verbose(VERB_CLIENT, "winsock_event wait=" ARG_LL "d.%6.6d",
			//	(long long)wait->tv_sec, (int)wait->tv_usec);
                        return;
                }
#endif
                /* event times out, remove it */
                (void)_getdns_rbtree_delete(base->times, p);
                p->ev_events &= ~EV_TIMEOUT;
                fptr_ok(fptr_whitelist_event(p->ev_callback));
                (*p->ev_callback)(p->ev_fd, EV_TIMEOUT, p->ev_arg);
        }
	//verbose(VERB_CLIENT, "winsock_event wait=(-1)");
}
Пример #7
0
int _getdns_handle_select(struct _getdns_event_base* base, struct timeval* wait)
{
	DWORD timeout = 0; /* in milliseconds */	
	DWORD ret;
	WSANETWORKEVENTS netev;
	struct _getdns_event* eventlist[WSK_MAX_ITEMS];
	int i, numwait = 0, startidx = 0, was_timeout = 0;
	int newstickies = 0;
	struct timeval nultm;

	printf("in handle select\n");

#ifndef S_SPLINT_S
        if(wait->tv_sec==(time_t)-1)
                wait = NULL;
		if (wait)
		//	timeout = 10 + wait->tv_usec / 1000;
		 timeout = wait->tv_sec * 1000 + wait->tv_usec / 1000;
 	if(base->tcp_stickies) {
		wait = &nultm;
		nultm.tv_sec = 0;
		nultm.tv_usec = 0;
		timeout = 0; /* no waiting, we have sticky events */
	}
#endif

	/* prepare event array */
	for(i=0; i<base->max; i++) {
		if(base->items[i]->ev_fd == -1 && !base->items[i]->is_signal)
			continue; /* skip timer only events */
		eventlist[numwait] = base->items[i];
		base->waitfor[numwait++] = base->items[i]->hEvent;
		printf("winsock_event bmax=%d numwait=%d wait=%x "
			"timeout=%d hEvent %d\n", base->max, numwait, (int)wait, (int)timeout, base->items[i]->hEvent);
		if (numwait == WSK_MAX_ITEMS)
			break; /* sanity check */
	}
	//log_assert(numwait <= WSA_MAXIMUM_WAIT_EVENTS);

	/* do the wait */
	if(numwait == 0) {
		/* WSAWaitFor.. doesn't like 0 event objects */
		if(wait) {
			Sleep(timeout);
		}
		was_timeout = 1;
	}
	else {
		//g do not sched udp write
		for (i = 0; i<base->max; i++) {
			if (!base->items[i]->is_tcp && base->items[i]->ev_events&EV_WRITE) {
				//gprintf("skip UDP sched\n");
				(*eventlist[i]->ev_callback)(eventlist[i]->ev_fd,
					EV_WRITE & eventlist[i]->ev_events,
					eventlist[i]->ev_arg);
				return 0;
			}
	    } 
		//gprintf("before wait %d\n", base->items[0]->ev_events);
		ret = WSAWaitForMultipleEvents(numwait, base->waitfor,
			0 /* do not wait for all, just one will do */,
			wait?timeout:WSA_INFINITE,
			0); /* we are not alertable (IO completion events) */
		//gprintf("after wait %d %d\n", ret, numwait);
		if(ret == WSA_WAIT_IO_COMPLETION) {
			//printf("getdns: WSAWaitForMultipleEvents failed: WSA_WAIT_IO_COMPLETION");
			return -1;
		} else if(ret == WSA_WAIT_FAILED) {
			//printf("getdns: WSAWaitForMultipleEvents failed: %s", 
			//	wsa_strerror(WSAGetLastError()));
			return -1;
		} else if(ret == WSA_WAIT_TIMEOUT) {
			//printf("timeout\n");
			was_timeout = 1;
		} else
			startidx = ret - WSA_WAIT_EVENT_0;
	}
	////verbose(VERB_CLIENT, "winsock_event wake was_timeout=%d startidx=%d", 
	//	was_timeout, startidx);

	/* get new time after wait */
        if(settime(base) < 0)
               return -1;

	/* callbacks */
	if(base->tcp_stickies)
		startidx = 0; /* process all events, some are sticky */
	for(i=startidx; i<numwait; i++)
		eventlist[i]->just_checked = 1;

	//verbose(VERB_CLIENT, "winsock_event signals");
	for(i=startidx; i<numwait; i++) {
		if(!base->waitfor[i])
			continue; /* was deleted */
		if(eventlist[i]->is_signal) {
			eventlist[i]->just_checked = 0;
			_getdns_handle_signal(eventlist[i]);
		}
	}
	/* early exit - do not process network, exit quickly */
	if(base->need_to_exit)
		return 0;

	//verbose(VERB_CLIENT, "winsock_event net");
	for(i=startidx; i<numwait; i++) {
		short bits = 0;
		/* eventlist[i] fired */
		/* see if eventlist[i] is still valid and just checked from
		 * WSAWaitForEvents */
		if(!base->waitfor[i])
			continue; /* was deleted */
		if(!eventlist[i]->just_checked)
			continue; /* added by other callback */
		if(eventlist[i]->is_signal)
			continue; /* not a network event at all */
		eventlist[i]->just_checked = 0;

		if(WSAEnumNetworkEvents(eventlist[i]->ev_fd, 
			base->waitfor[i], /* reset the event handle */
			/*NULL,*/ /* do not reset the event handle */
			&netev) != 0) {
			log_err("getdns: WSAEnumNetworkEvents failed: %s", 
				wsa_strerror(WSAGetLastError()));
			return -1;
		}
		if((netev.lNetworkEvents & FD_READ)) {
			if(netev.iErrorCode[FD_READ_BIT] != 0)
				printf("FD_READ_BIT error: %s\n",
				wsa_strerror(netev.iErrorCode[FD_READ_BIT]));
			bits |= EV_READ;
			printf("FD_READ_BIT\n");
		}
		if((netev.lNetworkEvents & FD_WRITE)) {
			if(netev.iErrorCode[FD_WRITE_BIT] != 0)
				printf("FD_WRITE_BIT error: %s\n",
				wsa_strerror(netev.iErrorCode[FD_WRITE_BIT]));
			bits |= EV_WRITE;
			printf("FD_WRITE_BIT\n");
		}
		if((netev.lNetworkEvents & FD_CONNECT)) {
			if(netev.iErrorCode[FD_CONNECT_BIT] != 0)
				printf("FD_CONNECT_BIT error: %s\n",
				wsa_strerror(netev.iErrorCode[FD_CONNECT_BIT]));
			bits |= EV_READ;
			bits |= EV_WRITE;
			printf("FD_CONNECT_BIT\n");
		}
		if((netev.lNetworkEvents & FD_ACCEPT)) {
			if(netev.iErrorCode[FD_ACCEPT_BIT] != 0)
				printf("FD_ACCEPT_BIT error: %s\n",
				wsa_strerror(netev.iErrorCode[FD_ACCEPT_BIT]));
			bits |= EV_READ;
			printf("FD_ACCEPT_BIT\n");
		}
		if((netev.lNetworkEvents & FD_CLOSE)) {
			if(netev.iErrorCode[FD_CLOSE_BIT] != 0)
				printf("FD_CLOSE_BIT error: %s\n",
				wsa_strerror(netev.iErrorCode[FD_CLOSE_BIT]));
			bits |= EV_READ;
			bits |= EV_WRITE;
			printf("FD_CLOSE_BIT\n");
		}
		if(eventlist[i]->is_tcp && eventlist[i]->stick_events) {
			/*
			printf("winsock %d pass sticky %s%s\n",
				eventlist[i]->ev_fd,
   			    (eventlist[i]->old_events&EV_READ)?"EV_READ":"",
				(eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":"");
			*/
			bits |= eventlist[i]->old_events;
		}
		if(eventlist[i]->is_tcp && bits) {
			eventlist[i]->old_events = bits;
			eventlist[i]->stick_events = 1;
			if((eventlist[i]->ev_events & bits)) {
				newstickies = 1;
			}
			/*
		printf("winsock %d store sticky %s%s",
				eventlist[i]->ev_fd,
				(eventlist[i]->old_events&EV_READ)?"EV_READ":"",
				(eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":"");
			*/	
		}
		if((bits & eventlist[i]->ev_events)) {
		/*     printf( "winsock event callback %p fd=%d "
			    "%s%s%s%s%s ; %s%s%s\n", 
				eventlist[i], eventlist[i]->ev_fd,
				(netev.lNetworkEvents&FD_READ)?" FD_READ":"",
				(netev.lNetworkEvents&FD_WRITE)?" FD_WRITE":"",
				(netev.lNetworkEvents&FD_CONNECT)?
					" FD_CONNECT":"",
			    (netev.lNetworkEvents&FD_ACCEPT)?
					" FD_ACCEPT":"",
				(netev.lNetworkEvents&FD_CLOSE)?" FD_CLOSE":"",
			    (bits&EV_READ)?" EV_READ":"",
			    (bits&EV_WRITE)?" EV_WRITE":"",
				(bits&EV_TIMEOUT)?" EV_TIMEOUT":"");
				*/
				fptr_ok(fptr_whitelist_event(
					eventlist[i]->ev_callback));
				(*eventlist[i]->ev_callback)(eventlist[i]->ev_fd,
					bits & eventlist[i]->ev_events,
					eventlist[i]->ev_arg);
		}
		/*
	   if(eventlist[i]->is_tcp && bits)
			printf( "winsock %d got sticky %s%s\n",
				eventlist[i]->ev_fd,
				(eventlist[i]->old_events&EV_READ)?"EV_READ":"",
				(eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":"");
	   */
	}
	//verbose(VERB_CLIENT, "winsock_event net");
	if(base->tcp_reinvigorated) {
		printf("winsock_event reinvigorated\n");
		base->tcp_reinvigorated = 0;
		newstickies = 1;
	}
	base->tcp_stickies = newstickies;
	//gprintf("winsock_event handle_select end\n");
        return 0;
}
Пример #8
0
/** call select and callbacks for that */
int _getdns_handle_select(struct _getdns_event_base* base, struct timeval* wait)
{
	fd_set r, w;
	int ret, i, timeout = 0, numwait = 0;
	struct _getdns_event* eventlist[WSK_MAX_ITEMS];

#ifndef S_SPLINT_S
	if (wait->tv_sec == (time_t)-1)
		wait = NULL;
#endif
	memmove(&r, &base->reads, sizeof(fd_set));
	memmove(&w, &base->writes, sizeof(fd_set));
	memmove(&base->ready, &base->content, sizeof(fd_set));
	/*
	if ((ret = select(base->max + 1, &r, &w, NULL, wait)) == -1) {
		ret = errno;
		if (settime(base) < 0)
			return -1;
		errno = ret;
		if (ret == EAGAIN || ret == EINTR)
			return 0;
		return -1;
	}
	*/

	/* prepare event array */
	for (i = 0; i<base->max; i++) {
		if (base->items[i]->ev_fd == -1 && !base->items[i]->is_signal)
			continue; /* skip timer only events */
		eventlist[numwait] = base->items[i];
		base->waitfor[numwait++] = base->items[i]->hEvent;
		if (numwait == WSK_MAX_ITEMS)
			break; /* sanity check */
	}

	ret = WSAWaitForMultipleEvents(base->max, base->waitfor,
		0 /* do not wait for all, just one will do */,
		wait ? timeout : WSA_INFINITE,
		0); /* we are not alertable (IO completion events) */
	if (ret == WSA_WAIT_IO_COMPLETION) {
		log_err("getdns: WSAWaitForMultipleEvents failed: WSA_WAIT_IO_COMPLETION");
		return -1;
	}
	else if (ret == WSA_WAIT_FAILED) {
		log_err("getdns: WSAWaitForMultipleEvents failed: %s",
			wsa_strerror(WSAGetLastError()));
		return -1;
	}
	else if (ret == WSA_WAIT_TIMEOUT) {
		was_timeout = 1;
	}
	else
		startidx = ret - WSA_WAIT_EVENT_0;


	if (settime(base) < 0)
		return -1;

	for (i = 0; i<base->max + 1; i++) {
		short bits = 0;
		if (!base->items[i] || !(FD_ISSET(i, &base->ready))) {
			continue;
		}
		if (FD_ISSET(i, &r)) {
			bits |= EV_READ;
			ret--;
		}
		if (FD_ISSET(i, &w)) {
			bits |= EV_WRITE;
			ret--;
		}
		bits &= base->items[i]->ev_events;
		if (bits) {
			fptr_ok(fptr_whitelist_event(
				base->items[i]->ev_callback));
			(*base->items[i]->ev_callback)(base->items[i]->ev_fd,
				bits, base->items[i]->ev_arg);
			if (ret == 0)
				break;
		}
	}
	return 0;
}