1*663afb9bSAndroid Build Coastguard Worker /*
2*663afb9bSAndroid Build Coastguard Worker * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
3*663afb9bSAndroid Build Coastguard Worker *
4*663afb9bSAndroid Build Coastguard Worker * All rights reserved.
5*663afb9bSAndroid Build Coastguard Worker *
6*663afb9bSAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
7*663afb9bSAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions
8*663afb9bSAndroid Build Coastguard Worker * are met:
9*663afb9bSAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright
10*663afb9bSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
11*663afb9bSAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
12*663afb9bSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the
13*663afb9bSAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution.
14*663afb9bSAndroid Build Coastguard Worker * 3. The name of the author may not be used to endorse or promote products
15*663afb9bSAndroid Build Coastguard Worker * derived from this software without specific prior written permission.
16*663afb9bSAndroid Build Coastguard Worker *
17*663afb9bSAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18*663afb9bSAndroid Build Coastguard Worker * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19*663afb9bSAndroid Build Coastguard Worker * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20*663afb9bSAndroid Build Coastguard Worker * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21*663afb9bSAndroid Build Coastguard Worker * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22*663afb9bSAndroid Build Coastguard Worker * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23*663afb9bSAndroid Build Coastguard Worker * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24*663afb9bSAndroid Build Coastguard Worker * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25*663afb9bSAndroid Build Coastguard Worker * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26*663afb9bSAndroid Build Coastguard Worker * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*663afb9bSAndroid Build Coastguard Worker */
28*663afb9bSAndroid Build Coastguard Worker
29*663afb9bSAndroid Build Coastguard Worker #include "event2/event-config.h"
30*663afb9bSAndroid Build Coastguard Worker #include "evconfig-private.h"
31*663afb9bSAndroid Build Coastguard Worker
32*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_SYS_TIME_H
33*663afb9bSAndroid Build Coastguard Worker #include <sys/time.h>
34*663afb9bSAndroid Build Coastguard Worker #endif
35*663afb9bSAndroid Build Coastguard Worker
36*663afb9bSAndroid Build Coastguard Worker #include <errno.h>
37*663afb9bSAndroid Build Coastguard Worker #include <stdio.h>
38*663afb9bSAndroid Build Coastguard Worker #include <stdlib.h>
39*663afb9bSAndroid Build Coastguard Worker #include <string.h>
40*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_STDARG_H
41*663afb9bSAndroid Build Coastguard Worker #include <stdarg.h>
42*663afb9bSAndroid Build Coastguard Worker #endif
43*663afb9bSAndroid Build Coastguard Worker #ifdef EVENT__HAVE_UNISTD_H
44*663afb9bSAndroid Build Coastguard Worker #include <unistd.h>
45*663afb9bSAndroid Build Coastguard Worker #endif
46*663afb9bSAndroid Build Coastguard Worker
47*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
48*663afb9bSAndroid Build Coastguard Worker #include <winsock2.h>
49*663afb9bSAndroid Build Coastguard Worker #include <winerror.h>
50*663afb9bSAndroid Build Coastguard Worker #include <ws2tcpip.h>
51*663afb9bSAndroid Build Coastguard Worker #endif
52*663afb9bSAndroid Build Coastguard Worker
53*663afb9bSAndroid Build Coastguard Worker #include <sys/queue.h>
54*663afb9bSAndroid Build Coastguard Worker
55*663afb9bSAndroid Build Coastguard Worker #include "event2/util.h"
56*663afb9bSAndroid Build Coastguard Worker #include "event2/bufferevent.h"
57*663afb9bSAndroid Build Coastguard Worker #include "event2/buffer.h"
58*663afb9bSAndroid Build Coastguard Worker #include "event2/bufferevent_struct.h"
59*663afb9bSAndroid Build Coastguard Worker #include "event2/event.h"
60*663afb9bSAndroid Build Coastguard Worker #include "event2/util.h"
61*663afb9bSAndroid Build Coastguard Worker #include "event-internal.h"
62*663afb9bSAndroid Build Coastguard Worker #include "log-internal.h"
63*663afb9bSAndroid Build Coastguard Worker #include "mm-internal.h"
64*663afb9bSAndroid Build Coastguard Worker #include "bufferevent-internal.h"
65*663afb9bSAndroid Build Coastguard Worker #include "util-internal.h"
66*663afb9bSAndroid Build Coastguard Worker #include "iocp-internal.h"
67*663afb9bSAndroid Build Coastguard Worker
68*663afb9bSAndroid Build Coastguard Worker #ifndef SO_UPDATE_CONNECT_CONTEXT
69*663afb9bSAndroid Build Coastguard Worker /* Mingw is sometimes missing this */
70*663afb9bSAndroid Build Coastguard Worker #define SO_UPDATE_CONNECT_CONTEXT 0x7010
71*663afb9bSAndroid Build Coastguard Worker #endif
72*663afb9bSAndroid Build Coastguard Worker
73*663afb9bSAndroid Build Coastguard Worker /* prototypes */
74*663afb9bSAndroid Build Coastguard Worker static int be_async_enable(struct bufferevent *, short);
75*663afb9bSAndroid Build Coastguard Worker static int be_async_disable(struct bufferevent *, short);
76*663afb9bSAndroid Build Coastguard Worker static void be_async_destruct(struct bufferevent *);
77*663afb9bSAndroid Build Coastguard Worker static int be_async_flush(struct bufferevent *, short, enum bufferevent_flush_mode);
78*663afb9bSAndroid Build Coastguard Worker static int be_async_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
79*663afb9bSAndroid Build Coastguard Worker
80*663afb9bSAndroid Build Coastguard Worker struct bufferevent_async {
81*663afb9bSAndroid Build Coastguard Worker struct bufferevent_private bev;
82*663afb9bSAndroid Build Coastguard Worker struct event_overlapped connect_overlapped;
83*663afb9bSAndroid Build Coastguard Worker struct event_overlapped read_overlapped;
84*663afb9bSAndroid Build Coastguard Worker struct event_overlapped write_overlapped;
85*663afb9bSAndroid Build Coastguard Worker size_t read_in_progress;
86*663afb9bSAndroid Build Coastguard Worker size_t write_in_progress;
87*663afb9bSAndroid Build Coastguard Worker unsigned ok : 1;
88*663afb9bSAndroid Build Coastguard Worker unsigned read_added : 1;
89*663afb9bSAndroid Build Coastguard Worker unsigned write_added : 1;
90*663afb9bSAndroid Build Coastguard Worker };
91*663afb9bSAndroid Build Coastguard Worker
92*663afb9bSAndroid Build Coastguard Worker const struct bufferevent_ops bufferevent_ops_async = {
93*663afb9bSAndroid Build Coastguard Worker "socket_async",
94*663afb9bSAndroid Build Coastguard Worker evutil_offsetof(struct bufferevent_async, bev.bev),
95*663afb9bSAndroid Build Coastguard Worker be_async_enable,
96*663afb9bSAndroid Build Coastguard Worker be_async_disable,
97*663afb9bSAndroid Build Coastguard Worker NULL, /* Unlink */
98*663afb9bSAndroid Build Coastguard Worker be_async_destruct,
99*663afb9bSAndroid Build Coastguard Worker bufferevent_generic_adj_timeouts_,
100*663afb9bSAndroid Build Coastguard Worker be_async_flush,
101*663afb9bSAndroid Build Coastguard Worker be_async_ctrl,
102*663afb9bSAndroid Build Coastguard Worker };
103*663afb9bSAndroid Build Coastguard Worker
104*663afb9bSAndroid Build Coastguard Worker static inline void
be_async_run_eventcb(struct bufferevent * bev,short what,int options)105*663afb9bSAndroid Build Coastguard Worker be_async_run_eventcb(struct bufferevent *bev, short what, int options)
106*663afb9bSAndroid Build Coastguard Worker { bufferevent_run_eventcb_(bev, what, options|BEV_TRIG_DEFER_CALLBACKS); }
107*663afb9bSAndroid Build Coastguard Worker
108*663afb9bSAndroid Build Coastguard Worker static inline void
be_async_trigger_nolock(struct bufferevent * bev,short what,int options)109*663afb9bSAndroid Build Coastguard Worker be_async_trigger_nolock(struct bufferevent *bev, short what, int options)
110*663afb9bSAndroid Build Coastguard Worker { bufferevent_trigger_nolock_(bev, what, options|BEV_TRIG_DEFER_CALLBACKS); }
111*663afb9bSAndroid Build Coastguard Worker
112*663afb9bSAndroid Build Coastguard Worker static inline int
fatal_error(int err)113*663afb9bSAndroid Build Coastguard Worker fatal_error(int err)
114*663afb9bSAndroid Build Coastguard Worker {
115*663afb9bSAndroid Build Coastguard Worker switch (err) {
116*663afb9bSAndroid Build Coastguard Worker /* We may have already associated this fd with a port.
117*663afb9bSAndroid Build Coastguard Worker * Let's hope it's this port, and that the error code
118*663afb9bSAndroid Build Coastguard Worker * for doing this neer changes. */
119*663afb9bSAndroid Build Coastguard Worker case ERROR_INVALID_PARAMETER:
120*663afb9bSAndroid Build Coastguard Worker return 0;
121*663afb9bSAndroid Build Coastguard Worker }
122*663afb9bSAndroid Build Coastguard Worker return 1;
123*663afb9bSAndroid Build Coastguard Worker }
124*663afb9bSAndroid Build Coastguard Worker
125*663afb9bSAndroid Build Coastguard Worker static inline struct bufferevent_async *
upcast(struct bufferevent * bev)126*663afb9bSAndroid Build Coastguard Worker upcast(struct bufferevent *bev)
127*663afb9bSAndroid Build Coastguard Worker {
128*663afb9bSAndroid Build Coastguard Worker struct bufferevent_async *bev_a;
129*663afb9bSAndroid Build Coastguard Worker if (!BEV_IS_ASYNC(bev))
130*663afb9bSAndroid Build Coastguard Worker return NULL;
131*663afb9bSAndroid Build Coastguard Worker bev_a = EVUTIL_UPCAST(bev, struct bufferevent_async, bev.bev);
132*663afb9bSAndroid Build Coastguard Worker return bev_a;
133*663afb9bSAndroid Build Coastguard Worker }
134*663afb9bSAndroid Build Coastguard Worker
135*663afb9bSAndroid Build Coastguard Worker static inline struct bufferevent_async *
upcast_connect(struct event_overlapped * eo)136*663afb9bSAndroid Build Coastguard Worker upcast_connect(struct event_overlapped *eo)
137*663afb9bSAndroid Build Coastguard Worker {
138*663afb9bSAndroid Build Coastguard Worker struct bufferevent_async *bev_a;
139*663afb9bSAndroid Build Coastguard Worker bev_a = EVUTIL_UPCAST(eo, struct bufferevent_async, connect_overlapped);
140*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(BEV_IS_ASYNC(&bev_a->bev.bev));
141*663afb9bSAndroid Build Coastguard Worker return bev_a;
142*663afb9bSAndroid Build Coastguard Worker }
143*663afb9bSAndroid Build Coastguard Worker
144*663afb9bSAndroid Build Coastguard Worker static inline struct bufferevent_async *
upcast_read(struct event_overlapped * eo)145*663afb9bSAndroid Build Coastguard Worker upcast_read(struct event_overlapped *eo)
146*663afb9bSAndroid Build Coastguard Worker {
147*663afb9bSAndroid Build Coastguard Worker struct bufferevent_async *bev_a;
148*663afb9bSAndroid Build Coastguard Worker bev_a = EVUTIL_UPCAST(eo, struct bufferevent_async, read_overlapped);
149*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(BEV_IS_ASYNC(&bev_a->bev.bev));
150*663afb9bSAndroid Build Coastguard Worker return bev_a;
151*663afb9bSAndroid Build Coastguard Worker }
152*663afb9bSAndroid Build Coastguard Worker
153*663afb9bSAndroid Build Coastguard Worker static inline struct bufferevent_async *
upcast_write(struct event_overlapped * eo)154*663afb9bSAndroid Build Coastguard Worker upcast_write(struct event_overlapped *eo)
155*663afb9bSAndroid Build Coastguard Worker {
156*663afb9bSAndroid Build Coastguard Worker struct bufferevent_async *bev_a;
157*663afb9bSAndroid Build Coastguard Worker bev_a = EVUTIL_UPCAST(eo, struct bufferevent_async, write_overlapped);
158*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(BEV_IS_ASYNC(&bev_a->bev.bev));
159*663afb9bSAndroid Build Coastguard Worker return bev_a;
160*663afb9bSAndroid Build Coastguard Worker }
161*663afb9bSAndroid Build Coastguard Worker
162*663afb9bSAndroid Build Coastguard Worker static void
bev_async_del_write(struct bufferevent_async * beva)163*663afb9bSAndroid Build Coastguard Worker bev_async_del_write(struct bufferevent_async *beva)
164*663afb9bSAndroid Build Coastguard Worker {
165*663afb9bSAndroid Build Coastguard Worker struct bufferevent *bev = &beva->bev.bev;
166*663afb9bSAndroid Build Coastguard Worker
167*663afb9bSAndroid Build Coastguard Worker if (beva->write_added) {
168*663afb9bSAndroid Build Coastguard Worker beva->write_added = 0;
169*663afb9bSAndroid Build Coastguard Worker event_base_del_virtual_(bev->ev_base);
170*663afb9bSAndroid Build Coastguard Worker }
171*663afb9bSAndroid Build Coastguard Worker }
172*663afb9bSAndroid Build Coastguard Worker
173*663afb9bSAndroid Build Coastguard Worker static void
bev_async_del_read(struct bufferevent_async * beva)174*663afb9bSAndroid Build Coastguard Worker bev_async_del_read(struct bufferevent_async *beva)
175*663afb9bSAndroid Build Coastguard Worker {
176*663afb9bSAndroid Build Coastguard Worker struct bufferevent *bev = &beva->bev.bev;
177*663afb9bSAndroid Build Coastguard Worker
178*663afb9bSAndroid Build Coastguard Worker if (beva->read_added) {
179*663afb9bSAndroid Build Coastguard Worker beva->read_added = 0;
180*663afb9bSAndroid Build Coastguard Worker event_base_del_virtual_(bev->ev_base);
181*663afb9bSAndroid Build Coastguard Worker }
182*663afb9bSAndroid Build Coastguard Worker }
183*663afb9bSAndroid Build Coastguard Worker
184*663afb9bSAndroid Build Coastguard Worker static void
bev_async_add_write(struct bufferevent_async * beva)185*663afb9bSAndroid Build Coastguard Worker bev_async_add_write(struct bufferevent_async *beva)
186*663afb9bSAndroid Build Coastguard Worker {
187*663afb9bSAndroid Build Coastguard Worker struct bufferevent *bev = &beva->bev.bev;
188*663afb9bSAndroid Build Coastguard Worker
189*663afb9bSAndroid Build Coastguard Worker if (!beva->write_added) {
190*663afb9bSAndroid Build Coastguard Worker beva->write_added = 1;
191*663afb9bSAndroid Build Coastguard Worker event_base_add_virtual_(bev->ev_base);
192*663afb9bSAndroid Build Coastguard Worker }
193*663afb9bSAndroid Build Coastguard Worker }
194*663afb9bSAndroid Build Coastguard Worker
195*663afb9bSAndroid Build Coastguard Worker static void
bev_async_add_read(struct bufferevent_async * beva)196*663afb9bSAndroid Build Coastguard Worker bev_async_add_read(struct bufferevent_async *beva)
197*663afb9bSAndroid Build Coastguard Worker {
198*663afb9bSAndroid Build Coastguard Worker struct bufferevent *bev = &beva->bev.bev;
199*663afb9bSAndroid Build Coastguard Worker
200*663afb9bSAndroid Build Coastguard Worker if (!beva->read_added) {
201*663afb9bSAndroid Build Coastguard Worker beva->read_added = 1;
202*663afb9bSAndroid Build Coastguard Worker event_base_add_virtual_(bev->ev_base);
203*663afb9bSAndroid Build Coastguard Worker }
204*663afb9bSAndroid Build Coastguard Worker }
205*663afb9bSAndroid Build Coastguard Worker
206*663afb9bSAndroid Build Coastguard Worker static void
bev_async_consider_writing(struct bufferevent_async * beva)207*663afb9bSAndroid Build Coastguard Worker bev_async_consider_writing(struct bufferevent_async *beva)
208*663afb9bSAndroid Build Coastguard Worker {
209*663afb9bSAndroid Build Coastguard Worker size_t at_most;
210*663afb9bSAndroid Build Coastguard Worker int limit;
211*663afb9bSAndroid Build Coastguard Worker struct bufferevent *bev = &beva->bev.bev;
212*663afb9bSAndroid Build Coastguard Worker
213*663afb9bSAndroid Build Coastguard Worker /* Don't write if there's a write in progress, or we do not
214*663afb9bSAndroid Build Coastguard Worker * want to write, or when there's nothing left to write. */
215*663afb9bSAndroid Build Coastguard Worker if (beva->write_in_progress || beva->bev.connecting)
216*663afb9bSAndroid Build Coastguard Worker return;
217*663afb9bSAndroid Build Coastguard Worker if (!beva->ok || !(bev->enabled&EV_WRITE) ||
218*663afb9bSAndroid Build Coastguard Worker !evbuffer_get_length(bev->output)) {
219*663afb9bSAndroid Build Coastguard Worker bev_async_del_write(beva);
220*663afb9bSAndroid Build Coastguard Worker return;
221*663afb9bSAndroid Build Coastguard Worker }
222*663afb9bSAndroid Build Coastguard Worker
223*663afb9bSAndroid Build Coastguard Worker at_most = evbuffer_get_length(bev->output);
224*663afb9bSAndroid Build Coastguard Worker
225*663afb9bSAndroid Build Coastguard Worker /* This is safe so long as bufferevent_get_write_max never returns
226*663afb9bSAndroid Build Coastguard Worker * more than INT_MAX. That's true for now. XXXX */
227*663afb9bSAndroid Build Coastguard Worker limit = (int)bufferevent_get_write_max_(&beva->bev);
228*663afb9bSAndroid Build Coastguard Worker if (at_most >= (size_t)limit && limit >= 0)
229*663afb9bSAndroid Build Coastguard Worker at_most = limit;
230*663afb9bSAndroid Build Coastguard Worker
231*663afb9bSAndroid Build Coastguard Worker if (beva->bev.write_suspended) {
232*663afb9bSAndroid Build Coastguard Worker bev_async_del_write(beva);
233*663afb9bSAndroid Build Coastguard Worker return;
234*663afb9bSAndroid Build Coastguard Worker }
235*663afb9bSAndroid Build Coastguard Worker
236*663afb9bSAndroid Build Coastguard Worker /* XXXX doesn't respect low-water mark very well. */
237*663afb9bSAndroid Build Coastguard Worker bufferevent_incref_(bev);
238*663afb9bSAndroid Build Coastguard Worker if (evbuffer_launch_write_(bev->output, at_most,
239*663afb9bSAndroid Build Coastguard Worker &beva->write_overlapped)) {
240*663afb9bSAndroid Build Coastguard Worker bufferevent_decref_(bev);
241*663afb9bSAndroid Build Coastguard Worker beva->ok = 0;
242*663afb9bSAndroid Build Coastguard Worker be_async_run_eventcb(bev, BEV_EVENT_ERROR, 0);
243*663afb9bSAndroid Build Coastguard Worker } else {
244*663afb9bSAndroid Build Coastguard Worker beva->write_in_progress = at_most;
245*663afb9bSAndroid Build Coastguard Worker bufferevent_decrement_write_buckets_(&beva->bev, at_most);
246*663afb9bSAndroid Build Coastguard Worker bev_async_add_write(beva);
247*663afb9bSAndroid Build Coastguard Worker }
248*663afb9bSAndroid Build Coastguard Worker }
249*663afb9bSAndroid Build Coastguard Worker
250*663afb9bSAndroid Build Coastguard Worker static void
bev_async_consider_reading(struct bufferevent_async * beva)251*663afb9bSAndroid Build Coastguard Worker bev_async_consider_reading(struct bufferevent_async *beva)
252*663afb9bSAndroid Build Coastguard Worker {
253*663afb9bSAndroid Build Coastguard Worker size_t cur_size;
254*663afb9bSAndroid Build Coastguard Worker size_t read_high;
255*663afb9bSAndroid Build Coastguard Worker size_t at_most;
256*663afb9bSAndroid Build Coastguard Worker int limit;
257*663afb9bSAndroid Build Coastguard Worker struct bufferevent *bev = &beva->bev.bev;
258*663afb9bSAndroid Build Coastguard Worker
259*663afb9bSAndroid Build Coastguard Worker /* Don't read if there is a read in progress, or we do not
260*663afb9bSAndroid Build Coastguard Worker * want to read. */
261*663afb9bSAndroid Build Coastguard Worker if (beva->read_in_progress || beva->bev.connecting)
262*663afb9bSAndroid Build Coastguard Worker return;
263*663afb9bSAndroid Build Coastguard Worker if (!beva->ok || !(bev->enabled&EV_READ)) {
264*663afb9bSAndroid Build Coastguard Worker bev_async_del_read(beva);
265*663afb9bSAndroid Build Coastguard Worker return;
266*663afb9bSAndroid Build Coastguard Worker }
267*663afb9bSAndroid Build Coastguard Worker
268*663afb9bSAndroid Build Coastguard Worker /* Don't read if we're full */
269*663afb9bSAndroid Build Coastguard Worker cur_size = evbuffer_get_length(bev->input);
270*663afb9bSAndroid Build Coastguard Worker read_high = bev->wm_read.high;
271*663afb9bSAndroid Build Coastguard Worker if (read_high) {
272*663afb9bSAndroid Build Coastguard Worker if (cur_size >= read_high) {
273*663afb9bSAndroid Build Coastguard Worker bev_async_del_read(beva);
274*663afb9bSAndroid Build Coastguard Worker return;
275*663afb9bSAndroid Build Coastguard Worker }
276*663afb9bSAndroid Build Coastguard Worker at_most = read_high - cur_size;
277*663afb9bSAndroid Build Coastguard Worker } else {
278*663afb9bSAndroid Build Coastguard Worker at_most = 16384; /* FIXME totally magic. */
279*663afb9bSAndroid Build Coastguard Worker }
280*663afb9bSAndroid Build Coastguard Worker
281*663afb9bSAndroid Build Coastguard Worker /* XXXX This over-commits. */
282*663afb9bSAndroid Build Coastguard Worker /* XXXX see also not above on cast on bufferevent_get_write_max_() */
283*663afb9bSAndroid Build Coastguard Worker limit = (int)bufferevent_get_read_max_(&beva->bev);
284*663afb9bSAndroid Build Coastguard Worker if (at_most >= (size_t)limit && limit >= 0)
285*663afb9bSAndroid Build Coastguard Worker at_most = limit;
286*663afb9bSAndroid Build Coastguard Worker
287*663afb9bSAndroid Build Coastguard Worker if (beva->bev.read_suspended) {
288*663afb9bSAndroid Build Coastguard Worker bev_async_del_read(beva);
289*663afb9bSAndroid Build Coastguard Worker return;
290*663afb9bSAndroid Build Coastguard Worker }
291*663afb9bSAndroid Build Coastguard Worker
292*663afb9bSAndroid Build Coastguard Worker bufferevent_incref_(bev);
293*663afb9bSAndroid Build Coastguard Worker if (evbuffer_launch_read_(bev->input, at_most, &beva->read_overlapped)) {
294*663afb9bSAndroid Build Coastguard Worker beva->ok = 0;
295*663afb9bSAndroid Build Coastguard Worker be_async_run_eventcb(bev, BEV_EVENT_ERROR, 0);
296*663afb9bSAndroid Build Coastguard Worker bufferevent_decref_(bev);
297*663afb9bSAndroid Build Coastguard Worker } else {
298*663afb9bSAndroid Build Coastguard Worker beva->read_in_progress = at_most;
299*663afb9bSAndroid Build Coastguard Worker bufferevent_decrement_read_buckets_(&beva->bev, at_most);
300*663afb9bSAndroid Build Coastguard Worker bev_async_add_read(beva);
301*663afb9bSAndroid Build Coastguard Worker }
302*663afb9bSAndroid Build Coastguard Worker
303*663afb9bSAndroid Build Coastguard Worker return;
304*663afb9bSAndroid Build Coastguard Worker }
305*663afb9bSAndroid Build Coastguard Worker
306*663afb9bSAndroid Build Coastguard Worker static void
be_async_outbuf_callback(struct evbuffer * buf,const struct evbuffer_cb_info * cbinfo,void * arg)307*663afb9bSAndroid Build Coastguard Worker be_async_outbuf_callback(struct evbuffer *buf,
308*663afb9bSAndroid Build Coastguard Worker const struct evbuffer_cb_info *cbinfo,
309*663afb9bSAndroid Build Coastguard Worker void *arg)
310*663afb9bSAndroid Build Coastguard Worker {
311*663afb9bSAndroid Build Coastguard Worker struct bufferevent *bev = arg;
312*663afb9bSAndroid Build Coastguard Worker struct bufferevent_async *bev_async = upcast(bev);
313*663afb9bSAndroid Build Coastguard Worker
314*663afb9bSAndroid Build Coastguard Worker /* If we added data to the outbuf and were not writing before,
315*663afb9bSAndroid Build Coastguard Worker * we may want to write now. */
316*663afb9bSAndroid Build Coastguard Worker
317*663afb9bSAndroid Build Coastguard Worker bufferevent_incref_and_lock_(bev);
318*663afb9bSAndroid Build Coastguard Worker
319*663afb9bSAndroid Build Coastguard Worker if (cbinfo->n_added)
320*663afb9bSAndroid Build Coastguard Worker bev_async_consider_writing(bev_async);
321*663afb9bSAndroid Build Coastguard Worker
322*663afb9bSAndroid Build Coastguard Worker bufferevent_decref_and_unlock_(bev);
323*663afb9bSAndroid Build Coastguard Worker }
324*663afb9bSAndroid Build Coastguard Worker
325*663afb9bSAndroid Build Coastguard Worker static void
be_async_inbuf_callback(struct evbuffer * buf,const struct evbuffer_cb_info * cbinfo,void * arg)326*663afb9bSAndroid Build Coastguard Worker be_async_inbuf_callback(struct evbuffer *buf,
327*663afb9bSAndroid Build Coastguard Worker const struct evbuffer_cb_info *cbinfo,
328*663afb9bSAndroid Build Coastguard Worker void *arg)
329*663afb9bSAndroid Build Coastguard Worker {
330*663afb9bSAndroid Build Coastguard Worker struct bufferevent *bev = arg;
331*663afb9bSAndroid Build Coastguard Worker struct bufferevent_async *bev_async = upcast(bev);
332*663afb9bSAndroid Build Coastguard Worker
333*663afb9bSAndroid Build Coastguard Worker /* If we drained data from the inbuf and were not reading before,
334*663afb9bSAndroid Build Coastguard Worker * we may want to read now */
335*663afb9bSAndroid Build Coastguard Worker
336*663afb9bSAndroid Build Coastguard Worker bufferevent_incref_and_lock_(bev);
337*663afb9bSAndroid Build Coastguard Worker
338*663afb9bSAndroid Build Coastguard Worker if (cbinfo->n_deleted)
339*663afb9bSAndroid Build Coastguard Worker bev_async_consider_reading(bev_async);
340*663afb9bSAndroid Build Coastguard Worker
341*663afb9bSAndroid Build Coastguard Worker bufferevent_decref_and_unlock_(bev);
342*663afb9bSAndroid Build Coastguard Worker }
343*663afb9bSAndroid Build Coastguard Worker
344*663afb9bSAndroid Build Coastguard Worker static int
be_async_enable(struct bufferevent * buf,short what)345*663afb9bSAndroid Build Coastguard Worker be_async_enable(struct bufferevent *buf, short what)
346*663afb9bSAndroid Build Coastguard Worker {
347*663afb9bSAndroid Build Coastguard Worker struct bufferevent_async *bev_async = upcast(buf);
348*663afb9bSAndroid Build Coastguard Worker
349*663afb9bSAndroid Build Coastguard Worker if (!bev_async->ok)
350*663afb9bSAndroid Build Coastguard Worker return -1;
351*663afb9bSAndroid Build Coastguard Worker
352*663afb9bSAndroid Build Coastguard Worker if (bev_async->bev.connecting) {
353*663afb9bSAndroid Build Coastguard Worker /* Don't launch anything during connection attempts. */
354*663afb9bSAndroid Build Coastguard Worker return 0;
355*663afb9bSAndroid Build Coastguard Worker }
356*663afb9bSAndroid Build Coastguard Worker
357*663afb9bSAndroid Build Coastguard Worker if (what & EV_READ)
358*663afb9bSAndroid Build Coastguard Worker BEV_RESET_GENERIC_READ_TIMEOUT(buf);
359*663afb9bSAndroid Build Coastguard Worker if (what & EV_WRITE)
360*663afb9bSAndroid Build Coastguard Worker BEV_RESET_GENERIC_WRITE_TIMEOUT(buf);
361*663afb9bSAndroid Build Coastguard Worker
362*663afb9bSAndroid Build Coastguard Worker /* If we newly enable reading or writing, and we aren't reading or
363*663afb9bSAndroid Build Coastguard Worker writing already, consider launching a new read or write. */
364*663afb9bSAndroid Build Coastguard Worker
365*663afb9bSAndroid Build Coastguard Worker if (what & EV_READ)
366*663afb9bSAndroid Build Coastguard Worker bev_async_consider_reading(bev_async);
367*663afb9bSAndroid Build Coastguard Worker if (what & EV_WRITE)
368*663afb9bSAndroid Build Coastguard Worker bev_async_consider_writing(bev_async);
369*663afb9bSAndroid Build Coastguard Worker return 0;
370*663afb9bSAndroid Build Coastguard Worker }
371*663afb9bSAndroid Build Coastguard Worker
372*663afb9bSAndroid Build Coastguard Worker static int
be_async_disable(struct bufferevent * bev,short what)373*663afb9bSAndroid Build Coastguard Worker be_async_disable(struct bufferevent *bev, short what)
374*663afb9bSAndroid Build Coastguard Worker {
375*663afb9bSAndroid Build Coastguard Worker struct bufferevent_async *bev_async = upcast(bev);
376*663afb9bSAndroid Build Coastguard Worker /* XXXX If we disable reading or writing, we may want to consider
377*663afb9bSAndroid Build Coastguard Worker * canceling any in-progress read or write operation, though it might
378*663afb9bSAndroid Build Coastguard Worker * not work. */
379*663afb9bSAndroid Build Coastguard Worker
380*663afb9bSAndroid Build Coastguard Worker if (what & EV_READ) {
381*663afb9bSAndroid Build Coastguard Worker BEV_DEL_GENERIC_READ_TIMEOUT(bev);
382*663afb9bSAndroid Build Coastguard Worker bev_async_del_read(bev_async);
383*663afb9bSAndroid Build Coastguard Worker }
384*663afb9bSAndroid Build Coastguard Worker if (what & EV_WRITE) {
385*663afb9bSAndroid Build Coastguard Worker BEV_DEL_GENERIC_WRITE_TIMEOUT(bev);
386*663afb9bSAndroid Build Coastguard Worker bev_async_del_write(bev_async);
387*663afb9bSAndroid Build Coastguard Worker }
388*663afb9bSAndroid Build Coastguard Worker
389*663afb9bSAndroid Build Coastguard Worker return 0;
390*663afb9bSAndroid Build Coastguard Worker }
391*663afb9bSAndroid Build Coastguard Worker
392*663afb9bSAndroid Build Coastguard Worker static void
be_async_destruct(struct bufferevent * bev)393*663afb9bSAndroid Build Coastguard Worker be_async_destruct(struct bufferevent *bev)
394*663afb9bSAndroid Build Coastguard Worker {
395*663afb9bSAndroid Build Coastguard Worker struct bufferevent_async *bev_async = upcast(bev);
396*663afb9bSAndroid Build Coastguard Worker struct bufferevent_private *bev_p = BEV_UPCAST(bev);
397*663afb9bSAndroid Build Coastguard Worker evutil_socket_t fd;
398*663afb9bSAndroid Build Coastguard Worker
399*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(!upcast(bev)->write_in_progress &&
400*663afb9bSAndroid Build Coastguard Worker !upcast(bev)->read_in_progress);
401*663afb9bSAndroid Build Coastguard Worker
402*663afb9bSAndroid Build Coastguard Worker bev_async_del_read(bev_async);
403*663afb9bSAndroid Build Coastguard Worker bev_async_del_write(bev_async);
404*663afb9bSAndroid Build Coastguard Worker
405*663afb9bSAndroid Build Coastguard Worker fd = evbuffer_overlapped_get_fd_(bev->input);
406*663afb9bSAndroid Build Coastguard Worker if (fd != (evutil_socket_t)EVUTIL_INVALID_SOCKET &&
407*663afb9bSAndroid Build Coastguard Worker (bev_p->options & BEV_OPT_CLOSE_ON_FREE)) {
408*663afb9bSAndroid Build Coastguard Worker evutil_closesocket(fd);
409*663afb9bSAndroid Build Coastguard Worker evbuffer_overlapped_set_fd_(bev->input, EVUTIL_INVALID_SOCKET);
410*663afb9bSAndroid Build Coastguard Worker }
411*663afb9bSAndroid Build Coastguard Worker }
412*663afb9bSAndroid Build Coastguard Worker
413*663afb9bSAndroid Build Coastguard Worker /* GetQueuedCompletionStatus doesn't reliably yield WSA error codes, so
414*663afb9bSAndroid Build Coastguard Worker * we use WSAGetOverlappedResult to translate. */
415*663afb9bSAndroid Build Coastguard Worker static void
bev_async_set_wsa_error(struct bufferevent * bev,struct event_overlapped * eo)416*663afb9bSAndroid Build Coastguard Worker bev_async_set_wsa_error(struct bufferevent *bev, struct event_overlapped *eo)
417*663afb9bSAndroid Build Coastguard Worker {
418*663afb9bSAndroid Build Coastguard Worker DWORD bytes, flags;
419*663afb9bSAndroid Build Coastguard Worker evutil_socket_t fd;
420*663afb9bSAndroid Build Coastguard Worker
421*663afb9bSAndroid Build Coastguard Worker fd = evbuffer_overlapped_get_fd_(bev->input);
422*663afb9bSAndroid Build Coastguard Worker WSAGetOverlappedResult(fd, &eo->overlapped, &bytes, FALSE, &flags);
423*663afb9bSAndroid Build Coastguard Worker }
424*663afb9bSAndroid Build Coastguard Worker
425*663afb9bSAndroid Build Coastguard Worker static int
be_async_flush(struct bufferevent * bev,short what,enum bufferevent_flush_mode mode)426*663afb9bSAndroid Build Coastguard Worker be_async_flush(struct bufferevent *bev, short what,
427*663afb9bSAndroid Build Coastguard Worker enum bufferevent_flush_mode mode)
428*663afb9bSAndroid Build Coastguard Worker {
429*663afb9bSAndroid Build Coastguard Worker return 0;
430*663afb9bSAndroid Build Coastguard Worker }
431*663afb9bSAndroid Build Coastguard Worker
432*663afb9bSAndroid Build Coastguard Worker static void
connect_complete(struct event_overlapped * eo,ev_uintptr_t key,ev_ssize_t nbytes,int ok)433*663afb9bSAndroid Build Coastguard Worker connect_complete(struct event_overlapped *eo, ev_uintptr_t key,
434*663afb9bSAndroid Build Coastguard Worker ev_ssize_t nbytes, int ok)
435*663afb9bSAndroid Build Coastguard Worker {
436*663afb9bSAndroid Build Coastguard Worker struct bufferevent_async *bev_a = upcast_connect(eo);
437*663afb9bSAndroid Build Coastguard Worker struct bufferevent *bev = &bev_a->bev.bev;
438*663afb9bSAndroid Build Coastguard Worker evutil_socket_t sock;
439*663afb9bSAndroid Build Coastguard Worker
440*663afb9bSAndroid Build Coastguard Worker BEV_LOCK(bev);
441*663afb9bSAndroid Build Coastguard Worker
442*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(bev_a->bev.connecting);
443*663afb9bSAndroid Build Coastguard Worker bev_a->bev.connecting = 0;
444*663afb9bSAndroid Build Coastguard Worker sock = evbuffer_overlapped_get_fd_(bev_a->bev.bev.input);
445*663afb9bSAndroid Build Coastguard Worker /* XXXX Handle error? */
446*663afb9bSAndroid Build Coastguard Worker setsockopt(sock, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
447*663afb9bSAndroid Build Coastguard Worker
448*663afb9bSAndroid Build Coastguard Worker if (ok)
449*663afb9bSAndroid Build Coastguard Worker bufferevent_async_set_connected_(bev);
450*663afb9bSAndroid Build Coastguard Worker else
451*663afb9bSAndroid Build Coastguard Worker bev_async_set_wsa_error(bev, eo);
452*663afb9bSAndroid Build Coastguard Worker
453*663afb9bSAndroid Build Coastguard Worker be_async_run_eventcb(bev, ok ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR, 0);
454*663afb9bSAndroid Build Coastguard Worker
455*663afb9bSAndroid Build Coastguard Worker event_base_del_virtual_(bev->ev_base);
456*663afb9bSAndroid Build Coastguard Worker
457*663afb9bSAndroid Build Coastguard Worker bufferevent_decref_and_unlock_(bev);
458*663afb9bSAndroid Build Coastguard Worker }
459*663afb9bSAndroid Build Coastguard Worker
460*663afb9bSAndroid Build Coastguard Worker static void
read_complete(struct event_overlapped * eo,ev_uintptr_t key,ev_ssize_t nbytes,int ok)461*663afb9bSAndroid Build Coastguard Worker read_complete(struct event_overlapped *eo, ev_uintptr_t key,
462*663afb9bSAndroid Build Coastguard Worker ev_ssize_t nbytes, int ok)
463*663afb9bSAndroid Build Coastguard Worker {
464*663afb9bSAndroid Build Coastguard Worker struct bufferevent_async *bev_a = upcast_read(eo);
465*663afb9bSAndroid Build Coastguard Worker struct bufferevent *bev = &bev_a->bev.bev;
466*663afb9bSAndroid Build Coastguard Worker short what = BEV_EVENT_READING;
467*663afb9bSAndroid Build Coastguard Worker ev_ssize_t amount_unread;
468*663afb9bSAndroid Build Coastguard Worker BEV_LOCK(bev);
469*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(bev_a->read_in_progress);
470*663afb9bSAndroid Build Coastguard Worker
471*663afb9bSAndroid Build Coastguard Worker amount_unread = bev_a->read_in_progress - nbytes;
472*663afb9bSAndroid Build Coastguard Worker evbuffer_commit_read_(bev->input, nbytes);
473*663afb9bSAndroid Build Coastguard Worker bev_a->read_in_progress = 0;
474*663afb9bSAndroid Build Coastguard Worker if (amount_unread)
475*663afb9bSAndroid Build Coastguard Worker bufferevent_decrement_read_buckets_(&bev_a->bev, -amount_unread);
476*663afb9bSAndroid Build Coastguard Worker
477*663afb9bSAndroid Build Coastguard Worker if (!ok)
478*663afb9bSAndroid Build Coastguard Worker bev_async_set_wsa_error(bev, eo);
479*663afb9bSAndroid Build Coastguard Worker
480*663afb9bSAndroid Build Coastguard Worker if (bev_a->ok) {
481*663afb9bSAndroid Build Coastguard Worker if (ok && nbytes) {
482*663afb9bSAndroid Build Coastguard Worker BEV_RESET_GENERIC_READ_TIMEOUT(bev);
483*663afb9bSAndroid Build Coastguard Worker be_async_trigger_nolock(bev, EV_READ, 0);
484*663afb9bSAndroid Build Coastguard Worker bev_async_consider_reading(bev_a);
485*663afb9bSAndroid Build Coastguard Worker } else if (!ok) {
486*663afb9bSAndroid Build Coastguard Worker what |= BEV_EVENT_ERROR;
487*663afb9bSAndroid Build Coastguard Worker bev_a->ok = 0;
488*663afb9bSAndroid Build Coastguard Worker be_async_run_eventcb(bev, what, 0);
489*663afb9bSAndroid Build Coastguard Worker } else if (!nbytes) {
490*663afb9bSAndroid Build Coastguard Worker what |= BEV_EVENT_EOF;
491*663afb9bSAndroid Build Coastguard Worker bev_a->ok = 0;
492*663afb9bSAndroid Build Coastguard Worker be_async_run_eventcb(bev, what, 0);
493*663afb9bSAndroid Build Coastguard Worker }
494*663afb9bSAndroid Build Coastguard Worker }
495*663afb9bSAndroid Build Coastguard Worker
496*663afb9bSAndroid Build Coastguard Worker bufferevent_decref_and_unlock_(bev);
497*663afb9bSAndroid Build Coastguard Worker }
498*663afb9bSAndroid Build Coastguard Worker
499*663afb9bSAndroid Build Coastguard Worker static void
write_complete(struct event_overlapped * eo,ev_uintptr_t key,ev_ssize_t nbytes,int ok)500*663afb9bSAndroid Build Coastguard Worker write_complete(struct event_overlapped *eo, ev_uintptr_t key,
501*663afb9bSAndroid Build Coastguard Worker ev_ssize_t nbytes, int ok)
502*663afb9bSAndroid Build Coastguard Worker {
503*663afb9bSAndroid Build Coastguard Worker struct bufferevent_async *bev_a = upcast_write(eo);
504*663afb9bSAndroid Build Coastguard Worker struct bufferevent *bev = &bev_a->bev.bev;
505*663afb9bSAndroid Build Coastguard Worker short what = BEV_EVENT_WRITING;
506*663afb9bSAndroid Build Coastguard Worker ev_ssize_t amount_unwritten;
507*663afb9bSAndroid Build Coastguard Worker
508*663afb9bSAndroid Build Coastguard Worker BEV_LOCK(bev);
509*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(bev_a->write_in_progress);
510*663afb9bSAndroid Build Coastguard Worker
511*663afb9bSAndroid Build Coastguard Worker amount_unwritten = bev_a->write_in_progress - nbytes;
512*663afb9bSAndroid Build Coastguard Worker evbuffer_commit_write_(bev->output, nbytes);
513*663afb9bSAndroid Build Coastguard Worker bev_a->write_in_progress = 0;
514*663afb9bSAndroid Build Coastguard Worker
515*663afb9bSAndroid Build Coastguard Worker if (amount_unwritten)
516*663afb9bSAndroid Build Coastguard Worker bufferevent_decrement_write_buckets_(&bev_a->bev,
517*663afb9bSAndroid Build Coastguard Worker -amount_unwritten);
518*663afb9bSAndroid Build Coastguard Worker
519*663afb9bSAndroid Build Coastguard Worker
520*663afb9bSAndroid Build Coastguard Worker if (!ok)
521*663afb9bSAndroid Build Coastguard Worker bev_async_set_wsa_error(bev, eo);
522*663afb9bSAndroid Build Coastguard Worker
523*663afb9bSAndroid Build Coastguard Worker if (bev_a->ok) {
524*663afb9bSAndroid Build Coastguard Worker if (ok && nbytes) {
525*663afb9bSAndroid Build Coastguard Worker BEV_RESET_GENERIC_WRITE_TIMEOUT(bev);
526*663afb9bSAndroid Build Coastguard Worker be_async_trigger_nolock(bev, EV_WRITE, 0);
527*663afb9bSAndroid Build Coastguard Worker bev_async_consider_writing(bev_a);
528*663afb9bSAndroid Build Coastguard Worker } else if (!ok) {
529*663afb9bSAndroid Build Coastguard Worker what |= BEV_EVENT_ERROR;
530*663afb9bSAndroid Build Coastguard Worker bev_a->ok = 0;
531*663afb9bSAndroid Build Coastguard Worker be_async_run_eventcb(bev, what, 0);
532*663afb9bSAndroid Build Coastguard Worker } else if (!nbytes) {
533*663afb9bSAndroid Build Coastguard Worker what |= BEV_EVENT_EOF;
534*663afb9bSAndroid Build Coastguard Worker bev_a->ok = 0;
535*663afb9bSAndroid Build Coastguard Worker be_async_run_eventcb(bev, what, 0);
536*663afb9bSAndroid Build Coastguard Worker }
537*663afb9bSAndroid Build Coastguard Worker }
538*663afb9bSAndroid Build Coastguard Worker
539*663afb9bSAndroid Build Coastguard Worker bufferevent_decref_and_unlock_(bev);
540*663afb9bSAndroid Build Coastguard Worker }
541*663afb9bSAndroid Build Coastguard Worker
542*663afb9bSAndroid Build Coastguard Worker struct bufferevent *
bufferevent_async_new_(struct event_base * base,evutil_socket_t fd,int options)543*663afb9bSAndroid Build Coastguard Worker bufferevent_async_new_(struct event_base *base,
544*663afb9bSAndroid Build Coastguard Worker evutil_socket_t fd, int options)
545*663afb9bSAndroid Build Coastguard Worker {
546*663afb9bSAndroid Build Coastguard Worker struct bufferevent_async *bev_a;
547*663afb9bSAndroid Build Coastguard Worker struct bufferevent *bev;
548*663afb9bSAndroid Build Coastguard Worker struct event_iocp_port *iocp;
549*663afb9bSAndroid Build Coastguard Worker
550*663afb9bSAndroid Build Coastguard Worker options |= BEV_OPT_THREADSAFE;
551*663afb9bSAndroid Build Coastguard Worker
552*663afb9bSAndroid Build Coastguard Worker if (!(iocp = event_base_get_iocp_(base)))
553*663afb9bSAndroid Build Coastguard Worker return NULL;
554*663afb9bSAndroid Build Coastguard Worker
555*663afb9bSAndroid Build Coastguard Worker if (fd >= 0 && event_iocp_port_associate_(iocp, fd, 1)<0) {
556*663afb9bSAndroid Build Coastguard Worker if (fatal_error(GetLastError()))
557*663afb9bSAndroid Build Coastguard Worker return NULL;
558*663afb9bSAndroid Build Coastguard Worker }
559*663afb9bSAndroid Build Coastguard Worker
560*663afb9bSAndroid Build Coastguard Worker if (!(bev_a = mm_calloc(1, sizeof(struct bufferevent_async))))
561*663afb9bSAndroid Build Coastguard Worker return NULL;
562*663afb9bSAndroid Build Coastguard Worker
563*663afb9bSAndroid Build Coastguard Worker bev = &bev_a->bev.bev;
564*663afb9bSAndroid Build Coastguard Worker if (!(bev->input = evbuffer_overlapped_new_(fd))) {
565*663afb9bSAndroid Build Coastguard Worker mm_free(bev_a);
566*663afb9bSAndroid Build Coastguard Worker return NULL;
567*663afb9bSAndroid Build Coastguard Worker }
568*663afb9bSAndroid Build Coastguard Worker if (!(bev->output = evbuffer_overlapped_new_(fd))) {
569*663afb9bSAndroid Build Coastguard Worker evbuffer_free(bev->input);
570*663afb9bSAndroid Build Coastguard Worker mm_free(bev_a);
571*663afb9bSAndroid Build Coastguard Worker return NULL;
572*663afb9bSAndroid Build Coastguard Worker }
573*663afb9bSAndroid Build Coastguard Worker
574*663afb9bSAndroid Build Coastguard Worker if (bufferevent_init_common_(&bev_a->bev, base, &bufferevent_ops_async,
575*663afb9bSAndroid Build Coastguard Worker options)<0)
576*663afb9bSAndroid Build Coastguard Worker goto err;
577*663afb9bSAndroid Build Coastguard Worker
578*663afb9bSAndroid Build Coastguard Worker evbuffer_add_cb(bev->input, be_async_inbuf_callback, bev);
579*663afb9bSAndroid Build Coastguard Worker evbuffer_add_cb(bev->output, be_async_outbuf_callback, bev);
580*663afb9bSAndroid Build Coastguard Worker
581*663afb9bSAndroid Build Coastguard Worker event_overlapped_init_(&bev_a->connect_overlapped, connect_complete);
582*663afb9bSAndroid Build Coastguard Worker event_overlapped_init_(&bev_a->read_overlapped, read_complete);
583*663afb9bSAndroid Build Coastguard Worker event_overlapped_init_(&bev_a->write_overlapped, write_complete);
584*663afb9bSAndroid Build Coastguard Worker
585*663afb9bSAndroid Build Coastguard Worker bufferevent_init_generic_timeout_cbs_(bev);
586*663afb9bSAndroid Build Coastguard Worker
587*663afb9bSAndroid Build Coastguard Worker bev_a->ok = fd >= 0;
588*663afb9bSAndroid Build Coastguard Worker
589*663afb9bSAndroid Build Coastguard Worker return bev;
590*663afb9bSAndroid Build Coastguard Worker err:
591*663afb9bSAndroid Build Coastguard Worker bufferevent_free(&bev_a->bev.bev);
592*663afb9bSAndroid Build Coastguard Worker return NULL;
593*663afb9bSAndroid Build Coastguard Worker }
594*663afb9bSAndroid Build Coastguard Worker
595*663afb9bSAndroid Build Coastguard Worker void
bufferevent_async_set_connected_(struct bufferevent * bev)596*663afb9bSAndroid Build Coastguard Worker bufferevent_async_set_connected_(struct bufferevent *bev)
597*663afb9bSAndroid Build Coastguard Worker {
598*663afb9bSAndroid Build Coastguard Worker struct bufferevent_async *bev_async = upcast(bev);
599*663afb9bSAndroid Build Coastguard Worker bev_async->ok = 1;
600*663afb9bSAndroid Build Coastguard Worker /* Now's a good time to consider reading/writing */
601*663afb9bSAndroid Build Coastguard Worker be_async_enable(bev, bev->enabled);
602*663afb9bSAndroid Build Coastguard Worker }
603*663afb9bSAndroid Build Coastguard Worker
604*663afb9bSAndroid Build Coastguard Worker int
bufferevent_async_can_connect_(struct bufferevent * bev)605*663afb9bSAndroid Build Coastguard Worker bufferevent_async_can_connect_(struct bufferevent *bev)
606*663afb9bSAndroid Build Coastguard Worker {
607*663afb9bSAndroid Build Coastguard Worker const struct win32_extension_fns *ext =
608*663afb9bSAndroid Build Coastguard Worker event_get_win32_extension_fns_();
609*663afb9bSAndroid Build Coastguard Worker
610*663afb9bSAndroid Build Coastguard Worker if (BEV_IS_ASYNC(bev) &&
611*663afb9bSAndroid Build Coastguard Worker event_base_get_iocp_(bev->ev_base) &&
612*663afb9bSAndroid Build Coastguard Worker ext && ext->ConnectEx)
613*663afb9bSAndroid Build Coastguard Worker return 1;
614*663afb9bSAndroid Build Coastguard Worker
615*663afb9bSAndroid Build Coastguard Worker return 0;
616*663afb9bSAndroid Build Coastguard Worker }
617*663afb9bSAndroid Build Coastguard Worker
618*663afb9bSAndroid Build Coastguard Worker int
bufferevent_async_connect_(struct bufferevent * bev,evutil_socket_t fd,const struct sockaddr * sa,int socklen)619*663afb9bSAndroid Build Coastguard Worker bufferevent_async_connect_(struct bufferevent *bev, evutil_socket_t fd,
620*663afb9bSAndroid Build Coastguard Worker const struct sockaddr *sa, int socklen)
621*663afb9bSAndroid Build Coastguard Worker {
622*663afb9bSAndroid Build Coastguard Worker BOOL rc;
623*663afb9bSAndroid Build Coastguard Worker struct bufferevent_async *bev_async = upcast(bev);
624*663afb9bSAndroid Build Coastguard Worker struct sockaddr_storage ss;
625*663afb9bSAndroid Build Coastguard Worker const struct win32_extension_fns *ext =
626*663afb9bSAndroid Build Coastguard Worker event_get_win32_extension_fns_();
627*663afb9bSAndroid Build Coastguard Worker
628*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(ext && ext->ConnectEx && fd >= 0 && sa != NULL);
629*663afb9bSAndroid Build Coastguard Worker
630*663afb9bSAndroid Build Coastguard Worker /* ConnectEx() requires that the socket be bound to an address
631*663afb9bSAndroid Build Coastguard Worker * with bind() before using, otherwise it will fail. We attempt
632*663afb9bSAndroid Build Coastguard Worker * to issue a bind() here, taking into account that the error
633*663afb9bSAndroid Build Coastguard Worker * code is set to WSAEINVAL when the socket is already bound. */
634*663afb9bSAndroid Build Coastguard Worker memset(&ss, 0, sizeof(ss));
635*663afb9bSAndroid Build Coastguard Worker if (sa->sa_family == AF_INET) {
636*663afb9bSAndroid Build Coastguard Worker struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
637*663afb9bSAndroid Build Coastguard Worker sin->sin_family = AF_INET;
638*663afb9bSAndroid Build Coastguard Worker sin->sin_addr.s_addr = INADDR_ANY;
639*663afb9bSAndroid Build Coastguard Worker } else if (sa->sa_family == AF_INET6) {
640*663afb9bSAndroid Build Coastguard Worker struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
641*663afb9bSAndroid Build Coastguard Worker sin6->sin6_family = AF_INET6;
642*663afb9bSAndroid Build Coastguard Worker sin6->sin6_addr = in6addr_any;
643*663afb9bSAndroid Build Coastguard Worker } else {
644*663afb9bSAndroid Build Coastguard Worker /* Well, the user will have to bind() */
645*663afb9bSAndroid Build Coastguard Worker return -1;
646*663afb9bSAndroid Build Coastguard Worker }
647*663afb9bSAndroid Build Coastguard Worker if (bind(fd, (struct sockaddr *)&ss, sizeof(ss)) < 0 &&
648*663afb9bSAndroid Build Coastguard Worker WSAGetLastError() != WSAEINVAL)
649*663afb9bSAndroid Build Coastguard Worker return -1;
650*663afb9bSAndroid Build Coastguard Worker
651*663afb9bSAndroid Build Coastguard Worker event_base_add_virtual_(bev->ev_base);
652*663afb9bSAndroid Build Coastguard Worker bufferevent_incref_(bev);
653*663afb9bSAndroid Build Coastguard Worker rc = ext->ConnectEx(fd, sa, socklen, NULL, 0, NULL,
654*663afb9bSAndroid Build Coastguard Worker &bev_async->connect_overlapped.overlapped);
655*663afb9bSAndroid Build Coastguard Worker if (rc || WSAGetLastError() == ERROR_IO_PENDING)
656*663afb9bSAndroid Build Coastguard Worker return 0;
657*663afb9bSAndroid Build Coastguard Worker
658*663afb9bSAndroid Build Coastguard Worker event_base_del_virtual_(bev->ev_base);
659*663afb9bSAndroid Build Coastguard Worker bufferevent_decref_(bev);
660*663afb9bSAndroid Build Coastguard Worker
661*663afb9bSAndroid Build Coastguard Worker return -1;
662*663afb9bSAndroid Build Coastguard Worker }
663*663afb9bSAndroid Build Coastguard Worker
664*663afb9bSAndroid Build Coastguard Worker static int
be_async_ctrl(struct bufferevent * bev,enum bufferevent_ctrl_op op,union bufferevent_ctrl_data * data)665*663afb9bSAndroid Build Coastguard Worker be_async_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
666*663afb9bSAndroid Build Coastguard Worker union bufferevent_ctrl_data *data)
667*663afb9bSAndroid Build Coastguard Worker {
668*663afb9bSAndroid Build Coastguard Worker switch (op) {
669*663afb9bSAndroid Build Coastguard Worker case BEV_CTRL_GET_FD:
670*663afb9bSAndroid Build Coastguard Worker data->fd = evbuffer_overlapped_get_fd_(bev->input);
671*663afb9bSAndroid Build Coastguard Worker return 0;
672*663afb9bSAndroid Build Coastguard Worker case BEV_CTRL_SET_FD: {
673*663afb9bSAndroid Build Coastguard Worker struct bufferevent_async *bev_a = upcast(bev);
674*663afb9bSAndroid Build Coastguard Worker struct event_iocp_port *iocp;
675*663afb9bSAndroid Build Coastguard Worker
676*663afb9bSAndroid Build Coastguard Worker if (data->fd == evbuffer_overlapped_get_fd_(bev->input))
677*663afb9bSAndroid Build Coastguard Worker return 0;
678*663afb9bSAndroid Build Coastguard Worker if (!(iocp = event_base_get_iocp_(bev->ev_base)))
679*663afb9bSAndroid Build Coastguard Worker return -1;
680*663afb9bSAndroid Build Coastguard Worker if (event_iocp_port_associate_(iocp, data->fd, 1) < 0) {
681*663afb9bSAndroid Build Coastguard Worker if (fatal_error(GetLastError()))
682*663afb9bSAndroid Build Coastguard Worker return -1;
683*663afb9bSAndroid Build Coastguard Worker }
684*663afb9bSAndroid Build Coastguard Worker evbuffer_overlapped_set_fd_(bev->input, data->fd);
685*663afb9bSAndroid Build Coastguard Worker evbuffer_overlapped_set_fd_(bev->output, data->fd);
686*663afb9bSAndroid Build Coastguard Worker bev_a->ok = data->fd >= 0;
687*663afb9bSAndroid Build Coastguard Worker return 0;
688*663afb9bSAndroid Build Coastguard Worker }
689*663afb9bSAndroid Build Coastguard Worker case BEV_CTRL_CANCEL_ALL: {
690*663afb9bSAndroid Build Coastguard Worker struct bufferevent_async *bev_a = upcast(bev);
691*663afb9bSAndroid Build Coastguard Worker evutil_socket_t fd = evbuffer_overlapped_get_fd_(bev->input);
692*663afb9bSAndroid Build Coastguard Worker if (fd != (evutil_socket_t)EVUTIL_INVALID_SOCKET &&
693*663afb9bSAndroid Build Coastguard Worker (bev_a->bev.options & BEV_OPT_CLOSE_ON_FREE)) {
694*663afb9bSAndroid Build Coastguard Worker closesocket(fd);
695*663afb9bSAndroid Build Coastguard Worker evbuffer_overlapped_set_fd_(bev->input, EVUTIL_INVALID_SOCKET);
696*663afb9bSAndroid Build Coastguard Worker }
697*663afb9bSAndroid Build Coastguard Worker bev_a->ok = 0;
698*663afb9bSAndroid Build Coastguard Worker return 0;
699*663afb9bSAndroid Build Coastguard Worker }
700*663afb9bSAndroid Build Coastguard Worker case BEV_CTRL_GET_UNDERLYING:
701*663afb9bSAndroid Build Coastguard Worker default:
702*663afb9bSAndroid Build Coastguard Worker return -1;
703*663afb9bSAndroid Build Coastguard Worker }
704*663afb9bSAndroid Build Coastguard Worker }
705*663afb9bSAndroid Build Coastguard Worker
706*663afb9bSAndroid Build Coastguard Worker
707