📄 event.c
字号:
/* * OpenVPN -- An application to securely tunnel IP networks * over a single TCP/UDP port, with support for SSL/TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2002-2004 James Yonan <jim@yonan.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program (see the file COPYING included with this * distribution); if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#ifdef WIN32#include "config-win32.h"#else#include "config.h"#endif#include "syshead.h"#include "buffer.h"#include "error.h"#include "integer.h"#include "event.h"#include "memdbg.h"/* * Some OSes will prefer select() over poll() * when both are available. */#if defined(TARGET_DARWIN)#define SELECT_PREFERRED_OVER_POLL#endif/* * All non-windows OSes are assumed to have select() */#ifdef WIN32#define SELECT 0#else#define SELECT 1#endifstatic inline inttv_to_ms_timeout (const struct timeval *tv){ return max_int (tv->tv_sec * 1000 + (tv->tv_usec + 500) / 1000, 1);}#ifdef WIN32struct we_set{ struct event_set_functions func; bool fast; HANDLE *events; struct event_set_return *esr; int n_events; int capacity;};static voidwe_free (struct event_set *es){ struct we_set *wes = (struct we_set *) es; free (wes->events); free (wes->esr); free (wes);}static voidwe_reset (struct event_set *es){ struct we_set *wes = (struct we_set *) es; ASSERT (wes->fast); wes->n_events = 0;}static voidwe_del (struct event_set *es, event_t event){ struct we_set *wes = (struct we_set *) es; ASSERT (!wes->fast); ASSERT (0); // JYFIXME -- implement we_del}static voidwe_ctl (struct event_set *es, event_t event, unsigned int rwflags, void *arg){ struct we_set *wes = (struct we_set *) es; msg (D_EVENT_WAIT, "WE_CTL n=%d rwflags=0x%04x ev=0x%08x arg=" ptr_format, wes->n_events, rwflags, (unsigned int)event, (ptr_type)arg); if (wes->fast) { if (rwflags & EVENT_WRITE) { if (wes->n_events < wes->capacity) { wes->events[wes->n_events] = event->write; wes->esr[wes->n_events].rwflags = EVENT_WRITE; wes->esr[wes->n_events].arg = arg; ++wes->n_events; } else goto err; } if (rwflags & EVENT_READ) { if (wes->n_events < wes->capacity) { wes->events[wes->n_events] = event->read; wes->esr[wes->n_events].rwflags = EVENT_READ; wes->esr[wes->n_events].arg = arg; ++wes->n_events; } else goto err; } } else { ASSERT (0); // JYFIXME -- implement we_ctl for !fast } return; err: msg (D_EVENT_ERRORS, "Error: Windows resource limit WSA_MAXIMUM_WAIT_EVENTS (%d) has been exceeded", WSA_MAXIMUM_WAIT_EVENTS);}static intwe_wait (struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen){ struct we_set *wes = (struct we_set *) es; const DWORD status = WSAWaitForMultipleEvents( (DWORD) wes->n_events, wes->events, FALSE, (DWORD) tv_to_ms_timeout (tv), FALSE); if (outlen >= 1 && status >= WSA_WAIT_EVENT_0 && status < WSA_WAIT_EVENT_0 + (DWORD) wes->n_events) { *out = wes->esr[status - WSA_WAIT_EVENT_0]; msg (D_EVENT_WAIT, "WE_WAIT rwflags=0x%04x arg=" ptr_format, out->rwflags, (ptr_type)out->arg); return 1; } else if (status == WSA_WAIT_TIMEOUT) return 0; else return -1;}static struct event_set *we_init (int *maxevents, unsigned int flags){ struct we_set *wes; msg (D_EVENT_WAIT, "WE_INIT maxevents=%d flags=0x%08x", *maxevents, flags); ALLOC_OBJ_CLEAR (wes, struct we_set); /* set dispatch functions */ wes->func.free = we_free; wes->func.reset = we_reset; wes->func.del = we_del; wes->func.ctl = we_ctl; wes->func.wait = we_wait; if (flags & EVENT_METHOD_FAST) wes->fast = true; wes->n_events = 0; /* Figure our event capacity */ ASSERT (*maxevents > 0); wes->capacity = min_int (*maxevents * 2, WSA_MAXIMUM_WAIT_EVENTS); *maxevents = min_int (*maxevents, WSA_MAXIMUM_WAIT_EVENTS); /* Allocate space for Win32 event handles */ ALLOC_ARRAY_CLEAR (wes->events, HANDLE, wes->capacity); /* Allocate space for event_set_return objects */ ALLOC_ARRAY_CLEAR (wes->esr, struct event_set_return, wes->capacity); msg (D_EVENT_WAIT, "WE_INIT maxevents=%d capacity=%d", *maxevents, wes->capacity); return (struct event_set *) wes;}#endif /* WIN32 */#if EPOLLstruct ep_set{ struct event_set_functions func; bool fast; int epfd; int maxevents; struct epoll_event *events;};static voidep_free (struct event_set *es){ struct ep_set *eps = (struct ep_set *) es; close (eps->epfd); free (eps->events); free (eps);}static voidep_reset (struct event_set *es){ const struct ep_set *eps = (struct ep_set *) es; ASSERT (eps->fast);}static voidep_del (struct event_set *es, event_t event){ struct ep_set *eps = (struct ep_set *) es; ASSERT (!eps->fast); if (epoll_ctl (eps->epfd, EPOLL_CTL_DEL, event, NULL) < 0) msg (M_ERR, "EVENT: epoll_ctl EPOLL_CTL_DEL failed");}static voidep_ctl (struct event_set *es, event_t event, unsigned int rwflags, void *arg){ struct ep_set *eps = (struct ep_set *) es; struct epoll_event ev; ev.events = 0; ev.data.ptr = arg; if (rwflags & EVENT_READ) ev.events |= EPOLLIN; if (rwflags & EVENT_WRITE) ev.events |= EPOLLOUT; msg (D_EVENT_WAIT, "EP_CTL fd=%d rwflags=0x%04x ev=0x%08x arg=" ptr_format, (int)event, rwflags, (unsigned int)ev.events, (ptr_type)ev.data.ptr); if (epoll_ctl (eps->epfd, EPOLL_CTL_MOD, event, &ev) < 0) { if (errno == ENOENT) { if (epoll_ctl (eps->epfd, EPOLL_CTL_ADD, event, &ev) < 0) msg (M_ERR, "EVENT: epoll_ctl EPOLL_CTL_ADD failed"); } else msg (M_ERR, "EVENT: epoll_ctl EPOLL_CTL_MOD failed"); }}static intep_wait (struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen){ struct ep_set *eps = (struct ep_set *) es; int stat; if (outlen > eps->maxevents) outlen = eps->maxevents; stat = epoll_wait (eps->epfd, eps->events, outlen, tv_to_ms_timeout (tv)); ASSERT (stat <= outlen); if (stat > 0) { int i; const struct epoll_event *ev = eps->events; struct event_set_return *esr = out; for (i = 0; i < stat; ++i) { esr->rwflags = 0; if (ev->events & (EPOLLIN|EPOLLPRI|EPOLLERR)) esr->rwflags |= EVENT_READ; if (ev->events & EPOLLOUT) esr->rwflags |= EVENT_WRITE; esr->arg = ev->data.ptr; msg (D_EVENT_WAIT, "EP_WAIT[%d] rwflags=0x%04x ev=0x%08x arg=" ptr_format, i, esr->rwflags, ev->events, (ptr_type)ev->data.ptr); ++ev; ++esr; } } return stat;}static struct event_set *ep_init (int *maxevents, unsigned int flags){ struct ep_set *eps; int fd; msg (D_EVENT_WAIT, "EP_INIT maxevents=%d flags=0x%08x", *maxevents, flags); /* open epoll file descriptor */ fd = epoll_create (*maxevents); if (fd < 0) return NULL; ALLOC_OBJ_CLEAR (eps, struct ep_set); /* set dispatch functions */ eps->func.free = ep_free; eps->func.reset = ep_reset; eps->func.del = ep_del; eps->func.ctl = ep_ctl; eps->func.wait = ep_wait; /* fast method ("sort of") corresponds to epoll one-shot */ if (flags & EVENT_METHOD_FAST) eps->fast = true; /* allocate space for epoll_wait return */ ASSERT (*maxevents > 0); eps->maxevents = *maxevents; ALLOC_ARRAY_CLEAR (eps->events, struct epoll_event, eps->maxevents); /* set epoll control fd */ eps->epfd = fd; return (struct event_set *) eps;}#endif /* EPOLL */#if POLLstruct po_set{ struct event_set_functions func; bool fast; struct pollfd *events; void **args; int n_events; int capacity;};static voidpo_free (struct event_set *es){ struct po_set *pos = (struct po_set *) es; free (pos->events); free (pos->args); free (pos);}static voidpo_reset (struct event_set *es)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -