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 #ifndef IOCP_INTERNAL_H_INCLUDED_ 28*c43e99fdSEd Maste #define IOCP_INTERNAL_H_INCLUDED_ 29*c43e99fdSEd Maste 30*c43e99fdSEd Maste #ifdef __cplusplus 31*c43e99fdSEd Maste extern "C" { 32*c43e99fdSEd Maste #endif 33*c43e99fdSEd Maste 34*c43e99fdSEd Maste struct event_overlapped; 35*c43e99fdSEd Maste struct event_iocp_port; 36*c43e99fdSEd Maste struct evbuffer; 37*c43e99fdSEd Maste typedef void (*iocp_callback)(struct event_overlapped *, ev_uintptr_t, ev_ssize_t, int success); 38*c43e99fdSEd Maste 39*c43e99fdSEd Maste /* This whole file is actually win32 only. We wrap the structures in a win32 40*c43e99fdSEd Maste * ifdef so that we can test-compile code that uses these interfaces on 41*c43e99fdSEd Maste * non-win32 platforms. */ 42*c43e99fdSEd Maste #ifdef _WIN32 43*c43e99fdSEd Maste 44*c43e99fdSEd Maste /** 45*c43e99fdSEd Maste Internal use only. Wraps an OVERLAPPED that we're using for libevent 46*c43e99fdSEd Maste functionality. Whenever an event_iocp_port gets an event for a given 47*c43e99fdSEd Maste OVERLAPPED*, it upcasts the pointer to an event_overlapped, and calls the 48*c43e99fdSEd Maste iocp_callback function with the event_overlapped, the iocp key, and the 49*c43e99fdSEd Maste number of bytes transferred as arguments. 50*c43e99fdSEd Maste */ 51*c43e99fdSEd Maste struct event_overlapped { 52*c43e99fdSEd Maste OVERLAPPED overlapped; 53*c43e99fdSEd Maste iocp_callback cb; 54*c43e99fdSEd Maste }; 55*c43e99fdSEd Maste 56*c43e99fdSEd Maste /* Mingw's headers don't define LPFN_ACCEPTEX. */ 57*c43e99fdSEd Maste 58*c43e99fdSEd Maste typedef BOOL (WINAPI *AcceptExPtr)(SOCKET, SOCKET, PVOID, DWORD, DWORD, DWORD, LPDWORD, LPOVERLAPPED); 59*c43e99fdSEd Maste typedef BOOL (WINAPI *ConnectExPtr)(SOCKET, const struct sockaddr *, int, PVOID, DWORD, LPDWORD, LPOVERLAPPED); 60*c43e99fdSEd Maste typedef void (WINAPI *GetAcceptExSockaddrsPtr)(PVOID, DWORD, DWORD, DWORD, LPSOCKADDR *, LPINT, LPSOCKADDR *, LPINT); 61*c43e99fdSEd Maste 62*c43e99fdSEd Maste /** Internal use only. Holds pointers to functions that only some versions of 63*c43e99fdSEd Maste Windows provide. 64*c43e99fdSEd Maste */ 65*c43e99fdSEd Maste struct win32_extension_fns { 66*c43e99fdSEd Maste AcceptExPtr AcceptEx; 67*c43e99fdSEd Maste ConnectExPtr ConnectEx; 68*c43e99fdSEd Maste GetAcceptExSockaddrsPtr GetAcceptExSockaddrs; 69*c43e99fdSEd Maste }; 70*c43e99fdSEd Maste 71*c43e99fdSEd Maste /** 72*c43e99fdSEd Maste Internal use only. Stores a Windows IO Completion port, along with 73*c43e99fdSEd Maste related data. 74*c43e99fdSEd Maste */ 75*c43e99fdSEd Maste struct event_iocp_port { 76*c43e99fdSEd Maste /** The port itself */ 77*c43e99fdSEd Maste HANDLE port; 78*c43e99fdSEd Maste /* A lock to cover internal structures. */ 79*c43e99fdSEd Maste CRITICAL_SECTION lock; 80*c43e99fdSEd Maste /** Number of threads ever open on the port. */ 81*c43e99fdSEd Maste short n_threads; 82*c43e99fdSEd Maste /** True iff we're shutting down all the threads on this port */ 83*c43e99fdSEd Maste short shutdown; 84*c43e99fdSEd Maste /** How often the threads on this port check for shutdown and other 85*c43e99fdSEd Maste * conditions */ 86*c43e99fdSEd Maste long ms; 87*c43e99fdSEd Maste /* The threads that are waiting for events. */ 88*c43e99fdSEd Maste HANDLE *threads; 89*c43e99fdSEd Maste /** Number of threads currently open on this port. */ 90*c43e99fdSEd Maste short n_live_threads; 91*c43e99fdSEd Maste /** A semaphore to signal when we are done shutting down. */ 92*c43e99fdSEd Maste HANDLE *shutdownSemaphore; 93*c43e99fdSEd Maste }; 94*c43e99fdSEd Maste 95*c43e99fdSEd Maste const struct win32_extension_fns *event_get_win32_extension_fns_(void); 96*c43e99fdSEd Maste #else 97*c43e99fdSEd Maste /* Dummy definition so we can test-compile more things on unix. */ 98*c43e99fdSEd Maste struct event_overlapped { 99*c43e99fdSEd Maste iocp_callback cb; 100*c43e99fdSEd Maste }; 101*c43e99fdSEd Maste #endif 102*c43e99fdSEd Maste 103*c43e99fdSEd Maste /** Initialize the fields in an event_overlapped. 104*c43e99fdSEd Maste 105*c43e99fdSEd Maste @param overlapped The struct event_overlapped to initialize 106*c43e99fdSEd Maste @param cb The callback that should be invoked once the IO operation has 107*c43e99fdSEd Maste finished. 108*c43e99fdSEd Maste */ 109*c43e99fdSEd Maste void event_overlapped_init_(struct event_overlapped *, iocp_callback cb); 110*c43e99fdSEd Maste 111*c43e99fdSEd Maste /** Allocate and return a new evbuffer that supports overlapped IO on a given 112*c43e99fdSEd Maste socket. The socket must be associated with an IO completion port using 113*c43e99fdSEd Maste event_iocp_port_associate_. 114*c43e99fdSEd Maste */ 115*c43e99fdSEd Maste struct evbuffer *evbuffer_overlapped_new_(evutil_socket_t fd); 116*c43e99fdSEd Maste 117*c43e99fdSEd Maste /** XXXX Document (nickm) */ 118*c43e99fdSEd Maste evutil_socket_t evbuffer_overlapped_get_fd_(struct evbuffer *buf); 119*c43e99fdSEd Maste 120*c43e99fdSEd Maste void evbuffer_overlapped_set_fd_(struct evbuffer *buf, evutil_socket_t fd); 121*c43e99fdSEd Maste 122*c43e99fdSEd Maste /** Start reading data onto the end of an overlapped evbuffer. 123*c43e99fdSEd Maste 124*c43e99fdSEd Maste An evbuffer can only have one read pending at a time. While the read 125*c43e99fdSEd Maste is in progress, no other data may be added to the end of the buffer. 126*c43e99fdSEd Maste The buffer must be created with event_overlapped_init_(). 127*c43e99fdSEd Maste evbuffer_commit_read_() must be called in the completion callback. 128*c43e99fdSEd Maste 129*c43e99fdSEd Maste @param buf The buffer to read onto 130*c43e99fdSEd Maste @param n The number of bytes to try to read. 131*c43e99fdSEd Maste @param ol Overlapped object with associated completion callback. 132*c43e99fdSEd Maste @return 0 on success, -1 on error. 133*c43e99fdSEd Maste */ 134*c43e99fdSEd Maste int evbuffer_launch_read_(struct evbuffer *buf, size_t n, struct event_overlapped *ol); 135*c43e99fdSEd Maste 136*c43e99fdSEd Maste /** Start writing data from the start of an evbuffer. 137*c43e99fdSEd Maste 138*c43e99fdSEd Maste An evbuffer can only have one write pending at a time. While the write is 139*c43e99fdSEd Maste in progress, no other data may be removed from the front of the buffer. 140*c43e99fdSEd Maste The buffer must be created with event_overlapped_init_(). 141*c43e99fdSEd Maste evbuffer_commit_write_() must be called in the completion callback. 142*c43e99fdSEd Maste 143*c43e99fdSEd Maste @param buf The buffer to read onto 144*c43e99fdSEd Maste @param n The number of bytes to try to read. 145*c43e99fdSEd Maste @param ol Overlapped object with associated completion callback. 146*c43e99fdSEd Maste @return 0 on success, -1 on error. 147*c43e99fdSEd Maste */ 148*c43e99fdSEd Maste int evbuffer_launch_write_(struct evbuffer *buf, ev_ssize_t n, struct event_overlapped *ol); 149*c43e99fdSEd Maste 150*c43e99fdSEd Maste /** XXX document */ 151*c43e99fdSEd Maste void evbuffer_commit_read_(struct evbuffer *, ev_ssize_t); 152*c43e99fdSEd Maste void evbuffer_commit_write_(struct evbuffer *, ev_ssize_t); 153*c43e99fdSEd Maste 154*c43e99fdSEd Maste /** Create an IOCP, and launch its worker threads. Internal use only. 155*c43e99fdSEd Maste 156*c43e99fdSEd Maste This interface is unstable, and will change. 157*c43e99fdSEd Maste */ 158*c43e99fdSEd Maste struct event_iocp_port *event_iocp_port_launch_(int n_cpus); 159*c43e99fdSEd Maste 160*c43e99fdSEd Maste /** Associate a file descriptor with an iocp, such that overlapped IO on the 161*c43e99fdSEd Maste fd will happen on one of the iocp's worker threads. 162*c43e99fdSEd Maste */ 163*c43e99fdSEd Maste int event_iocp_port_associate_(struct event_iocp_port *port, evutil_socket_t fd, 164*c43e99fdSEd Maste ev_uintptr_t key); 165*c43e99fdSEd Maste 166*c43e99fdSEd Maste /** Tell all threads serving an iocp to stop. Wait for up to waitMsec for all 167*c43e99fdSEd Maste the threads to finish whatever they're doing. If waitMsec is -1, wait 168*c43e99fdSEd Maste as long as required. If all the threads are done, free the port and return 169*c43e99fdSEd Maste 0. Otherwise, return -1. If you get a -1 return value, it is safe to call 170*c43e99fdSEd Maste this function again. 171*c43e99fdSEd Maste */ 172*c43e99fdSEd Maste int event_iocp_shutdown_(struct event_iocp_port *port, long waitMsec); 173*c43e99fdSEd Maste 174*c43e99fdSEd Maste /* FIXME document. */ 175*c43e99fdSEd Maste int event_iocp_activate_overlapped_(struct event_iocp_port *port, 176*c43e99fdSEd Maste struct event_overlapped *o, 177*c43e99fdSEd Maste ev_uintptr_t key, ev_uint32_t n_bytes); 178*c43e99fdSEd Maste 179*c43e99fdSEd Maste struct event_base; 180*c43e99fdSEd Maste /* FIXME document. */ 181*c43e99fdSEd Maste struct event_iocp_port *event_base_get_iocp_(struct event_base *base); 182*c43e99fdSEd Maste 183*c43e99fdSEd Maste /* FIXME document. */ 184*c43e99fdSEd Maste int event_base_start_iocp_(struct event_base *base, int n_cpus); 185*c43e99fdSEd Maste void event_base_stop_iocp_(struct event_base *base); 186*c43e99fdSEd Maste 187*c43e99fdSEd Maste /* FIXME document. */ 188*c43e99fdSEd Maste struct bufferevent *bufferevent_async_new_(struct event_base *base, 189*c43e99fdSEd Maste evutil_socket_t fd, int options); 190*c43e99fdSEd Maste 191*c43e99fdSEd Maste /* FIXME document. */ 192*c43e99fdSEd Maste void bufferevent_async_set_connected_(struct bufferevent *bev); 193*c43e99fdSEd Maste int bufferevent_async_can_connect_(struct bufferevent *bev); 194*c43e99fdSEd Maste int bufferevent_async_connect_(struct bufferevent *bev, evutil_socket_t fd, 195*c43e99fdSEd Maste const struct sockaddr *sa, int socklen); 196*c43e99fdSEd Maste 197*c43e99fdSEd Maste #ifdef __cplusplus 198*c43e99fdSEd Maste } 199*c43e99fdSEd Maste #endif 200*c43e99fdSEd Maste 201*c43e99fdSEd Maste #endif 202