1 /*
2  *  OpenVPN -- An application to securely tunnel IP networks
3  *             over a single TCP/UDP port, with support for SSL/TLS-based
4  *             session authentication and key exchange,
5  *             packet encryption, packet authentication, and
6  *             packet compression.
7  *
8  *  Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net>
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License version 2
12  *  as published by the Free Software Foundation.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License along
20  *  with this program; if not, write to the Free Software Foundation, Inc.,
21  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 #ifndef EVENT_H
25 #define EVENT_H
26 
27 #include "win32.h"
28 #include "sig.h"
29 #include "perf.h"
30 
31 /*
32  * rwflags passed to event_ctl and returned by
33  * struct event_set_return.
34  */
35 #define READ_SHIFT      0
36 #define WRITE_SHIFT     1
37 
38 #define EVENT_UNDEF     4
39 #define EVENT_READ      (1 << READ_SHIFT)
40 #define EVENT_WRITE     (1 << WRITE_SHIFT)
41 
42 /* event flags returned by io_wait.
43  *
44  * All these events are defined as bits in a bitfield.
45  * Each event 'type' owns two bits in the bitfield: one for the READ
46  * event and one for the WRITE event.
47  *
48  * For this reason, the specific event bit is calculated by adding
49  * the event type identifier (always a multiple of 2, as defined
50  * below) to 0 for READ and 1 for WRITE.
51  *
52  * E.g.
53  * MANAGEMENT_SHIFT = 6;  <---- event type identifier
54  * MANAGEMENT_READ = (1 << (6 + 0)),  <---- READ event
55  * MANAGEMENT_WRITE = (1 << (6 + 1))  <---- WRITE event
56  *
57  * 'error' and 'file_close' are special and use read/write for different
58  * signals.
59  */
60 
61 #define SOCKET_SHIFT        0
62 #define SOCKET_READ         (1 << (SOCKET_SHIFT + READ_SHIFT))
63 #define SOCKET_WRITE        (1 << (SOCKET_SHIFT + WRITE_SHIFT))
64 #define TUN_SHIFT           2
65 #define TUN_READ            (1 << (TUN_SHIFT + READ_SHIFT))
66 #define TUN_WRITE           (1 << (TUN_SHIFT + WRITE_SHIFT))
67 #define ERR_SHIFT           4
68 #define ES_ERROR            (1 << (ERR_SHIFT + READ_SHIFT))
69 #define ES_TIMEOUT          (1 << (ERR_SHIFT + WRITE_SHIFT))
70 #define MANAGEMENT_SHIFT    6
71 #define MANAGEMENT_READ     (1 << (MANAGEMENT_SHIFT + READ_SHIFT))
72 #define MANAGEMENT_WRITE    (1 << (MANAGEMENT_SHIFT + WRITE_SHIFT))
73 #define FILE_SHIFT          8
74 #define FILE_CLOSED         (1 << (FILE_SHIFT + READ_SHIFT))
75 
76 /*
77  * Initialization flags passed to event_set_init
78  */
79 #define EVENT_METHOD_US_TIMEOUT   (1<<0)
80 #define EVENT_METHOD_FAST         (1<<1)
81 
82 #ifdef _WIN32
83 
84 typedef const struct rw_handle *event_t;
85 
86 #define UNDEFINED_EVENT (NULL)
87 
88 #else  /* ifdef _WIN32 */
89 
90 typedef int event_t;
91 
92 #define UNDEFINED_EVENT (-1)
93 
94 #endif
95 
96 struct event_set;
97 struct event_set_return;
98 
99 struct event_set_functions
100 {
101     void (*free)(struct event_set *es);
102     void (*reset)(struct event_set *es);
103     void (*del)(struct event_set *es, event_t event);
104     void (*ctl)(struct event_set *es, event_t event, unsigned int rwflags, void *arg);
105 
106     /*
107      * Return status for wait:
108      * -1 on signal or error
109      * 0 on timeout
110      * length of event_set_return if at least 1 event is returned
111      */
112     int (*wait)(struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen);
113 };
114 
115 struct event_set_return
116 {
117     unsigned int rwflags;
118     void *arg;
119 };
120 
121 struct event_set
122 {
123     struct event_set_functions func;
124 };
125 
126 /*
127  * maxevents on input:  desired max number of event_t descriptors
128  *                      simultaneously set with event_ctl
129  * maxevents on output: may be modified down, depending on limitations
130  *                      of underlying API
131  * flags:               EVENT_METHOD_x flags
132  */
133 struct event_set *event_set_init(int *maxevents, unsigned int flags);
134 
135 static inline void
event_free(struct event_set * es)136 event_free(struct event_set *es)
137 {
138     if (es)
139     {
140         (*es->func.free)(es);
141     }
142 }
143 
144 static inline void
event_reset(struct event_set * es)145 event_reset(struct event_set *es)
146 {
147     (*es->func.reset)(es);
148 }
149 
150 static inline void
event_del(struct event_set * es,event_t event)151 event_del(struct event_set *es, event_t event)
152 {
153     (*es->func.del)(es, event);
154 }
155 
156 static inline void
event_ctl(struct event_set * es,event_t event,unsigned int rwflags,void * arg)157 event_ctl(struct event_set *es, event_t event, unsigned int rwflags, void *arg)
158 {
159     (*es->func.ctl)(es, event, rwflags, arg);
160 }
161 
162 static inline int
event_wait(struct event_set * es,const struct timeval * tv,struct event_set_return * out,int outlen)163 event_wait(struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen)
164 {
165     int ret;
166     perf_push(PERF_IO_WAIT);
167     ret = (*es->func.wait)(es, tv, out, outlen);
168     perf_pop();
169     return ret;
170 }
171 
172 static inline void
event_set_return_init(struct event_set_return * esr)173 event_set_return_init(struct event_set_return *esr)
174 {
175     esr->rwflags = 0;
176     esr->arg = NULL;
177 }
178 
179 #ifdef _WIN32
180 
181 static inline void
wait_signal(struct event_set * es,void * arg)182 wait_signal(struct event_set *es, void *arg)
183 {
184     if (HANDLE_DEFINED(win32_signal.in.read))
185     {
186         event_ctl(es, &win32_signal.in, EVENT_READ, arg);
187     }
188 }
189 
190 #else  /* ifdef _WIN32 */
191 
192 static inline void
wait_signal(struct event_set * es,void * arg)193 wait_signal(struct event_set *es, void *arg)
194 {
195 }
196 
197 #endif
198 
199 #endif /* ifndef EVENT_H */
200