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