📄 event.c
字号:
{ struct po_set *pos = (struct po_set *) es; ASSERT (pos->fast); pos->n_events = 0;}static voidpo_del (struct event_set *es, event_t event){ struct po_set *pos = (struct po_set *) es; ASSERT (!pos->fast); ASSERT (0); // JYFIXME -- implement po_del}static voidpo_ctl (struct event_set *es, event_t event, unsigned int rwflags, void *arg){ struct po_set *pos = (struct po_set *) es; msg (D_EVENT_WAIT, "PO_CTL rwflags=0x%04x ev=%d arg=" ptr_format, rwflags, (int)event, (ptr_type)arg); if (pos->fast) { if (pos->n_events < pos->capacity) { struct pollfd *pfdp = &pos->events[pos->n_events]; pfdp->fd = event; pfdp->events = pfdp->revents = 0; pos->args[pos->n_events] = arg; if (rwflags & EVENT_WRITE) pfdp->events |= POLLOUT; if (rwflags & EVENT_READ) pfdp->events |= (POLLIN|POLLPRI); ++pos->n_events; } else goto err; } else { ASSERT (0); // JYFIXME -- implement po_ctl for !fast } return; err: msg (D_EVENT_ERRORS, "Error: poll: too many I/O wait events");}static intpo_wait (struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen){ struct po_set *pos = (struct po_set *) es; int stat; stat = poll (pos->events, pos->n_events, tv_to_ms_timeout (tv)); // JYFIXME -- show extra debug info after poll() call#if 0 msg (D_EVENT_WAIT, "PO_WAIT DEBUG stat=%d pos->n_events=%d", stat, pos->n_events);#endif ASSERT (stat <= pos->n_events); if (stat > 0) { int i, j=0; const struct pollfd *pfdp = pos->events; for (i = 0; i < pos->n_events && j < outlen; ++i) { if (pfdp->revents & (POLLIN|POLLPRI|POLLERR|POLLHUP|POLLOUT)) { out->rwflags = 0; if (pfdp->revents & (POLLIN|POLLPRI|POLLERR|POLLHUP)) out->rwflags |= EVENT_READ; if (pfdp->revents & POLLOUT) out->rwflags |= EVENT_WRITE; out->arg = pos->args[i]; msg (D_EVENT_WAIT, "PO_WAIT[%d,%d] fd=%d rev=0x%08x rwflags=0x%04x arg=" ptr_format, i, j, pfdp->fd, pfdp->revents, out->rwflags, (ptr_type)out->arg); ++out; ++j; } ++pfdp; } return j; } return stat;}static struct event_set *po_init (int *maxevents, unsigned int flags){ struct po_set *pos; msg (D_EVENT_WAIT, "PO_INIT maxevents=%d flags=0x%08x", *maxevents, flags); ALLOC_OBJ_CLEAR (pos, struct po_set); /* set dispatch functions */ pos->func.free = po_free; pos->func.reset = po_reset; pos->func.del = po_del; pos->func.ctl = po_ctl; pos->func.wait = po_wait; if (flags & EVENT_METHOD_FAST) pos->fast = true; pos->n_events = 0; /* Figure our event capacity */ ASSERT (*maxevents > 0); pos->capacity = *maxevents; /* Allocate space for pollfd structures to be passed to poll() */ ALLOC_ARRAY_CLEAR (pos->events, struct pollfd, pos->capacity); /* Allocate space for event_set_return objects */ ALLOC_ARRAY_CLEAR (pos->args, void *, pos->capacity); return (struct event_set *) pos;}#endif /* POLL */#if SELECTstruct se_set{ struct event_set_functions func; bool fast; fd_set readfds; fd_set writefds; void **args; int maxfd; int capacity;};static voidse_free (struct event_set *es){ struct se_set *ses = (struct se_set *) es; free (ses->args); free (ses);}static voidse_reset (struct event_set *es){ struct se_set *ses = (struct se_set *) es; int i; ASSERT (ses->fast); FD_ZERO (&ses->readfds); FD_ZERO (&ses->writefds); for (i = 0; i <= ses->maxfd; ++i) ses->args[i] = NULL; ses->maxfd = -1;}static voidse_del (struct event_set *es, event_t event){ struct se_set *ses = (struct se_set *) es; ASSERT (!ses->fast); if (event >= 0 && event < ses->capacity) { FD_CLR (event, &ses->readfds); FD_CLR (event, &ses->writefds); ses->args[event] = NULL; } else msg (D_EVENT_ERRORS, "Error: select/se_del: too many I/O wait events"); return;}static voidse_ctl (struct event_set *es, event_t event, unsigned int rwflags, void *arg){ struct se_set *ses = (struct se_set *) es; msg (D_EVENT_WAIT, "SE_CTL rwflags=0x%04x ev=%d arg=" ptr_format, rwflags, (int)event, (ptr_type)arg); if (event >= 0 && event < ses->capacity) { ses->maxfd = max_int (event, ses->maxfd); ses->args[event] = arg; if (ses->fast) { if (rwflags & EVENT_READ) FD_SET (event, &ses->readfds); if (rwflags & EVENT_WRITE) FD_SET (event, &ses->writefds); } else { if (rwflags & EVENT_READ) FD_SET (event, &ses->readfds); else FD_CLR (event, &ses->readfds); if (rwflags & EVENT_WRITE) FD_SET (event, &ses->writefds); else FD_CLR (event, &ses->writefds); } } else { msg (D_EVENT_ERRORS, "Error: select: too many I/O wait events"); }}static intse_wait_return (struct se_set *ses, fd_set *read, fd_set *write, struct event_set_return *out, int outlen){ int i, j = 0; for (i = 0; i <= ses->maxfd && j < outlen; ++i) { const bool r = FD_ISSET (i, read); const bool w = FD_ISSET (i, write); if (r || w) { out->rwflags = 0; if (r) out->rwflags |= EVENT_READ; if (w) out->rwflags |= EVENT_WRITE; out->arg = ses->args[i]; msg (D_EVENT_WAIT, "SE_WAIT[%d,%d] rwflags=0x%04x arg=" ptr_format, i, j, out->rwflags, (ptr_type)out->arg); ++out; ++j; } } return j;}static intse_wait_fast (struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen){ struct se_set *ses = (struct se_set *) es; struct timeval tv_tmp = *tv; int stat; stat = select (ses->maxfd + 1, &ses->readfds, &ses->writefds, NULL, &tv_tmp); if (stat > 0) stat = se_wait_return (ses, &ses->readfds, &ses->writefds, out, outlen); return stat;}static intse_wait_scalable (struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen){ struct se_set *ses = (struct se_set *) es; struct timeval tv_tmp = *tv; fd_set read = ses->readfds; fd_set write = ses->writefds; int stat; stat = select (ses->maxfd + 1, &read, &write, NULL, &tv_tmp); if (stat > 0) stat = se_wait_return (ses, &read, &write, out, outlen); return stat;}static struct event_set *se_init (int *maxevents, unsigned int flags){ const int maximum_fds = 256; // JYFIXME -- figure out the minimum on all OSes which OpenVPN supports struct se_set *ses; msg (D_EVENT_WAIT, "SE_INIT maxevents=%d flags=0x%08x", *maxevents, flags); ALLOC_OBJ_CLEAR (ses, struct se_set); /* set dispatch functions */ ses->func.free = se_free; ses->func.reset = se_reset; ses->func.del = se_del; ses->func.ctl = se_ctl; ses->func.wait = se_wait_scalable; if (flags & EVENT_METHOD_FAST) { ses->fast = true; ses->func.wait = se_wait_fast; } /* Select needs to be passed this value + 1 */ ses->maxfd = -1; /* Figure our event capacity */ ASSERT (*maxevents > 0); *maxevents = min_int (*maxevents, maximum_fds); ses->capacity = *maxevents + 10; /* Allocate space for event_set_return void * args */ ALLOC_ARRAY_CLEAR (ses->args, void *, ses->capacity); return (struct event_set *) ses;}#endif /* SELECT */static struct event_set *event_set_init_simple (int *maxevents, unsigned int flags){ struct event_set *ret = NULL;#ifdef WIN32 ret = we_init (maxevents, flags);#elif POLL && SELECT if (flags & EVENT_METHOD_US_TIMEOUT) ret = se_init (maxevents, flags); # ifdef SELECT_PREFERRED_OVER_POLL if (!ret) ret = se_init (maxevents, flags); if (!ret) ret = po_init (maxevents, flags);# else if (!ret) ret = po_init (maxevents, flags); if (!ret) ret = se_init (maxevents, flags);# endif#elif POLL ret = po_init (maxevents, flags);#elif SELECT ret = se_init (maxevents, flags);#else#error At least one of poll, select, or WSAWaitForMultipleEvents must be supported by the kernel#endif ASSERT (ret); return ret;}static struct event_set *event_set_init_scalable (int *maxevents, unsigned int flags){ struct event_set *ret = NULL;#if EPOLL ret = ep_init (maxevents, flags); if (!ret) { msg (M_WARN, "Note: sys_epoll API is unavailable, falling back to poll/select API"); ret = event_set_init_simple (maxevents, flags); }#else ret = event_set_init_simple (maxevents, flags);#endif ASSERT (ret); return ret;}struct event_set *event_set_init (int *maxevents, unsigned int flags){ if (flags & EVENT_METHOD_FAST) return event_set_init_simple (maxevents, flags); else return event_set_init_scalable (maxevents, flags);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -