Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 990 lines (858 sloc) 25.376 kb
5908bd7 @provos provided buffered events
provos authored
1 /*
b85b710 Update copyright statements to reflect the facts that:
Nick Mathewson authored
2 * Copyright (c) 2002-2007 Niels Provos <provos@citi.umich.edu>
e49e289 Update copyright notices to 2012
Nick Mathewson authored
3 * Copyright (c) 2007-2012 Niels Provos, Nick Mathewson
5908bd7 @provos provided buffered events
provos authored
4 *
849d524 @provos license
provos authored
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5908bd7 @provos provided buffered events
provos authored
26 */
27
ec347b9 Move event-config.h to include/event2
Nick Mathewson authored
28 #include "event2/event-config.h"
0915ca0 @kev009 Include evconfig-private.h in internal files for great good.
kev009 authored
29 #include "evconfig-private.h"
30
31 #include <sys/types.h>
5908bd7 @provos provided buffered events
provos authored
32
68120d9 Convert event-config.h macros to avoid reserved identifiers
Nick Mathewson authored
33 #ifdef EVENT__HAVE_SYS_TIME_H
5908bd7 @provos provided buffered events
provos authored
34 #include <sys/time.h>
35 #endif
36
37 #include <errno.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
68120d9 Convert event-config.h macros to avoid reserved identifiers
Nick Mathewson authored
41 #ifdef EVENT__HAVE_STDARG_H
5908bd7 @provos provided buffered events
provos authored
42 #include <stdarg.h>
43 #endif
44
9f560bf Use "_WIN32", not WIN32: it's standard and we don't need to fake it
Nick Mathewson authored
45 #ifdef _WIN32
4e1ec3e Make all the C files in the libraries compile under MSVC 2005 Express. ...
Nick Mathewson authored
46 #include <winsock2.h>
47 #endif
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
48 #include <errno.h>
4e1ec3e Make all the C files in the libraries compile under MSVC 2005 Express. ...
Nick Mathewson authored
49
0ac7307 r15193@tombo: nickm | 2008-04-16 16:00:35 -0400
Nick Mathewson authored
50 #include "event2/util.h"
51 #include "event2/buffer.h"
d7d1f1d Move responsibility for IOCP callback into bufferevent_async.
Nick Mathewson authored
52 #include "event2/buffer_compat.h"
53 #include "event2/bufferevent.h"
0ac7307 r15193@tombo: nickm | 2008-04-16 16:00:35 -0400
Nick Mathewson authored
54 #include "event2/bufferevent_struct.h"
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
55 #include "event2/bufferevent_compat.h"
0ac7307 r15193@tombo: nickm | 2008-04-16 16:00:35 -0400
Nick Mathewson authored
56 #include "event2/event.h"
02fbf68 Use finalization feature so bufferevents can avoid deadlocks
Nick Mathewson authored
57 #include "event-internal.h"
169321c Rename four internal headers to follow the -internal.h convention.
Nick Mathewson authored
58 #include "log-internal.h"
7eb250e r14939@tombo: nickm | 2007-11-25 11:59:26 -0500
Nick Mathewson authored
59 #include "mm-internal.h"
682adc4 @provos support input/output filters for bufferevents
provos authored
60 #include "bufferevent-internal.h"
d7d1f1d Move responsibility for IOCP callback into bufferevent_async.
Nick Mathewson authored
61 #include "evbuffer-internal.h"
81ab45a Use new EVUTIL_ERR_*_RETRIABLE macros when we're testing an errno for bl...
Nick Mathewson authored
62 #include "util-internal.h"
5908bd7 @provos provided buffered events
provos authored
63
cb9da0b Fix all identifiers with names beginning with underscore.
Nick Mathewson authored
64 static void bufferevent_cancel_all_(struct bufferevent *bev);
02fbf68 Use finalization feature so bufferevents can avoid deadlocks
Nick Mathewson authored
65 static void bufferevent_finalize_cb_(struct event_callback *evcb, void *arg_);
e6af35d Correctly terminate IO on an async bufferevent on bufferevent_free
Nick Mathewson authored
66
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
67 void
8ac3c4c Have all visible internal function names end with an underscore.
Nick Mathewson authored
68 bufferevent_suspend_read_(struct bufferevent *bufev, bufferevent_suspend_flags what)
682adc4 @provos support input/output filters for bufferevents
provos authored
69 {
1becc4c Refactor new elements of bufferevent into bufferevent_private structure
Nick Mathewson authored
70 struct bufferevent_private *bufev_private =
71 EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
915193e Locking support for bufferevents.
Nick Mathewson authored
72 BEV_LOCK(bufev);
0d744aa Refactor our 'suspend operation' logic on bufferevents.
Nick Mathewson authored
73 if (!bufev_private->read_suspended)
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
74 bufev->be_ops->disable(bufev, EV_READ);
0d744aa Refactor our 'suspend operation' logic on bufferevents.
Nick Mathewson authored
75 bufev_private->read_suspended |= what;
5948429 Fix a deadlock: there were some LOCKs that should have been UNLOCKs. Re...
Nick Mathewson authored
76 BEV_UNLOCK(bufev);
682adc4 @provos support input/output filters for bufferevents
provos authored
77 }
78
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
79 void
8ac3c4c Have all visible internal function names end with an underscore.
Nick Mathewson authored
80 bufferevent_unsuspend_read_(struct bufferevent *bufev, bufferevent_suspend_flags what)
5908bd7 @provos provided buffered events
provos authored
81 {
1becc4c Refactor new elements of bufferevent into bufferevent_private structure
Nick Mathewson authored
82 struct bufferevent_private *bufev_private =
83 EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
0d744aa Refactor our 'suspend operation' logic on bufferevents.
Nick Mathewson authored
84 BEV_LOCK(bufev);
85 bufev_private->read_suspended &= ~what;
040a019 @SimonPerreault Obey enabled status when unsuspending
SimonPerreault authored
86 if (!bufev_private->read_suspended && (bufev->enabled & EV_READ))
0d744aa Refactor our 'suspend operation' logic on bufferevents.
Nick Mathewson authored
87 bufev->be_ops->enable(bufev, EV_READ);
88 BEV_UNLOCK(bufev);
89 }
915193e Locking support for bufferevents.
Nick Mathewson authored
90
0d744aa Refactor our 'suspend operation' logic on bufferevents.
Nick Mathewson authored
91 void
8ac3c4c Have all visible internal function names end with an underscore.
Nick Mathewson authored
92 bufferevent_suspend_write_(struct bufferevent *bufev, bufferevent_suspend_flags what)
0d744aa Refactor our 'suspend operation' logic on bufferevents.
Nick Mathewson authored
93 {
94 struct bufferevent_private *bufev_private =
95 EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
915193e Locking support for bufferevents.
Nick Mathewson authored
96 BEV_LOCK(bufev);
0d744aa Refactor our 'suspend operation' logic on bufferevents.
Nick Mathewson authored
97 if (!bufev_private->write_suspended)
98 bufev->be_ops->disable(bufev, EV_WRITE);
99 bufev_private->write_suspended |= what;
5948429 Fix a deadlock: there were some LOCKs that should have been UNLOCKs. Re...
Nick Mathewson authored
100 BEV_UNLOCK(bufev);
5908bd7 @provos provided buffered events
provos authored
101 }
102
0d744aa Refactor our 'suspend operation' logic on bufferevents.
Nick Mathewson authored
103 void
8ac3c4c Have all visible internal function names end with an underscore.
Nick Mathewson authored
104 bufferevent_unsuspend_write_(struct bufferevent *bufev, bufferevent_suspend_flags what)
0d744aa Refactor our 'suspend operation' logic on bufferevents.
Nick Mathewson authored
105 {
106 struct bufferevent_private *bufev_private =
107 EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
108 BEV_LOCK(bufev);
109 bufev_private->write_suspended &= ~what;
040a019 @SimonPerreault Obey enabled status when unsuspending
SimonPerreault authored
110 if (!bufev_private->write_suspended && (bufev->enabled & EV_WRITE))
0d744aa Refactor our 'suspend operation' logic on bufferevents.
Nick Mathewson authored
111 bufev->be_ops->enable(bufev, EV_WRITE);
112 BEV_UNLOCK(bufev);
113 }
114
115
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
116 /* Callback to implement watermarks on the input buffer. Only enabled
117 * if the watermark is set. */
5908bd7 @provos provided buffered events
provos authored
118 static void
f1b1bad Make the new evbuffer callbacks use a new struct-based interface.
Nick Mathewson authored
119 bufferevent_inbuf_wm_cb(struct evbuffer *buf,
120 const struct evbuffer_cb_info *cbinfo,
121 void *arg)
5908bd7 @provos provided buffered events
provos authored
122 {
123 struct bufferevent *bufev = arg;
e5bbd40 Clean up formatting: use tabs, not 8-spaces, to indent.
Nick Mathewson authored
124 size_t size;
915193e Locking support for bufferevents.
Nick Mathewson authored
125
126 size = evbuffer_get_length(buf);
5908bd7 @provos provided buffered events
provos authored
127
5846bf6 Simplify the read high-watermark checking.
Nick Mathewson authored
128 if (size >= bufev->wm_read.high)
129 bufferevent_wm_suspend_read(bufev);
130 else
131 bufferevent_wm_unsuspend_read(bufev);
5908bd7 @provos provided buffered events
provos authored
132 }
133
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
134 static void
a4079aa Replace more deferred_cb names with event_callback
Nick Mathewson authored
135 bufferevent_run_deferred_callbacks_locked(struct event_callback *cb, void *arg)
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
136 {
137 struct bufferevent_private *bufev_private = arg;
138 struct bufferevent *bufev = &bufev_private->bev;
139
140 BEV_LOCK(bufev);
bd26bac When running with deferred callbacks, always send the "connected" event
Nick Mathewson authored
141 if ((bufev_private->eventcb_pending & BEV_EVENT_CONNECTED) &&
142 bufev->errorcb) {
143 /* The "connected" happened before any reads or writes, so
144 send it first. */
145 bufev_private->eventcb_pending &= ~BEV_EVENT_CONNECTED;
146 bufev->errorcb(bufev, BEV_EVENT_CONNECTED, bufev->cbarg);
147 }
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
148 if (bufev_private->readcb_pending && bufev->readcb) {
149 bufev_private->readcb_pending = 0;
150 bufev->readcb(bufev, bufev->cbarg);
151 }
152 if (bufev_private->writecb_pending && bufev->writecb) {
153 bufev_private->writecb_pending = 0;
154 bufev->writecb(bufev, bufev->cbarg);
155 }
5232cfa Consistently say "eventcb" instead of "errorcb"
Nick Mathewson authored
156 if (bufev_private->eventcb_pending && bufev->errorcb) {
157 short what = bufev_private->eventcb_pending;
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
158 int err = bufev_private->errno_pending;
5232cfa Consistently say "eventcb" instead of "errorcb"
Nick Mathewson authored
159 bufev_private->eventcb_pending = 0;
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
160 bufev_private->errno_pending = 0;
161 EVUTIL_SET_SOCKET_ERROR(err);
162 bufev->errorcb(bufev, what, bufev->cbarg);
163 }
cb9da0b Fix all identifiers with names beginning with underscore.
Nick Mathewson authored
164 bufferevent_decref_and_unlock_(bufev);
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
165 }
166
a5208fe @fancycode Release locks on bufferevents while executing callbacks
fancycode authored
167 static void
a4079aa Replace more deferred_cb names with event_callback
Nick Mathewson authored
168 bufferevent_run_deferred_callbacks_unlocked(struct event_callback *cb, void *arg)
a5208fe @fancycode Release locks on bufferevents while executing callbacks
fancycode authored
169 {
170 struct bufferevent_private *bufev_private = arg;
171 struct bufferevent *bufev = &bufev_private->bev;
172
173 BEV_LOCK(bufev);
174 #define UNLOCKED(stmt) \
175 do { BEV_UNLOCK(bufev); stmt; BEV_LOCK(bufev); } while(0)
176
177 if ((bufev_private->eventcb_pending & BEV_EVENT_CONNECTED) &&
178 bufev->errorcb) {
179 /* The "connected" happened before any reads or writes, so
180 send it first. */
181 bufferevent_event_cb errorcb = bufev->errorcb;
182 void *cbarg = bufev->cbarg;
183 bufev_private->eventcb_pending &= ~BEV_EVENT_CONNECTED;
184 UNLOCKED(errorcb(bufev, BEV_EVENT_CONNECTED, cbarg));
185 }
186 if (bufev_private->readcb_pending && bufev->readcb) {
187 bufferevent_data_cb readcb = bufev->readcb;
188 void *cbarg = bufev->cbarg;
189 bufev_private->readcb_pending = 0;
190 UNLOCKED(readcb(bufev, cbarg));
191 }
192 if (bufev_private->writecb_pending && bufev->writecb) {
193 bufferevent_data_cb writecb = bufev->writecb;
194 void *cbarg = bufev->cbarg;
195 bufev_private->writecb_pending = 0;
196 UNLOCKED(writecb(bufev, cbarg));
197 }
198 if (bufev_private->eventcb_pending && bufev->errorcb) {
199 bufferevent_event_cb errorcb = bufev->errorcb;
200 void *cbarg = bufev->cbarg;
201 short what = bufev_private->eventcb_pending;
202 int err = bufev_private->errno_pending;
203 bufev_private->eventcb_pending = 0;
204 bufev_private->errno_pending = 0;
205 EVUTIL_SET_SOCKET_ERROR(err);
206 UNLOCKED(errorcb(bufev,what,cbarg));
207 }
cb9da0b Fix all identifiers with names beginning with underscore.
Nick Mathewson authored
208 bufferevent_decref_and_unlock_(bufev);
a5208fe @fancycode Release locks on bufferevents while executing callbacks
fancycode authored
209 #undef UNLOCKED
210 }
211
b06b264 Make "deferred callback queue" independent of event_base.
Nick Mathewson authored
212 #define SCHEDULE_DEFERRED(bevp) \
213 do { \
ae2b84b Replace deferred_cbs with event_callback-based implementation.
Nick Mathewson authored
214 if (event_deferred_cb_schedule_( \
a4079aa Replace more deferred_cb names with event_callback
Nick Mathewson authored
215 (bevp)->bev.ev_base, \
ae2b84b Replace deferred_cbs with event_callback-based implementation.
Nick Mathewson authored
216 &(bevp)->deferred)) \
217 bufferevent_incref_(&(bevp)->bev); \
17a14f1 @chris-davis Only process up to MAX_DEFERRED deferred_cbs at a time.
chris-davis authored
218 } while (0)
b06b264 Make "deferred callback queue" independent of event_base.
Nick Mathewson authored
219
220
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
221 void
61ee18b @mistotebe Add an option to trigger bufferevent I/O callbacks
mistotebe authored
222 bufferevent_run_readcb_(struct bufferevent *bufev, int options)
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
223 {
a62283a Always hold a reference to a bufferevent when calling its callbacks.
Nick Mathewson authored
224 /* Requires that we hold the lock and a reference */
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
225 struct bufferevent_private *p =
226 EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
2e8eeea Fix crash bugs when a bufferevent's eventcb is not set.
Nick Mathewson authored
227 if (bufev->readcb == NULL)
228 return;
a3172a4 Minor optimizations on bufferevent_trigger options
Nick Mathewson authored
229 if ((p->options|options) & BEV_OPT_DEFER_CALLBACKS) {
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
230 p->readcb_pending = 1;
ae2b84b Replace deferred_cbs with event_callback-based implementation.
Nick Mathewson authored
231 SCHEDULE_DEFERRED(p);
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
232 } else {
233 bufev->readcb(bufev, bufev->cbarg);
234 }
235 }
236
237 void
61ee18b @mistotebe Add an option to trigger bufferevent I/O callbacks
mistotebe authored
238 bufferevent_run_writecb_(struct bufferevent *bufev, int options)
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
239 {
a62283a Always hold a reference to a bufferevent when calling its callbacks.
Nick Mathewson authored
240 /* Requires that we hold the lock and a reference */
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
241 struct bufferevent_private *p =
242 EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
2e8eeea Fix crash bugs when a bufferevent's eventcb is not set.
Nick Mathewson authored
243 if (bufev->writecb == NULL)
244 return;
a3172a4 Minor optimizations on bufferevent_trigger options
Nick Mathewson authored
245 if ((p->options|options) & BEV_OPT_DEFER_CALLBACKS) {
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
246 p->writecb_pending = 1;
ae2b84b Replace deferred_cbs with event_callback-based implementation.
Nick Mathewson authored
247 SCHEDULE_DEFERRED(p);
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
248 } else {
249 bufev->writecb(bufev, bufev->cbarg);
250 }
251 }
252
a3172a4 Minor optimizations on bufferevent_trigger options
Nick Mathewson authored
253 #define BEV_TRIG_ALL_OPTS ( \
254 BEV_TRIG_IGNORE_WATERMARKS| \
255 BEV_TRIG_DEFER_CALLBACKS \
256 )
257
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
258 void
61ee18b @mistotebe Add an option to trigger bufferevent I/O callbacks
mistotebe authored
259 bufferevent_trigger(struct bufferevent *bufev, short iotype, int options)
260 {
261 bufferevent_incref_and_lock_(bufev);
a3172a4 Minor optimizations on bufferevent_trigger options
Nick Mathewson authored
262 bufferevent_trigger_nolock_(bufev, iotype, options&BEV_TRIG_ALL_OPTS);
61ee18b @mistotebe Add an option to trigger bufferevent I/O callbacks
mistotebe authored
263 bufferevent_decref_and_unlock_(bufev);
264 }
265
266 void
a7384c7 @mistotebe Add an option to trigger bufferevent event callbacks
mistotebe authored
267 bufferevent_run_eventcb_(struct bufferevent *bufev, short what, int options)
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
268 {
a62283a Always hold a reference to a bufferevent when calling its callbacks.
Nick Mathewson authored
269 /* Requires that we hold the lock and a reference */
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
270 struct bufferevent_private *p =
271 EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
2e8eeea Fix crash bugs when a bufferevent's eventcb is not set.
Nick Mathewson authored
272 if (bufev->errorcb == NULL)
273 return;
a3172a4 Minor optimizations on bufferevent_trigger options
Nick Mathewson authored
274 if ((p->options|options) & BEV_OPT_DEFER_CALLBACKS) {
5232cfa Consistently say "eventcb" instead of "errorcb"
Nick Mathewson authored
275 p->eventcb_pending |= what;
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
276 p->errno_pending = EVUTIL_SOCKET_ERROR();
ae2b84b Replace deferred_cbs with event_callback-based implementation.
Nick Mathewson authored
277 SCHEDULE_DEFERRED(p);
a98a512 Add a generic way for any bufferevent to make its callback deferred
Nick Mathewson authored
278 } else {
279 bufev->errorcb(bufev, what, bufev->cbarg);
280 }
281 }
282
a7384c7 @mistotebe Add an option to trigger bufferevent event callbacks
mistotebe authored
283 void
284 bufferevent_trigger_event(struct bufferevent *bufev, short what, int options)
285 {
286 bufferevent_incref_and_lock_(bufev);
a3172a4 Minor optimizations on bufferevent_trigger options
Nick Mathewson authored
287 bufferevent_run_eventcb_(bufev, what, options&BEV_TRIG_ALL_OPTS);
a7384c7 @mistotebe Add an option to trigger bufferevent event callbacks
mistotebe authored
288 bufferevent_decref_and_unlock_(bufev);
289 }
290
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
291 int
8ac3c4c Have all visible internal function names end with an underscore.
Nick Mathewson authored
292 bufferevent_init_common_(struct bufferevent_private *bufev_private,
1becc4c Refactor new elements of bufferevent into bufferevent_private structure
Nick Mathewson authored
293 struct event_base *base,
294 const struct bufferevent_ops *ops,
295 enum bufferevent_options options)
5908bd7 @provos provided buffered events
provos authored
296 {
1becc4c Refactor new elements of bufferevent into bufferevent_private structure
Nick Mathewson authored
297 struct bufferevent *bufev = &bufev_private->bev;
298
b69d03b Add a constructor for bufferevent_async.
Nick Mathewson authored
299 if (!bufev->input) {
300 if ((bufev->input = evbuffer_new()) == NULL)
301 return -1;
302 }
5908bd7 @provos provided buffered events
provos authored
303
b69d03b Add a constructor for bufferevent_async.
Nick Mathewson authored
304 if (!bufev->output) {
305 if ((bufev->output = evbuffer_new()) == NULL) {
306 evbuffer_free(bufev->input);
307 return -1;
308 }
5908bd7 @provos provided buffered events
provos authored
309 }
310
91039e4 Add reference counts to bufferevents.
Nick Mathewson authored
311 bufev_private->refcnt = 1;
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
312 bufev->ev_base = base;
313
314 /* Disable timeouts. */
315 evutil_timerclear(&bufev->timeout_read);
316 evutil_timerclear(&bufev->timeout_write);
5908bd7 @provos provided buffered events
provos authored
317
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
318 bufev->be_ops = ops;
5908bd7 @provos provided buffered events
provos authored
319
cb9da0b Fix all identifiers with names beginning with underscore.
Nick Mathewson authored
320 bufferevent_ratelim_init_(bufev_private);
998c813 @sorc1 bufferevent: Add functions to set/get max_single_read/write values.
sorc1 authored
321
f296e63 @provos allow setting an event base for bufferevents; from phil oleson
provos authored
322 /*
323 * Set to EV_WRITE so that using bufferevent_write is going to
324 * trigger a callback. Reading needs to be explicitly enabled
325 * because otherwise no data will be available.
326 */
327 bufev->enabled = EV_WRITE;
5908bd7 @provos provided buffered events
provos authored
328
68120d9 Convert event-config.h macros to avoid reserved identifiers
Nick Mathewson authored
329 #ifndef EVENT__DISABLE_THREAD_SUPPORT
915193e Locking support for bufferevents.
Nick Mathewson authored
330 if (options & BEV_OPT_THREADSAFE) {
8ac3c4c Have all visible internal function names end with an underscore.
Nick Mathewson authored
331 if (bufferevent_enable_locking_(bufev, NULL) < 0) {
915193e Locking support for bufferevents.
Nick Mathewson authored
332 /* cleanup */
8398641 @jweyrich Fix infrequent memory leak in bufferevent_init_common().
jweyrich authored
333 evbuffer_free(bufev->input);
334 evbuffer_free(bufev->output);
335 bufev->input = NULL;
336 bufev->output = NULL;
915193e Locking support for bufferevents.
Nick Mathewson authored
337 return -1;
338 }
339 }
340 #endif
a5208fe @fancycode Release locks on bufferevents while executing callbacks
fancycode authored
341 if ((options & (BEV_OPT_DEFER_CALLBACKS|BEV_OPT_UNLOCK_CALLBACKS))
342 == BEV_OPT_UNLOCK_CALLBACKS) {
343 event_warnx("UNLOCK_CALLBACKS requires DEFER_CALLBACKS");
344 return -1;
345 }
61ee18b @mistotebe Add an option to trigger bufferevent I/O callbacks
mistotebe authored
346 if (options & BEV_OPT_UNLOCK_CALLBACKS)
347 event_deferred_cb_init_(
348 &bufev_private->deferred,
349 event_base_get_npriorities(base) / 2,
350 bufferevent_run_deferred_callbacks_unlocked,
351 bufev_private);
352 else
353 event_deferred_cb_init_(
354 &bufev_private->deferred,
355 event_base_get_npriorities(base) / 2,
356 bufferevent_run_deferred_callbacks_locked,
357 bufev_private);
915193e Locking support for bufferevents.
Nick Mathewson authored
358
1becc4c Refactor new elements of bufferevent into bufferevent_private structure
Nick Mathewson authored
359 bufev_private->options = options;
682adc4 @provos support input/output filters for bufferevents
provos authored
360
8ac3c4c Have all visible internal function names end with an underscore.
Nick Mathewson authored
361 evbuffer_set_parent_(bufev->input, bufev);
362 evbuffer_set_parent_(bufev->output, bufev);
d7d1f1d Move responsibility for IOCP callback into bufferevent_async.
Nick Mathewson authored
363
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
364 return 0;
5908bd7 @provos provided buffered events
provos authored
365 }
366
9485ff9 @provos introduce bufferevent_setcb and bufferevent_setfd to allow better manipu...
provos authored
367 void
368 bufferevent_setcb(struct bufferevent *bufev,
83f46e5 Do not use the "evbuffer_" prefix to denote parts of bufferevents.
Nick Mathewson authored
369 bufferevent_data_cb readcb, bufferevent_data_cb writecb,
5232cfa Consistently say "eventcb" instead of "errorcb"
Nick Mathewson authored
370 bufferevent_event_cb eventcb, void *cbarg)
9485ff9 @provos introduce bufferevent_setcb and bufferevent_setfd to allow better manipu...
provos authored
371 {
915193e Locking support for bufferevents.
Nick Mathewson authored
372 BEV_LOCK(bufev);
373
9485ff9 @provos introduce bufferevent_setcb and bufferevent_setfd to allow better manipu...
provos authored
374 bufev->readcb = readcb;
375 bufev->writecb = writecb;
5232cfa Consistently say "eventcb" instead of "errorcb"
Nick Mathewson authored
376 bufev->errorcb = eventcb;
9485ff9 @provos introduce bufferevent_setcb and bufferevent_setfd to allow better manipu...
provos authored
377
378 bufev->cbarg = cbarg;
915193e Locking support for bufferevents.
Nick Mathewson authored
379 BEV_UNLOCK(bufev);
9485ff9 @provos introduce bufferevent_setcb and bufferevent_setfd to allow better manipu...
provos authored
380 }
381
a650394 Add a bufferevent_getcb() to find a bufferevent's current callbacks
Nick Mathewson authored
382 void
383 bufferevent_getcb(struct bufferevent *bufev,
384 bufferevent_data_cb *readcb_ptr,
385 bufferevent_data_cb *writecb_ptr,
386 bufferevent_event_cb *eventcb_ptr,
387 void **cbarg_ptr)
388 {
389 BEV_LOCK(bufev);
390 if (readcb_ptr)
391 *readcb_ptr = bufev->readcb;
392 if (writecb_ptr)
393 *writecb_ptr = bufev->writecb;
394 if (eventcb_ptr)
395 *eventcb_ptr = bufev->errorcb;
396 if (cbarg_ptr)
397 *cbarg_ptr = bufev->cbarg;
398
399 BEV_UNLOCK(bufev);
400 }
401
dd183f7 @provos provide bufferevent_input and bufferevent_output without requiring knowl...
provos authored
402 struct evbuffer *
8acb80b r15551@tombo: nickm | 2008-05-08 14:49:20 -0400
Nick Mathewson authored
403 bufferevent_get_input(struct bufferevent *bufev)
dd183f7 @provos provide bufferevent_input and bufferevent_output without requiring knowl...
provos authored
404 {
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
405 return bufev->input;
dd183f7 @provos provide bufferevent_input and bufferevent_output without requiring knowl...
provos authored
406 }
407
408 struct evbuffer *
8acb80b r15551@tombo: nickm | 2008-05-08 14:49:20 -0400
Nick Mathewson authored
409 bufferevent_get_output(struct bufferevent *bufev)
dd183f7 @provos provide bufferevent_input and bufferevent_output without requiring knowl...
provos authored
410 {
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
411 return bufev->output;
f6c4017 @provos fix a bug in which bufferevent_write_buffer would not schedule a write e...
provos authored
412 }
413
aab49b6 Add a bufferevent_get_base function
Nick Mathewson authored
414 struct event_base *
415 bufferevent_get_base(struct bufferevent *bufev)
416 {
417 return bufev->ev_base;
418 }
419
5908bd7 @provos provided buffered events
provos authored
420 int
060c409 Make the argument to bufferevent_get_priority const
Nick Mathewson authored
421 bufferevent_get_priority(const struct bufferevent *bufev)
bd39554 Add a bufferevent_get_priority() function
Nick Mathewson authored
422 {
423 if (event_initialized(&bufev->ev_read)) {
424 return event_get_priority(&bufev->ev_read);
425 } else {
426 return event_base_get_npriorities(bufev->ev_base) / 2;
427 }
428 }
429
430 int
af6f331 @provos use a const pointer for bufferevent_write
provos authored
431 bufferevent_write(struct bufferevent *bufev, const void *data, size_t size)
5908bd7 @provos provided buffered events
provos authored
432 {
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
433 if (evbuffer_add(bufev->output, data, size) == -1)
682adc4 @provos support input/output filters for bufferevents
provos authored
434 return (-1);
435
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
436 return 0;
5908bd7 @provos provided buffered events
provos authored
437 }
438
439 int
440 bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf)
441 {
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
442 if (evbuffer_add_buffer(bufev->output, buf) == -1)
682adc4 @provos support input/output filters for bufferevents
provos authored
443 return (-1);
9993137 Remove all trailing whitespace in all the source files.
Nick Mathewson authored
444
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
445 return 0;
5908bd7 @provos provided buffered events
provos authored
446 }
447
448 size_t
449 bufferevent_read(struct bufferevent *bufev, void *data, size_t size)
450 {
5c70ea4 @provos improved code for evbuffer; avoids memcpy
provos authored
451 return (evbuffer_remove(bufev->input, data, size));
5908bd7 @provos provided buffered events
provos authored
452 }
453
454 int
89f63b2 @provos add bufferevent_read_buffer function
provos authored
455 bufferevent_read_buffer(struct bufferevent *bufev, struct evbuffer *buf)
456 {
457 return (evbuffer_add_buffer(buf, bufev->input));
458 }
459
460 int
5908bd7 @provos provided buffered events
provos authored
461 bufferevent_enable(struct bufferevent *bufev, short event)
462 {
1becc4c Refactor new elements of bufferevent into bufferevent_private structure
Nick Mathewson authored
463 struct bufferevent_private *bufev_private =
464 EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
465 short impl_events = event;
915193e Locking support for bufferevents.
Nick Mathewson authored
466 int r = 0;
467
cb9da0b Fix all identifiers with names beginning with underscore.
Nick Mathewson authored
468 bufferevent_incref_and_lock_(bufev);
1becc4c Refactor new elements of bufferevent into bufferevent_private structure
Nick Mathewson authored
469 if (bufev_private->read_suspended)
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
470 impl_events &= ~EV_READ;
0d744aa Refactor our 'suspend operation' logic on bufferevents.
Nick Mathewson authored
471 if (bufev_private->write_suspended)
472 impl_events &= ~EV_WRITE;
5908bd7 @provos provided buffered events
provos authored
473
474 bufev->enabled |= event;
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
475
0d744aa Refactor our 'suspend operation' logic on bufferevents.
Nick Mathewson authored
476 if (impl_events && bufev->be_ops->enable(bufev, impl_events) < 0)
915193e Locking support for bufferevents.
Nick Mathewson authored
477 r = -1;
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
478
cb9da0b Fix all identifiers with names beginning with underscore.
Nick Mathewson authored
479 bufferevent_decref_and_unlock_(bufev);
915193e Locking support for bufferevents.
Nick Mathewson authored
480 return r;
5908bd7 @provos provided buffered events
provos authored
481 }
482
ff3f6cd Check more internal event_add() calls for failure
Nick Mathewson authored
483 int
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
484 bufferevent_set_timeouts(struct bufferevent *bufev,
485 const struct timeval *tv_read,
486 const struct timeval *tv_write)
5908bd7 @provos provided buffered events
provos authored
487 {
ff3f6cd Check more internal event_add() calls for failure
Nick Mathewson authored
488 int r = 0;
915193e Locking support for bufferevents.
Nick Mathewson authored
489 BEV_LOCK(bufev);
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
490 if (tv_read) {
491 bufev->timeout_read = *tv_read;
492 } else {
493 evutil_timerclear(&bufev->timeout_read);
5908bd7 @provos provided buffered events
provos authored
494 }
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
495 if (tv_write) {
496 bufev->timeout_write = *tv_write;
497 } else {
498 evutil_timerclear(&bufev->timeout_write);
5908bd7 @provos provided buffered events
provos authored
499 }
500
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
501 if (bufev->be_ops->adj_timeouts)
ff3f6cd Check more internal event_add() calls for failure
Nick Mathewson authored
502 r = bufev->be_ops->adj_timeouts(bufev);
915193e Locking support for bufferevents.
Nick Mathewson authored
503 BEV_UNLOCK(bufev);
ff3f6cd Check more internal event_add() calls for failure
Nick Mathewson authored
504
505 return r;
5908bd7 @provos provided buffered events
provos authored
506 }
507
508
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
509 /* Obsolete; use bufferevent_set_timeouts */
5908bd7 @provos provided buffered events
provos authored
510 void
511 bufferevent_settimeout(struct bufferevent *bufev,
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
512 int timeout_read, int timeout_write)
513 {
514 struct timeval tv_read, tv_write;
515 struct timeval *ptv_read = NULL, *ptv_write = NULL;
fbf01c7 @provos support for low and high watermarks
provos authored
516
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
517 memset(&tv_read, 0, sizeof(tv_read));
518 memset(&tv_write, 0, sizeof(tv_write));
fbf01c7 @provos support for low and high watermarks
provos authored
519
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
520 if (timeout_read) {
521 tv_read.tv_sec = timeout_read;
522 ptv_read = &tv_read;
fbf01c7 @provos support for low and high watermarks
provos authored
523 }
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
524 if (timeout_write) {
525 tv_write.tv_sec = timeout_write;
526 ptv_write = &tv_write;
fbf01c7 @provos support for low and high watermarks
provos authored
527 }
528
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
529 bufferevent_set_timeouts(bufev, ptv_read, ptv_write);
fbf01c7 @provos support for low and high watermarks
provos authored
530 }
f296e63 @provos allow setting an event base for bufferevents; from phil oleson
provos authored
531
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
532
f296e63 @provos allow setting an event base for bufferevents; from phil oleson
provos authored
533 int
8ac3c4c Have all visible internal function names end with an underscore.
Nick Mathewson authored
534 bufferevent_disable_hard_(struct bufferevent *bufev, short event)
5dc5662 @kroki Workaround libevent bug
kroki authored
535 {
536 int r = 0;
537 struct bufferevent_private *bufev_private =
538 EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
539
540 BEV_LOCK(bufev);
541 bufev->enabled &= ~event;
542
543 bufev_private->connecting = 0;
544 if (bufev->be_ops->disable(bufev, event) < 0)
545 r = -1;
546
547 BEV_UNLOCK(bufev);
548 return r;
549 }
550
551 int
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
552 bufferevent_disable(struct bufferevent *bufev, short event)
f296e63 @provos allow setting an event base for bufferevents; from phil oleson
provos authored
553 {
915193e Locking support for bufferevents.
Nick Mathewson authored
554 int r = 0;
555
556 BEV_LOCK(bufev);
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
557 bufev->enabled &= ~event;
9485ff9 @provos introduce bufferevent_setcb and bufferevent_setfd to allow better manipu...
provos authored
558
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
559 if (bufev->be_ops->disable(bufev, event) < 0)
915193e Locking support for bufferevents.
Nick Mathewson authored
560 r = -1;
f296e63 @provos allow setting an event base for bufferevents; from phil oleson
provos authored
561
915193e Locking support for bufferevents.
Nick Mathewson authored
562 BEV_UNLOCK(bufev);
563 return r;
f296e63 @provos allow setting an event base for bufferevents; from phil oleson
provos authored
564 }
682adc4 @provos support input/output filters for bufferevents
provos authored
565
566 /*
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
567 * Sets the water marks
682adc4 @provos support input/output filters for bufferevents
provos authored
568 */
569
570 void
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
571 bufferevent_setwatermark(struct bufferevent *bufev, short events,
572 size_t lowmark, size_t highmark)
682adc4 @provos support input/output filters for bufferevents
provos authored
573 {
1becc4c Refactor new elements of bufferevent into bufferevent_private structure
Nick Mathewson authored
574 struct bufferevent_private *bufev_private =
575 EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
682adc4 @provos support input/output filters for bufferevents
provos authored
576
915193e Locking support for bufferevents.
Nick Mathewson authored
577 BEV_LOCK(bufev);
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
578 if (events & EV_WRITE) {
579 bufev->wm_write.low = lowmark;
580 bufev->wm_write.high = highmark;
682adc4 @provos support input/output filters for bufferevents
provos authored
581 }
582
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
583 if (events & EV_READ) {
584 bufev->wm_read.low = lowmark;
585 bufev->wm_read.high = highmark;
682adc4 @provos support input/output filters for bufferevents
provos authored
586
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
587 if (highmark) {
588 /* There is now a new high-water mark for read.
589 enable the callback if needed, and see if we should
590 suspend/bufferevent_wm_unsuspend. */
591
1becc4c Refactor new elements of bufferevent into bufferevent_private structure
Nick Mathewson authored
592 if (bufev_private->read_watermarks_cb == NULL) {
593 bufev_private->read_watermarks_cb =
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
594 evbuffer_add_cb(bufev->input,
595 bufferevent_inbuf_wm_cb,
596 bufev);
597 }
598 evbuffer_cb_set_flags(bufev->input,
438f9ed Add the abilitity to mark some buffer callbacks as never-deferred.
Nick Mathewson authored
599 bufev_private->read_watermarks_cb,
600 EVBUFFER_CB_ENABLED|EVBUFFER_CB_NODEFER);
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
601
b34e4ac @ufo2243 [Bugfix] fix bufferevent setwatermark suspend_read
ufo2243 authored
602 if (evbuffer_get_length(bufev->input) >= highmark)
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
603 bufferevent_wm_suspend_read(bufev);
a8f6d96 Actually stop using EVBUFFER_LENGTH/DATA, and move them to buffer_compat...
Nick Mathewson authored
604 else if (evbuffer_get_length(bufev->input) < highmark)
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
605 bufferevent_wm_unsuspend_read(bufev);
606 } else {
607 /* There is now no high-water mark for read. */
1becc4c Refactor new elements of bufferevent into bufferevent_private structure
Nick Mathewson authored
608 if (bufev_private->read_watermarks_cb)
bba69e0 New semantics for evbuffer_cb_set_flags().
Nick Mathewson authored
609 evbuffer_cb_clear_flags(bufev->input,
1becc4c Refactor new elements of bufferevent into bufferevent_private structure
Nick Mathewson authored
610 bufev_private->read_watermarks_cb,
bba69e0 New semantics for evbuffer_cb_set_flags().
Nick Mathewson authored
611 EVBUFFER_CB_ENABLED);
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
612 bufferevent_wm_unsuspend_read(bufev);
613 }
682adc4 @provos support input/output filters for bufferevents
provos authored
614 }
915193e Locking support for bufferevents.
Nick Mathewson authored
615 BEV_UNLOCK(bufev);
682adc4 @provos support input/output filters for bufferevents
provos authored
616 }
617
a21e510 @ufo2243 make bufferevent_getwatermark api more robust
ufo2243 authored
618 int
4ce242b @mistotebe Add watermark introspection
mistotebe authored
619 bufferevent_getwatermark(struct bufferevent *bufev, short events,
620 size_t *lowmark, size_t *highmark)
621 {
bd41947 @mistotebe Clarifications in response to merge req. comments
mistotebe authored
622 if (events == EV_WRITE) {
a21e510 @ufo2243 make bufferevent_getwatermark api more robust
ufo2243 authored
623 BEV_LOCK(bufev);
4ce242b @mistotebe Add watermark introspection
mistotebe authored
624 if (lowmark)
625 *lowmark = bufev->wm_write.low;
626 if (highmark)
627 *highmark = bufev->wm_write.high;
a21e510 @ufo2243 make bufferevent_getwatermark api more robust
ufo2243 authored
628 BEV_UNLOCK(bufev);
629 return 0;
4ce242b @mistotebe Add watermark introspection
mistotebe authored
630 }
631
bd41947 @mistotebe Clarifications in response to merge req. comments
mistotebe authored
632 if (events == EV_READ) {
a21e510 @ufo2243 make bufferevent_getwatermark api more robust
ufo2243 authored
633 BEV_LOCK(bufev);
4ce242b @mistotebe Add watermark introspection
mistotebe authored
634 if (lowmark)
635 *lowmark = bufev->wm_read.low;
636 if (highmark)
637 *highmark = bufev->wm_read.high;
a21e510 @ufo2243 make bufferevent_getwatermark api more robust
ufo2243 authored
638 BEV_UNLOCK(bufev);
639 return 0;
4ce242b @mistotebe Add watermark introspection
mistotebe authored
640 }
a21e510 @ufo2243 make bufferevent_getwatermark api more robust
ufo2243 authored
641 return -1;
4ce242b @mistotebe Add watermark introspection
mistotebe authored
642 }
643
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
644 int
645 bufferevent_flush(struct bufferevent *bufev,
646 short iotype,
647 enum bufferevent_flush_mode mode)
682adc4 @provos support input/output filters for bufferevents
provos authored
648 {
915193e Locking support for bufferevents.
Nick Mathewson authored
649 int r = -1;
650 BEV_LOCK(bufev);
e5bbd40 Clean up formatting: use tabs, not 8-spaces, to indent.
Nick Mathewson authored
651 if (bufev->be_ops->flush)
652 r = bufev->be_ops->flush(bufev, iotype, mode);
915193e Locking support for bufferevents.
Nick Mathewson authored
653 BEV_UNLOCK(bufev);
654 return r;
682adc4 @provos support input/output filters for bufferevents
provos authored
655 }
656
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
657 void
cb9da0b Fix all identifiers with names beginning with underscore.
Nick Mathewson authored
658 bufferevent_incref_and_lock_(struct bufferevent *bufev)
a62283a Always hold a reference to a bufferevent when calling its callbacks.
Nick Mathewson authored
659 {
660 struct bufferevent_private *bufev_private =
661 BEV_UPCAST(bufev);
662 BEV_LOCK(bufev);
663 ++bufev_private->refcnt;
664 }
665
f1bc125 Improve robustness for refcounting
Nick Mathewson authored
666 #if 0
667 static void
946b584 Clean up lingering _identifiers.
Nick Mathewson authored
668 bufferevent_transfer_lock_ownership_(struct bufferevent *donor,
f1bc125 Improve robustness for refcounting
Nick Mathewson authored
669 struct bufferevent *recipient)
670 {
671 struct bufferevent_private *d = BEV_UPCAST(donor);
672 struct bufferevent_private *r = BEV_UPCAST(recipient);
673 if (d->lock != r->lock)
674 return;
675 if (r->own_lock)
676 return;
677 if (d->own_lock) {
678 d->own_lock = 0;
679 r->own_lock = 1;
680 }
681 }
682 #endif
683
684 int
cb9da0b Fix all identifiers with names beginning with underscore.
Nick Mathewson authored
685 bufferevent_decref_and_unlock_(struct bufferevent *bufev)
682adc4 @provos support input/output filters for bufferevents
provos authored
686 {
91039e4 Add reference counts to bufferevents.
Nick Mathewson authored
687 struct bufferevent_private *bufev_private =
688 EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
02fbf68 Use finalization feature so bufferevents can avoid deadlocks
Nick Mathewson authored
689 int n_cbs = 0;
690 #define MAX_CBS 16
691 struct event_callback *cbs[MAX_CBS];
91039e4 Add reference counts to bufferevents.
Nick Mathewson authored
692
f1bc125 Improve robustness for refcounting
Nick Mathewson authored
693 EVUTIL_ASSERT(bufev_private->refcnt > 0);
694
91039e4 Add reference counts to bufferevents.
Nick Mathewson authored
695 if (--bufev_private->refcnt) {
696 BEV_UNLOCK(bufev);
f1bc125 Improve robustness for refcounting
Nick Mathewson authored
697 return 0;
91039e4 Add reference counts to bufferevents.
Nick Mathewson authored
698 }
699
02fbf68 Use finalization feature so bufferevents can avoid deadlocks
Nick Mathewson authored
700 if (bufev->be_ops->unlink)
701 bufev->be_ops->unlink(bufev);
702
703 /* Okay, we're out of references. Let's finalize this once all the
704 * callbacks are done running. */
705 cbs[0] = &bufev->ev_read.ev_evcallback;
706 cbs[1] = &bufev->ev_write.ev_evcallback;
707 cbs[2] = &bufev_private->deferred;
708 n_cbs = 3;
709 if (bufev_private->rate_limiting) {
710 struct event *e = &bufev_private->rate_limiting->refill_bucket_event;
711 if (event_initialized(e))
712 cbs[n_cbs++] = &e->ev_evcallback;
713 }
714 n_cbs += evbuffer_get_callbacks_(bufev->input, cbs+n_cbs, MAX_CBS-n_cbs);
715 n_cbs += evbuffer_get_callbacks_(bufev->output, cbs+n_cbs, MAX_CBS-n_cbs);
716
717 event_callback_finalize_many_(bufev->ev_base, n_cbs, cbs,
718 bufferevent_finalize_cb_);
719
720 #undef MAX_CBS
721 BEV_UNLOCK(bufev);
722
723 return 1;
724 }
725
726 static void
727 bufferevent_finalize_cb_(struct event_callback *evcb, void *arg_)
728 {
729 struct bufferevent *bufev = arg_;
730 struct bufferevent *underlying;
731 struct bufferevent_private *bufev_private =
732 EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
733
734 BEV_LOCK(bufev);
a773df5 @fancycode Fix a segfault when freeing SSL bufferevents in an unusual order
fancycode authored
735 underlying = bufferevent_get_underlying(bufev);
736
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
737 /* Clean up the shared info */
738 if (bufev->be_ops->destruct)
739 bufev->be_ops->destruct(bufev);
682adc4 @provos support input/output filters for bufferevents
provos authored
740
d7d1f1d Move responsibility for IOCP callback into bufferevent_async.
Nick Mathewson authored
741 /* XXX what happens if refcnt for these buffers is > 1?
742 * The buffers can share a lock with this bufferevent object,
743 * but the lock might be destroyed below. */
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
744 /* evbuffer will free the callbacks */
745 evbuffer_free(bufev->input);
746 evbuffer_free(bufev->output);
682adc4 @provos support input/output filters for bufferevents
provos authored
747
737c9cd Rate-limiting for bufferevents; group and individual limits are supporte...
Nick Mathewson authored
748 if (bufev_private->rate_limiting) {
749 if (bufev_private->rate_limiting->group)
8ac3c4c Have all visible internal function names end with an underscore.
Nick Mathewson authored
750 bufferevent_remove_from_rate_limit_group_internal_(bufev,0);
737c9cd Rate-limiting for bufferevents; group and individual limits are supporte...
Nick Mathewson authored
751 mm_free(bufev_private->rate_limiting);
752 bufev_private->rate_limiting = NULL;
753 }
754
a19b4a0 Call event_debug_unassign on internal events
Nick Mathewson authored
755
91039e4 Add reference counts to bufferevents.
Nick Mathewson authored
756 BEV_UNLOCK(bufev);
02fbf68 Use finalization feature so bufferevents can avoid deadlocks
Nick Mathewson authored
757
91039e4 Add reference counts to bufferevents.
Nick Mathewson authored
758 if (bufev_private->own_lock)
347952f Revise the locking API: deprecate the old locking callbacks and add tryl...
Nick Mathewson authored
759 EVTHREAD_FREE_LOCK(bufev_private->lock,
760 EVTHREAD_LOCKTYPE_RECURSIVE);
91039e4 Add reference counts to bufferevents.
Nick Mathewson authored
761
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
762 /* Free the actual allocated memory. */
0cf1431 Avoid an (untriggerable so far) crash bug in bufferevent_free()
Nick Mathewson authored
763 mm_free(((char*)bufev) - bufev->be_ops->mem_offset);
a773df5 @fancycode Fix a segfault when freeing SSL bufferevents in an unusual order
fancycode authored
764
f1bc125 Improve robustness for refcounting
Nick Mathewson authored
765 /* Release the reference to underlying now that we no longer need the
766 * reference to it. We wait this long mainly in case our lock is
767 * shared with underlying.
768 *
769 * The 'destruct' function will also drop a reference to underlying
770 * if BEV_OPT_CLOSE_ON_FREE is set.
771 *
a773df5 @fancycode Fix a segfault when freeing SSL bufferevents in an unusual order
fancycode authored
772 * XXX Should we/can we just refcount evbuffer/bufferevent locks?
773 * It would probably save us some headaches.
774 */
775 if (underlying)
8ac3c4c Have all visible internal function names end with an underscore.
Nick Mathewson authored
776 bufferevent_decref_(underlying);
91039e4 Add reference counts to bufferevents.
Nick Mathewson authored
777 }
778
f1bc125 Improve robustness for refcounting
Nick Mathewson authored
779 int
8ac3c4c Have all visible internal function names end with an underscore.
Nick Mathewson authored
780 bufferevent_decref_(struct bufferevent *bufev)
b2fbeb3 Make bufferevent_free() clear all callbacks immediately.
Nick Mathewson authored
781 {
782 BEV_LOCK(bufev);
cb9da0b Fix all identifiers with names beginning with underscore.
Nick Mathewson authored
783 return bufferevent_decref_and_unlock_(bufev);
b2fbeb3 Make bufferevent_free() clear all callbacks immediately.
Nick Mathewson authored
784 }
785
786 void
91039e4 Add reference counts to bufferevents.
Nick Mathewson authored
787 bufferevent_free(struct bufferevent *bufev)
788 {
789 BEV_LOCK(bufev);
b2fbeb3 Make bufferevent_free() clear all callbacks immediately.
Nick Mathewson authored
790 bufferevent_setcb(bufev, NULL, NULL, NULL, NULL);
cb9da0b Fix all identifiers with names beginning with underscore.
Nick Mathewson authored
791 bufferevent_cancel_all_(bufev);
792 bufferevent_decref_and_unlock_(bufev);
91039e4 Add reference counts to bufferevents.
Nick Mathewson authored
793 }
794
795 void
8ac3c4c Have all visible internal function names end with an underscore.
Nick Mathewson authored
796 bufferevent_incref_(struct bufferevent *bufev)
91039e4 Add reference counts to bufferevents.
Nick Mathewson authored
797 {
798 struct bufferevent_private *bufev_private =
799 EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
800
801 BEV_LOCK(bufev);
802 ++bufev_private->refcnt;
803 BEV_UNLOCK(bufev);
915193e Locking support for bufferevents.
Nick Mathewson authored
804 }
805
806 int
8ac3c4c Have all visible internal function names end with an underscore.
Nick Mathewson authored
807 bufferevent_enable_locking_(struct bufferevent *bufev, void *lock)
915193e Locking support for bufferevents.
Nick Mathewson authored
808 {
68120d9 Convert event-config.h macros to avoid reserved identifiers
Nick Mathewson authored
809 #ifdef EVENT__DISABLE_THREAD_SUPPORT
915193e Locking support for bufferevents.
Nick Mathewson authored
810 return -1;
811 #else
709c21c Bufferevent support for openssl.
Nick Mathewson authored
812 struct bufferevent *underlying;
813
915193e Locking support for bufferevents.
Nick Mathewson authored
814 if (BEV_UPCAST(bufev)->lock)
815 return -1;
709c21c Bufferevent support for openssl.
Nick Mathewson authored
816 underlying = bufferevent_get_underlying(bufev);
915193e Locking support for bufferevents.
Nick Mathewson authored
817
709c21c Bufferevent support for openssl.
Nick Mathewson authored
818 if (!lock && underlying && BEV_UPCAST(underlying)->lock) {
819 lock = BEV_UPCAST(underlying)->lock;
820 BEV_UPCAST(bufev)->lock = lock;
821 BEV_UPCAST(bufev)->own_lock = 0;
822 } else if (!lock) {
347952f Revise the locking API: deprecate the old locking callbacks and add tryl...
Nick Mathewson authored
823 EVTHREAD_ALLOC_LOCK(lock, EVTHREAD_LOCKTYPE_RECURSIVE);
915193e Locking support for bufferevents.
Nick Mathewson authored
824 if (!lock)
825 return -1;
826 BEV_UPCAST(bufev)->lock = lock;
827 BEV_UPCAST(bufev)->own_lock = 1;
828 } else {
829 BEV_UPCAST(bufev)->lock = lock;
830 BEV_UPCAST(bufev)->own_lock = 0;
831 }
832 evbuffer_enable_locking(bufev->input, lock);
833 evbuffer_enable_locking(bufev->output, lock);
834
709c21c Bufferevent support for openssl.
Nick Mathewson authored
835 if (underlying && !BEV_UPCAST(underlying)->lock)
8ac3c4c Have all visible internal function names end with an underscore.
Nick Mathewson authored
836 bufferevent_enable_locking_(underlying, lock);
709c21c Bufferevent support for openssl.
Nick Mathewson authored
837
915193e Locking support for bufferevents.
Nick Mathewson authored
838 return 0;
839 #endif
682adc4 @provos support input/output filters for bufferevents
provos authored
840 }
ea4b872 checkpoint work on big bufferevent refactoring
Nick Mathewson authored
841
31d89f2 Add a "ctrl" mechanism to bufferevents for property access.
Nick Mathewson authored
842 int
843 bufferevent_setfd(struct bufferevent *bev, evutil_socket_t fd)
844 {
845 union bufferevent_ctrl_data d;
846 int res = -1;
847 d.fd = fd;
848 BEV_LOCK(bev);
849 if (bev->be_ops->ctrl)
850 res = bev->be_ops->ctrl(bev, BEV_CTRL_SET_FD, &d);
851 BEV_UNLOCK(bev);
852 return res;
853 }
854
855 evutil_socket_t
856 bufferevent_getfd(struct bufferevent *bev)
857 {
858 union bufferevent_ctrl_data d;
859 int res = -1;
860 d.fd = -1;
861 BEV_LOCK(bev);
862 if (bev->be_ops->ctrl)
863 res = bev->be_ops->ctrl(bev, BEV_CTRL_GET_FD, &d);
864 BEV_UNLOCK(bev);
865 return (res<0) ? -1 : d.fd;
866 }
867
31db8a0 Fix a double close() bug in evhttp when the underlying bufferevent uses ...
Maxime Henrion authored
868 enum bufferevent_options
869 bufferevent_get_options_(struct bufferevent *bev)
870 {
871 struct bufferevent_private *bev_p =
872 EVUTIL_UPCAST(bev, struct bufferevent_private, bev);
dbc9cd4 Fix locking in bufferevent_get_options_().
Maxime Henrion authored
873 enum bufferevent_options options;
31db8a0 Fix a double close() bug in evhttp when the underlying bufferevent uses ...
Maxime Henrion authored
874
875 BEV_LOCK(bev);
dbc9cd4 Fix locking in bufferevent_get_options_().
Maxime Henrion authored
876 options = bev_p->options;
31db8a0 Fix a double close() bug in evhttp when the underlying bufferevent uses ...
Maxime Henrion authored
877 BEV_UNLOCK(bev);
dbc9cd4 Fix locking in bufferevent_get_options_().
Maxime Henrion authored
878 return options;
31db8a0 Fix a double close() bug in evhttp when the underlying bufferevent uses ...
Maxime Henrion authored
879 }
880
881
e6af35d Correctly terminate IO on an async bufferevent on bufferevent_free
Nick Mathewson authored
882 static void
cb9da0b Fix all identifiers with names beginning with underscore.
Nick Mathewson authored
883 bufferevent_cancel_all_(struct bufferevent *bev)
e6af35d Correctly terminate IO on an async bufferevent on bufferevent_free
Nick Mathewson authored
884 {
885 union bufferevent_ctrl_data d;
886 memset(&d, 0, sizeof(d));
887 BEV_LOCK(bev);
888 if (bev->be_ops->ctrl)
889 bev->be_ops->ctrl(bev, BEV_CTRL_CANCEL_ALL, &d);
890 BEV_UNLOCK(bev);
891 }
892
7c688dd New function to expose bufferevent.enabled
Nick Mathewson authored
893 short
894 bufferevent_get_enabled(struct bufferevent *bufev)
895 {
896 short r;
897 BEV_LOCK(bufev);
898 r = bufev->enabled;
899 BEV_UNLOCK(bufev);
900 return r;
901 }
902
31d89f2 Add a "ctrl" mechanism to bufferevents for property access.
Nick Mathewson authored
903 struct bufferevent *
904 bufferevent_get_underlying(struct bufferevent *bev)
905 {
906 union bufferevent_ctrl_data d;
907 int res = -1;
908 d.ptr = NULL;
909 BEV_LOCK(bev);
910 if (bev->be_ops->ctrl)
911 res = bev->be_ops->ctrl(bev, BEV_CTRL_GET_UNDERLYING, &d);
912 BEV_UNLOCK(bev);
913 return (res<0) ? NULL : d.ptr;
914 }
34574db Add a generic mechanism to implement timeouts in bufferevents.
Nick Mathewson authored
915
916 static void
917 bufferevent_generic_read_timeout_cb(evutil_socket_t fd, short event, void *ctx)
918 {
919 struct bufferevent *bev = ctx;
cb9da0b Fix all identifiers with names beginning with underscore.
Nick Mathewson authored
920 bufferevent_incref_and_lock_(bev);
d328829 Provide consistent, tested semantics for bufferevent timeouts
Nick Mathewson authored
921 bufferevent_disable(bev, EV_READ);
a7384c7 @mistotebe Add an option to trigger bufferevent event callbacks
mistotebe authored
922 bufferevent_run_eventcb_(bev, BEV_EVENT_TIMEOUT|BEV_EVENT_READING, 0);
cb9da0b Fix all identifiers with names beginning with underscore.
Nick Mathewson authored
923 bufferevent_decref_and_unlock_(bev);
34574db Add a generic mechanism to implement timeouts in bufferevents.
Nick Mathewson authored
924 }
925 static void
926 bufferevent_generic_write_timeout_cb(evutil_socket_t fd, short event, void *ctx)
927 {
928 struct bufferevent *bev = ctx;
cb9da0b