⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 event.c

📁 linux下的pppoe拨号程序源代码; 不错的开源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/************************************************************************* event.c** Abstraction of select call into "event-handling" to make programming* easier.** Copyright (C) 2001 Roaring Penguin Software Inc.** This program may be distributed according to the terms of the GNU* General Public License, version 2 or (at your option) any later version.** LIC: GPL************************************************************************/static char const RCSID[] ="$Id: event.c,v 1.2 2002/04/09 17:28:40 dfs Exp $";#include "event.h"#include <stdlib.h>#include <errno.h>static void DestroySelector(EventSelector *es);static void DestroyHandler(EventHandler *eh);static void DoPendingChanges(EventSelector *es);/*********************************************************************** %FUNCTION: Event_CreateSelector* %ARGUMENTS:*  None* %RETURNS:*  A newly-allocated EventSelector, or NULL if out of memory.* %DESCRIPTION:*  Creates a new EventSelector.***********************************************************************/EventSelector *Event_CreateSelector(void){    EventSelector *es = malloc(sizeof(EventSelector));    if (!es) return NULL;    es->handlers = NULL;    es->nestLevel = 0;    es->destroyPending = 0;    es->opsPending = 0;    EVENT_DEBUG(("CreateSelector() -> %p\n", (void *) es));    return es;}/*********************************************************************** %FUNCTION: Event_DestroySelector* %ARGUMENTS:*  es -- EventSelector to destroy* %RETURNS:*  Nothing* %DESCRIPTION:*  Destroys an EventSelector.  Destruction may be delayed if we*  are in the HandleEvent function.***********************************************************************/voidEvent_DestroySelector(EventSelector *es){    if (es->nestLevel) {	es->destroyPending = 1;	es->opsPending = 1;	return;    }    DestroySelector(es);}/*********************************************************************** %FUNCTION: Event_HandleEvent* %ARGUMENTS:*  es -- EventSelector* %RETURNS:*  0 if OK, non-zero on error.  errno is set appropriately.* %DESCRIPTION:*  Handles a single event (uses select() to wait for an event.)***********************************************************************/intEvent_HandleEvent(EventSelector *es){    fd_set readfds, writefds;    fd_set *rd, *wr;    unsigned int flags;    struct timeval abs_timeout, now;    struct timeval timeout;    struct timeval *tm;    EventHandler *eh;    int r = 0;    int errno_save = 0;    int foundTimeoutEvent = 0;    int foundReadEvent = 0;    int foundWriteEvent = 0;    int maxfd = -1;    int pastDue;    EVENT_DEBUG(("Enter Event_HandleEvent(es=%p)\n", (void *) es));    /* Build the select sets */    FD_ZERO(&readfds);    FD_ZERO(&writefds);    eh = es->handlers;    for (eh=es->handlers; eh; eh=eh->next) {	if (eh->flags & EVENT_FLAG_DELETED) continue;	if (eh->flags & EVENT_FLAG_READABLE) {	    foundReadEvent = 1;	    FD_SET(eh->fd, &readfds);	    if (eh->fd > maxfd) maxfd = eh->fd;	}	if (eh->flags & EVENT_FLAG_WRITEABLE) {	    foundWriteEvent = 1;	    FD_SET(eh->fd, &writefds);	    if (eh->fd > maxfd) maxfd = eh->fd;	}	if (eh->flags & EVENT_TIMER_BITS) {	    if (!foundTimeoutEvent) {		abs_timeout = eh->tmout;		foundTimeoutEvent = 1;	    } else {		if (eh->tmout.tv_sec < abs_timeout.tv_sec ||		    (eh->tmout.tv_sec == abs_timeout.tv_sec &&		     eh->tmout.tv_usec < abs_timeout.tv_usec)) {		    abs_timeout = eh->tmout;		}	    }	}    }    if (foundReadEvent) {	rd = &readfds;    } else {	rd = NULL;    }    if (foundWriteEvent) {	wr = &writefds;    } else {	wr = NULL;    }    if (foundTimeoutEvent) {	gettimeofday(&now, NULL);	/* Convert absolute timeout to relative timeout for select */	timeout.tv_usec = abs_timeout.tv_usec - now.tv_usec;	timeout.tv_sec = abs_timeout.tv_sec - now.tv_sec;	if (timeout.tv_usec < 0) {	    timeout.tv_usec += 1000000;	    timeout.tv_sec--;	}	if (timeout.tv_sec < 0 ||	    (timeout.tv_sec == 0 && timeout.tv_usec < 0)) {	    timeout.tv_sec = 0;	    timeout.tv_usec = 0;	}	tm = &timeout;    } else {	tm = NULL;    }    if (foundReadEvent || foundWriteEvent || foundTimeoutEvent) {	for(;;) {	    r = select(maxfd+1, rd, wr, NULL, tm);	    if (r < 0) {		if (errno == EINTR) continue;	    }	    break;	}    }    if (foundTimeoutEvent) gettimeofday(&now, NULL);    errno_save = errno;    es->nestLevel++;    if (r >= 0) {	/* Call handlers */	for (eh=es->handlers; eh; eh=eh->next) {	    /* Pending delete for this handler?  Ignore it */	    if (eh->flags & EVENT_FLAG_DELETED) continue;	    flags = 0;	    if ((eh->flags & EVENT_FLAG_READABLE) &&		FD_ISSET(eh->fd, &readfds)) {		flags |= EVENT_FLAG_READABLE;	    }	    if ((eh->flags & EVENT_FLAG_WRITEABLE) &&		FD_ISSET(eh->fd, &writefds)) {		flags |= EVENT_FLAG_WRITEABLE;	    }	    if (eh->flags & EVENT_TIMER_BITS) {		pastDue = (eh->tmout.tv_sec < now.tv_sec ||			   (eh->tmout.tv_sec == now.tv_sec &&			    eh->tmout.tv_usec <= now.tv_usec));		if (pastDue) {		    flags |= EVENT_TIMER_BITS;		    if (eh->flags & EVENT_FLAG_TIMER) {			/* Timer events are only called once */			es->opsPending = 1;			eh->flags |= EVENT_FLAG_DELETED;		    }		}	    }	    /* Do callback */	    if (flags) {		EVENT_DEBUG(("Enter callback: eh=%p flags=%u\n", eh, flags));		eh->fn(es, eh->fd, flags, eh->data);		EVENT_DEBUG(("Leave callback: eh=%p flags=%u\n", eh, flags));	    }	}    }    es->nestLevel--;    if (!es->nestLevel && es->opsPending) {	DoPendingChanges(es);    }    errno = errno_save;    return r;}/*********************************************************************** %FUNCTION: Event_AddHandler* %ARGUMENTS:*  es -- event selector*  fd -- file descriptor to watch*  flags -- combination of EVENT_FLAG_READABLE and EVENT_FLAG_WRITEABLE*  fn -- callback function to call when event is triggered*  data -- extra data to pass to callback function* %RETURNS:*  A newly-allocated EventHandler, or NULL.***********************************************************************/EventHandler *Event_AddHandler(EventSelector *es,		 int fd,		 unsigned int flags,		 EventCallbackFunc fn,		 void *data){    EventHandler *eh;    /* Specifically disable timer and deleted flags */    flags &= (~(EVENT_TIMER_BITS | EVENT_FLAG_DELETED));    /* Bad file descriptor */    if (fd < 0) {	errno = EBADF;	return NULL;    }    eh = malloc(sizeof(EventHandler));    if (!eh) return NULL;    eh->fd = fd;    eh->flags = flags;    eh->tmout.tv_usec = 0;    eh->tmout.tv_sec = 0;    eh->fn = fn;    eh->data = data;    /* Add immediately.  This is safe even if we are in a handler. */    eh->next = es->handlers;    es->handlers = eh;    EVENT_DEBUG(("Event_AddHandler(es=%p, fd=%d, flags=%u) -> %p\n", es, fd, flags, eh));    return eh;}/*********************************************************************** %FUNCTION: Event_AddHandlerWithTimeout* %ARGUMENTS:*  es -- event selector*  fd -- file descriptor to watch*  flags -- combination of EVENT_FLAG_READABLE and EVENT_FLAG_WRITEABLE*  t -- Timeout after which to call handler, even if not readable/writable.*       If t.tv_sec < 0, calls normal Event_AddHandler with no timeout.*  fn -- callback function to call when event is triggered*  data -- extra data to pass to callback function* %RETURNS:*  A newly-allocated EventHandler, or NULL.***********************************************************************/EventHandler *Event_AddHandlerWithTimeout(EventSelector *es,			    int fd,			    unsigned int flags,			    struct timeval t,			    EventCallbackFunc fn,			    void *data){    EventHandler *eh;    struct timeval now;    /* If timeout is negative, just do normal non-timing-out event */    if (t.tv_sec < 0 || t.tv_usec < 0) {	return Event_AddHandler(es, fd, flags, fn, data);    }    /* Specifically disable timer and deleted flags */    flags &= (~(EVENT_FLAG_TIMER | EVENT_FLAG_DELETED));    flags |= EVENT_FLAG_TIMEOUT;    /* Bad file descriptor? */    if (fd < 0) {	errno = EBADF;	return NULL;    }    /* Bad timeout? */    if (t.tv_usec >= 1000000) {	errno = EINVAL;	return NULL;    }    eh = malloc(sizeof(EventHandler));    if (!eh) return NULL;    /* Convert time interval to absolute time */    gettimeofday(&now, NULL);    t.tv_sec += now.tv_sec;    t.tv_usec += now.tv_usec;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -