xref: /minix3/external/bsd/libevent/dist/buffer_iocp.c (revision e985b929927b5932e3b68f4b50587d458900107a)
1*e985b929SDavid van Moolenbroek /*	$NetBSD: buffer_iocp.c,v 1.1.1.1 2013/04/11 16:43:25 christos Exp $	*/
2*e985b929SDavid van Moolenbroek /*
3*e985b929SDavid van Moolenbroek  * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
4*e985b929SDavid van Moolenbroek  *
5*e985b929SDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
6*e985b929SDavid van Moolenbroek  * modification, are permitted provided that the following conditions
7*e985b929SDavid van Moolenbroek  * are met:
8*e985b929SDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
9*e985b929SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer.
10*e985b929SDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright
11*e985b929SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer in the
12*e985b929SDavid van Moolenbroek  *    documentation and/or other materials provided with the distribution.
13*e985b929SDavid van Moolenbroek  * 3. The name of the author may not be used to endorse or promote products
14*e985b929SDavid van Moolenbroek  *    derived from this software without specific prior written permission.
15*e985b929SDavid van Moolenbroek  *
16*e985b929SDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*e985b929SDavid van Moolenbroek  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*e985b929SDavid van Moolenbroek  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*e985b929SDavid van Moolenbroek  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20*e985b929SDavid van Moolenbroek  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21*e985b929SDavid van Moolenbroek  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22*e985b929SDavid van Moolenbroek  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23*e985b929SDavid van Moolenbroek  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*e985b929SDavid van Moolenbroek  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25*e985b929SDavid van Moolenbroek  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*e985b929SDavid van Moolenbroek  */
27*e985b929SDavid van Moolenbroek 
28*e985b929SDavid van Moolenbroek /**
29*e985b929SDavid van Moolenbroek    @file buffer_iocp.c
30*e985b929SDavid van Moolenbroek 
31*e985b929SDavid van Moolenbroek    This module implements overlapped read and write functions for evbuffer
32*e985b929SDavid van Moolenbroek    objects on Windows.
33*e985b929SDavid van Moolenbroek */
34*e985b929SDavid van Moolenbroek 
35*e985b929SDavid van Moolenbroek #include "event2/buffer.h"
36*e985b929SDavid van Moolenbroek #include "event2/buffer_compat.h"
37*e985b929SDavid van Moolenbroek #include "event2/util.h"
38*e985b929SDavid van Moolenbroek #include "event2/thread.h"
39*e985b929SDavid van Moolenbroek #include "event2/event-config.h"
40*e985b929SDavid van Moolenbroek #include <sys/cdefs.h>
41*e985b929SDavid van Moolenbroek __RCSID("$NetBSD: buffer_iocp.c,v 1.1.1.1 2013/04/11 16:43:25 christos Exp $");
42*e985b929SDavid van Moolenbroek #include "util-internal.h"
43*e985b929SDavid van Moolenbroek #include "evthread-internal.h"
44*e985b929SDavid van Moolenbroek #include "evbuffer-internal.h"
45*e985b929SDavid van Moolenbroek #include "iocp-internal.h"
46*e985b929SDavid van Moolenbroek #include "mm-internal.h"
47*e985b929SDavid van Moolenbroek 
48*e985b929SDavid van Moolenbroek #include <winsock2.h>
49*e985b929SDavid van Moolenbroek #include <windows.h>
50*e985b929SDavid van Moolenbroek #include <stdio.h>
51*e985b929SDavid van Moolenbroek 
52*e985b929SDavid van Moolenbroek #define MAX_WSABUFS 16
53*e985b929SDavid van Moolenbroek 
54*e985b929SDavid van Moolenbroek /** An evbuffer that can handle overlapped IO. */
55*e985b929SDavid van Moolenbroek struct evbuffer_overlapped {
56*e985b929SDavid van Moolenbroek 	struct evbuffer buffer;
57*e985b929SDavid van Moolenbroek 	/** The socket that we're doing overlapped IO on. */
58*e985b929SDavid van Moolenbroek 	evutil_socket_t fd;
59*e985b929SDavid van Moolenbroek 
60*e985b929SDavid van Moolenbroek 	/** pending I/O type */
61*e985b929SDavid van Moolenbroek 	unsigned read_in_progress : 1;
62*e985b929SDavid van Moolenbroek 	unsigned write_in_progress : 1;
63*e985b929SDavid van Moolenbroek 
64*e985b929SDavid van Moolenbroek 	/** The first pinned chain in the buffer. */
65*e985b929SDavid van Moolenbroek 	struct evbuffer_chain *first_pinned;
66*e985b929SDavid van Moolenbroek 
67*e985b929SDavid van Moolenbroek 	/** How many chains are pinned; how many of the fields in buffers
68*e985b929SDavid van Moolenbroek 	 * are we using. */
69*e985b929SDavid van Moolenbroek 	int n_buffers;
70*e985b929SDavid van Moolenbroek 	WSABUF buffers[MAX_WSABUFS];
71*e985b929SDavid van Moolenbroek };
72*e985b929SDavid van Moolenbroek 
73*e985b929SDavid van Moolenbroek /** Given an evbuffer, return the correponding evbuffer structure, or NULL if
74*e985b929SDavid van Moolenbroek  * the evbuffer isn't overlapped. */
75*e985b929SDavid van Moolenbroek static inline struct evbuffer_overlapped *
upcast_evbuffer(struct evbuffer * buf)76*e985b929SDavid van Moolenbroek upcast_evbuffer(struct evbuffer *buf)
77*e985b929SDavid van Moolenbroek {
78*e985b929SDavid van Moolenbroek 	if (!buf || !buf->is_overlapped)
79*e985b929SDavid van Moolenbroek 		return NULL;
80*e985b929SDavid van Moolenbroek 	return EVUTIL_UPCAST(buf, struct evbuffer_overlapped, buffer);
81*e985b929SDavid van Moolenbroek }
82*e985b929SDavid van Moolenbroek 
83*e985b929SDavid van Moolenbroek /** Unpin all the chains noted as pinned in 'eo'. */
84*e985b929SDavid van Moolenbroek static void
pin_release(struct evbuffer_overlapped * eo,unsigned flag)85*e985b929SDavid van Moolenbroek pin_release(struct evbuffer_overlapped *eo, unsigned flag)
86*e985b929SDavid van Moolenbroek {
87*e985b929SDavid van Moolenbroek 	int i;
88*e985b929SDavid van Moolenbroek 	struct evbuffer_chain *next, *chain = eo->first_pinned;
89*e985b929SDavid van Moolenbroek 
90*e985b929SDavid van Moolenbroek 	for (i = 0; i < eo->n_buffers; ++i) {
91*e985b929SDavid van Moolenbroek 		EVUTIL_ASSERT(chain);
92*e985b929SDavid van Moolenbroek 		next = chain->next;
93*e985b929SDavid van Moolenbroek 		_evbuffer_chain_unpin(chain, flag);
94*e985b929SDavid van Moolenbroek 		chain = next;
95*e985b929SDavid van Moolenbroek 	}
96*e985b929SDavid van Moolenbroek }
97*e985b929SDavid van Moolenbroek 
98*e985b929SDavid van Moolenbroek void
evbuffer_commit_read(struct evbuffer * evbuf,ev_ssize_t nBytes)99*e985b929SDavid van Moolenbroek evbuffer_commit_read(struct evbuffer *evbuf, ev_ssize_t nBytes)
100*e985b929SDavid van Moolenbroek {
101*e985b929SDavid van Moolenbroek 	struct evbuffer_overlapped *buf = upcast_evbuffer(evbuf);
102*e985b929SDavid van Moolenbroek 	struct evbuffer_chain **chainp;
103*e985b929SDavid van Moolenbroek 	size_t remaining, len;
104*e985b929SDavid van Moolenbroek 	unsigned i;
105*e985b929SDavid van Moolenbroek 
106*e985b929SDavid van Moolenbroek 	EVBUFFER_LOCK(evbuf);
107*e985b929SDavid van Moolenbroek 	EVUTIL_ASSERT(buf->read_in_progress && !buf->write_in_progress);
108*e985b929SDavid van Moolenbroek 	EVUTIL_ASSERT(nBytes >= 0); /* XXXX Can this be false? */
109*e985b929SDavid van Moolenbroek 
110*e985b929SDavid van Moolenbroek 	evbuffer_unfreeze(evbuf, 0);
111*e985b929SDavid van Moolenbroek 
112*e985b929SDavid van Moolenbroek 	chainp = evbuf->last_with_datap;
113*e985b929SDavid van Moolenbroek 	if (!((*chainp)->flags & EVBUFFER_MEM_PINNED_R))
114*e985b929SDavid van Moolenbroek 		chainp = &(*chainp)->next;
115*e985b929SDavid van Moolenbroek 	remaining = nBytes;
116*e985b929SDavid van Moolenbroek 	for (i = 0; remaining > 0 && i < (unsigned)buf->n_buffers; ++i) {
117*e985b929SDavid van Moolenbroek 		EVUTIL_ASSERT(*chainp);
118*e985b929SDavid van Moolenbroek 		len = buf->buffers[i].len;
119*e985b929SDavid van Moolenbroek 		if (remaining < len)
120*e985b929SDavid van Moolenbroek 			len = remaining;
121*e985b929SDavid van Moolenbroek 		(*chainp)->off += len;
122*e985b929SDavid van Moolenbroek 		evbuf->last_with_datap = chainp;
123*e985b929SDavid van Moolenbroek 		remaining -= len;
124*e985b929SDavid van Moolenbroek 		chainp = &(*chainp)->next;
125*e985b929SDavid van Moolenbroek 	}
126*e985b929SDavid van Moolenbroek 
127*e985b929SDavid van Moolenbroek 	pin_release(buf, EVBUFFER_MEM_PINNED_R);
128*e985b929SDavid van Moolenbroek 
129*e985b929SDavid van Moolenbroek 	buf->read_in_progress = 0;
130*e985b929SDavid van Moolenbroek 
131*e985b929SDavid van Moolenbroek 	evbuf->total_len += nBytes;
132*e985b929SDavid van Moolenbroek 	evbuf->n_add_for_cb += nBytes;
133*e985b929SDavid van Moolenbroek 
134*e985b929SDavid van Moolenbroek 	evbuffer_invoke_callbacks(evbuf);
135*e985b929SDavid van Moolenbroek 
136*e985b929SDavid van Moolenbroek 	_evbuffer_decref_and_unlock(evbuf);
137*e985b929SDavid van Moolenbroek }
138*e985b929SDavid van Moolenbroek 
139*e985b929SDavid van Moolenbroek void
evbuffer_commit_write(struct evbuffer * evbuf,ev_ssize_t nBytes)140*e985b929SDavid van Moolenbroek evbuffer_commit_write(struct evbuffer *evbuf, ev_ssize_t nBytes)
141*e985b929SDavid van Moolenbroek {
142*e985b929SDavid van Moolenbroek 	struct evbuffer_overlapped *buf = upcast_evbuffer(evbuf);
143*e985b929SDavid van Moolenbroek 
144*e985b929SDavid van Moolenbroek 	EVBUFFER_LOCK(evbuf);
145*e985b929SDavid van Moolenbroek 	EVUTIL_ASSERT(buf->write_in_progress && !buf->read_in_progress);
146*e985b929SDavid van Moolenbroek 	evbuffer_unfreeze(evbuf, 1);
147*e985b929SDavid van Moolenbroek 	evbuffer_drain(evbuf, nBytes);
148*e985b929SDavid van Moolenbroek 	pin_release(buf,EVBUFFER_MEM_PINNED_W);
149*e985b929SDavid van Moolenbroek 	buf->write_in_progress = 0;
150*e985b929SDavid van Moolenbroek 	_evbuffer_decref_and_unlock(evbuf);
151*e985b929SDavid van Moolenbroek }
152*e985b929SDavid van Moolenbroek 
153*e985b929SDavid van Moolenbroek struct evbuffer *
evbuffer_overlapped_new(evutil_socket_t fd)154*e985b929SDavid van Moolenbroek evbuffer_overlapped_new(evutil_socket_t fd)
155*e985b929SDavid van Moolenbroek {
156*e985b929SDavid van Moolenbroek 	struct evbuffer_overlapped *evo;
157*e985b929SDavid van Moolenbroek 
158*e985b929SDavid van Moolenbroek 	evo = mm_calloc(1, sizeof(struct evbuffer_overlapped));
159*e985b929SDavid van Moolenbroek 	if (!evo)
160*e985b929SDavid van Moolenbroek 		return NULL;
161*e985b929SDavid van Moolenbroek 
162*e985b929SDavid van Moolenbroek 	TAILQ_INIT(&evo->buffer.callbacks);
163*e985b929SDavid van Moolenbroek 	evo->buffer.refcnt = 1;
164*e985b929SDavid van Moolenbroek 	evo->buffer.last_with_datap = &evo->buffer.first;
165*e985b929SDavid van Moolenbroek 
166*e985b929SDavid van Moolenbroek 	evo->buffer.is_overlapped = 1;
167*e985b929SDavid van Moolenbroek 	evo->fd = fd;
168*e985b929SDavid van Moolenbroek 
169*e985b929SDavid van Moolenbroek 	return &evo->buffer;
170*e985b929SDavid van Moolenbroek }
171*e985b929SDavid van Moolenbroek 
172*e985b929SDavid van Moolenbroek int
evbuffer_launch_write(struct evbuffer * buf,ev_ssize_t at_most,struct event_overlapped * ol)173*e985b929SDavid van Moolenbroek evbuffer_launch_write(struct evbuffer *buf, ev_ssize_t at_most,
174*e985b929SDavid van Moolenbroek 		struct event_overlapped *ol)
175*e985b929SDavid van Moolenbroek {
176*e985b929SDavid van Moolenbroek 	struct evbuffer_overlapped *buf_o = upcast_evbuffer(buf);
177*e985b929SDavid van Moolenbroek 	int r = -1;
178*e985b929SDavid van Moolenbroek 	int i;
179*e985b929SDavid van Moolenbroek 	struct evbuffer_chain *chain;
180*e985b929SDavid van Moolenbroek 	DWORD bytesSent;
181*e985b929SDavid van Moolenbroek 
182*e985b929SDavid van Moolenbroek 	if (!buf) {
183*e985b929SDavid van Moolenbroek 		/* No buffer, or it isn't overlapped */
184*e985b929SDavid van Moolenbroek 		return -1;
185*e985b929SDavid van Moolenbroek 	}
186*e985b929SDavid van Moolenbroek 
187*e985b929SDavid van Moolenbroek 	EVBUFFER_LOCK(buf);
188*e985b929SDavid van Moolenbroek 	EVUTIL_ASSERT(!buf_o->read_in_progress);
189*e985b929SDavid van Moolenbroek 	if (buf->freeze_start || buf_o->write_in_progress)
190*e985b929SDavid van Moolenbroek 		goto done;
191*e985b929SDavid van Moolenbroek 	if (!buf->total_len) {
192*e985b929SDavid van Moolenbroek 		/* Nothing to write */
193*e985b929SDavid van Moolenbroek 		r = 0;
194*e985b929SDavid van Moolenbroek 		goto done;
195*e985b929SDavid van Moolenbroek 	} else if (at_most < 0 || (size_t)at_most > buf->total_len) {
196*e985b929SDavid van Moolenbroek 		at_most = buf->total_len;
197*e985b929SDavid van Moolenbroek 	}
198*e985b929SDavid van Moolenbroek 	evbuffer_freeze(buf, 1);
199*e985b929SDavid van Moolenbroek 
200*e985b929SDavid van Moolenbroek 	buf_o->first_pinned = NULL;
201*e985b929SDavid van Moolenbroek 	buf_o->n_buffers = 0;
202*e985b929SDavid van Moolenbroek 	memset(buf_o->buffers, 0, sizeof(buf_o->buffers));
203*e985b929SDavid van Moolenbroek 
204*e985b929SDavid van Moolenbroek 	chain = buf_o->first_pinned = buf->first;
205*e985b929SDavid van Moolenbroek 
206*e985b929SDavid van Moolenbroek 	for (i=0; i < MAX_WSABUFS && chain; ++i, chain=chain->next) {
207*e985b929SDavid van Moolenbroek 		WSABUF *b = &buf_o->buffers[i];
208*e985b929SDavid van Moolenbroek 		b->buf = (char*)( chain->buffer + chain->misalign );
209*e985b929SDavid van Moolenbroek 		_evbuffer_chain_pin(chain, EVBUFFER_MEM_PINNED_W);
210*e985b929SDavid van Moolenbroek 
211*e985b929SDavid van Moolenbroek 		if ((size_t)at_most > chain->off) {
212*e985b929SDavid van Moolenbroek 			/* XXXX Cast is safe for now, since win32 has no
213*e985b929SDavid van Moolenbroek 			   mmaped chains.  But later, we need to have this
214*e985b929SDavid van Moolenbroek 			   add more WSAbufs if chain->off is greater than
215*e985b929SDavid van Moolenbroek 			   ULONG_MAX */
216*e985b929SDavid van Moolenbroek 			b->len = (unsigned long)chain->off;
217*e985b929SDavid van Moolenbroek 			at_most -= chain->off;
218*e985b929SDavid van Moolenbroek 		} else {
219*e985b929SDavid van Moolenbroek 			b->len = (unsigned long)at_most;
220*e985b929SDavid van Moolenbroek 			++i;
221*e985b929SDavid van Moolenbroek 			break;
222*e985b929SDavid van Moolenbroek 		}
223*e985b929SDavid van Moolenbroek 	}
224*e985b929SDavid van Moolenbroek 
225*e985b929SDavid van Moolenbroek 	buf_o->n_buffers = i;
226*e985b929SDavid van Moolenbroek 	_evbuffer_incref(buf);
227*e985b929SDavid van Moolenbroek 	if (WSASend(buf_o->fd, buf_o->buffers, i, &bytesSent, 0,
228*e985b929SDavid van Moolenbroek 		&ol->overlapped, NULL)) {
229*e985b929SDavid van Moolenbroek 		int error = WSAGetLastError();
230*e985b929SDavid van Moolenbroek 		if (error != WSA_IO_PENDING) {
231*e985b929SDavid van Moolenbroek 			/* An actual error. */
232*e985b929SDavid van Moolenbroek 			pin_release(buf_o, EVBUFFER_MEM_PINNED_W);
233*e985b929SDavid van Moolenbroek 			evbuffer_unfreeze(buf, 1);
234*e985b929SDavid van Moolenbroek 			evbuffer_free(buf); /* decref */
235*e985b929SDavid van Moolenbroek 			goto done;
236*e985b929SDavid van Moolenbroek 		}
237*e985b929SDavid van Moolenbroek 	}
238*e985b929SDavid van Moolenbroek 
239*e985b929SDavid van Moolenbroek 	buf_o->write_in_progress = 1;
240*e985b929SDavid van Moolenbroek 	r = 0;
241*e985b929SDavid van Moolenbroek done:
242*e985b929SDavid van Moolenbroek 	EVBUFFER_UNLOCK(buf);
243*e985b929SDavid van Moolenbroek 	return r;
244*e985b929SDavid van Moolenbroek }
245*e985b929SDavid van Moolenbroek 
246*e985b929SDavid van Moolenbroek int
evbuffer_launch_read(struct evbuffer * buf,size_t at_most,struct event_overlapped * ol)247*e985b929SDavid van Moolenbroek evbuffer_launch_read(struct evbuffer *buf, size_t at_most,
248*e985b929SDavid van Moolenbroek 		struct event_overlapped *ol)
249*e985b929SDavid van Moolenbroek {
250*e985b929SDavid van Moolenbroek 	struct evbuffer_overlapped *buf_o = upcast_evbuffer(buf);
251*e985b929SDavid van Moolenbroek 	int r = -1, i;
252*e985b929SDavid van Moolenbroek 	int nvecs;
253*e985b929SDavid van Moolenbroek 	int npin=0;
254*e985b929SDavid van Moolenbroek 	struct evbuffer_chain *chain=NULL, **chainp;
255*e985b929SDavid van Moolenbroek 	DWORD bytesRead;
256*e985b929SDavid van Moolenbroek 	DWORD flags = 0;
257*e985b929SDavid van Moolenbroek 	struct evbuffer_iovec vecs[MAX_WSABUFS];
258*e985b929SDavid van Moolenbroek 
259*e985b929SDavid van Moolenbroek 	if (!buf_o)
260*e985b929SDavid van Moolenbroek 		return -1;
261*e985b929SDavid van Moolenbroek 	EVBUFFER_LOCK(buf);
262*e985b929SDavid van Moolenbroek 	EVUTIL_ASSERT(!buf_o->write_in_progress);
263*e985b929SDavid van Moolenbroek 	if (buf->freeze_end || buf_o->read_in_progress)
264*e985b929SDavid van Moolenbroek 		goto done;
265*e985b929SDavid van Moolenbroek 
266*e985b929SDavid van Moolenbroek 	buf_o->first_pinned = NULL;
267*e985b929SDavid van Moolenbroek 	buf_o->n_buffers = 0;
268*e985b929SDavid van Moolenbroek 	memset(buf_o->buffers, 0, sizeof(buf_o->buffers));
269*e985b929SDavid van Moolenbroek 
270*e985b929SDavid van Moolenbroek 	if (_evbuffer_expand_fast(buf, at_most, MAX_WSABUFS) == -1)
271*e985b929SDavid van Moolenbroek 		goto done;
272*e985b929SDavid van Moolenbroek 	evbuffer_freeze(buf, 0);
273*e985b929SDavid van Moolenbroek 
274*e985b929SDavid van Moolenbroek 	nvecs = _evbuffer_read_setup_vecs(buf, at_most,
275*e985b929SDavid van Moolenbroek 	    vecs, MAX_WSABUFS, &chainp, 1);
276*e985b929SDavid van Moolenbroek 	for (i=0;i<nvecs;++i) {
277*e985b929SDavid van Moolenbroek 		WSABUF_FROM_EVBUFFER_IOV(
278*e985b929SDavid van Moolenbroek 			&buf_o->buffers[i],
279*e985b929SDavid van Moolenbroek 			&vecs[i]);
280*e985b929SDavid van Moolenbroek 	}
281*e985b929SDavid van Moolenbroek 
282*e985b929SDavid van Moolenbroek 	buf_o->n_buffers = nvecs;
283*e985b929SDavid van Moolenbroek 	buf_o->first_pinned = chain = *chainp;
284*e985b929SDavid van Moolenbroek 
285*e985b929SDavid van Moolenbroek 	npin=0;
286*e985b929SDavid van Moolenbroek 	for ( ; chain; chain = chain->next) {
287*e985b929SDavid van Moolenbroek 		_evbuffer_chain_pin(chain, EVBUFFER_MEM_PINNED_R);
288*e985b929SDavid van Moolenbroek 		++npin;
289*e985b929SDavid van Moolenbroek 	}
290*e985b929SDavid van Moolenbroek 	EVUTIL_ASSERT(npin == nvecs);
291*e985b929SDavid van Moolenbroek 
292*e985b929SDavid van Moolenbroek 	_evbuffer_incref(buf);
293*e985b929SDavid van Moolenbroek 	if (WSARecv(buf_o->fd, buf_o->buffers, nvecs, &bytesRead, &flags,
294*e985b929SDavid van Moolenbroek 		    &ol->overlapped, NULL)) {
295*e985b929SDavid van Moolenbroek 		int error = WSAGetLastError();
296*e985b929SDavid van Moolenbroek 		if (error != WSA_IO_PENDING) {
297*e985b929SDavid van Moolenbroek 			/* An actual error. */
298*e985b929SDavid van Moolenbroek 			pin_release(buf_o, EVBUFFER_MEM_PINNED_R);
299*e985b929SDavid van Moolenbroek 			evbuffer_unfreeze(buf, 0);
300*e985b929SDavid van Moolenbroek 			evbuffer_free(buf); /* decref */
301*e985b929SDavid van Moolenbroek 			goto done;
302*e985b929SDavid van Moolenbroek 		}
303*e985b929SDavid van Moolenbroek 	}
304*e985b929SDavid van Moolenbroek 
305*e985b929SDavid van Moolenbroek 	buf_o->read_in_progress = 1;
306*e985b929SDavid van Moolenbroek 	r = 0;
307*e985b929SDavid van Moolenbroek done:
308*e985b929SDavid van Moolenbroek 	EVBUFFER_UNLOCK(buf);
309*e985b929SDavid van Moolenbroek 	return r;
310*e985b929SDavid van Moolenbroek }
311*e985b929SDavid van Moolenbroek 
312*e985b929SDavid van Moolenbroek evutil_socket_t
_evbuffer_overlapped_get_fd(struct evbuffer * buf)313*e985b929SDavid van Moolenbroek _evbuffer_overlapped_get_fd(struct evbuffer *buf)
314*e985b929SDavid van Moolenbroek {
315*e985b929SDavid van Moolenbroek 	struct evbuffer_overlapped *buf_o = upcast_evbuffer(buf);
316*e985b929SDavid van Moolenbroek 	return buf_o ? buf_o->fd : -1;
317*e985b929SDavid van Moolenbroek }
318*e985b929SDavid van Moolenbroek 
319*e985b929SDavid van Moolenbroek void
_evbuffer_overlapped_set_fd(struct evbuffer * buf,evutil_socket_t fd)320*e985b929SDavid van Moolenbroek _evbuffer_overlapped_set_fd(struct evbuffer *buf, evutil_socket_t fd)
321*e985b929SDavid van Moolenbroek {
322*e985b929SDavid van Moolenbroek 	struct evbuffer_overlapped *buf_o = upcast_evbuffer(buf);
323*e985b929SDavid van Moolenbroek 	EVBUFFER_LOCK(buf);
324*e985b929SDavid van Moolenbroek 	/* XXX is this right?, should it cancel current I/O operations? */
325*e985b929SDavid van Moolenbroek 	if (buf_o)
326*e985b929SDavid van Moolenbroek 		buf_o->fd = fd;
327*e985b929SDavid van Moolenbroek 	EVBUFFER_UNLOCK(buf);
328*e985b929SDavid van Moolenbroek }
329