1275970Scy/* 2275970Scy * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson 3275970Scy * 4275970Scy * Redistribution and use in source and binary forms, with or without 5275970Scy * modification, are permitted provided that the following conditions 6275970Scy * are met: 7275970Scy * 1. Redistributions of source code must retain the above copyright 8275970Scy * notice, this list of conditions and the following disclaimer. 9275970Scy * 2. Redistributions in binary form must reproduce the above copyright 10275970Scy * notice, this list of conditions and the following disclaimer in the 11275970Scy * documentation and/or other materials provided with the distribution. 12275970Scy * 3. The name of the author may not be used to endorse or promote products 13275970Scy * derived from this software without specific prior written permission. 14275970Scy * 15275970Scy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16275970Scy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17275970Scy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18275970Scy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19275970Scy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20275970Scy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21275970Scy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22275970Scy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23275970Scy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24275970Scy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25275970Scy */ 26275970Scy 27275970Scy#ifndef IOCP_INTERNAL_H_INCLUDED_ 28275970Scy#define IOCP_INTERNAL_H_INCLUDED_ 29275970Scy 30275970Scy#ifdef __cplusplus 31275970Scyextern "C" { 32275970Scy#endif 33275970Scy 34275970Scystruct event_overlapped; 35275970Scystruct event_iocp_port; 36275970Scystruct evbuffer; 37275970Scytypedef void (*iocp_callback)(struct event_overlapped *, ev_uintptr_t, ev_ssize_t, int success); 38275970Scy 39275970Scy/* This whole file is actually win32 only. We wrap the structures in a win32 40275970Scy * ifdef so that we can test-compile code that uses these interfaces on 41275970Scy * non-win32 platforms. */ 42275970Scy#ifdef _WIN32 43275970Scy 44275970Scy/** 45275970Scy Internal use only. Wraps an OVERLAPPED that we're using for libevent 46275970Scy functionality. Whenever an event_iocp_port gets an event for a given 47275970Scy OVERLAPPED*, it upcasts the pointer to an event_overlapped, and calls the 48275970Scy iocp_callback function with the event_overlapped, the iocp key, and the 49275970Scy number of bytes transferred as arguments. 50275970Scy */ 51275970Scystruct event_overlapped { 52275970Scy OVERLAPPED overlapped; 53275970Scy iocp_callback cb; 54275970Scy}; 55275970Scy 56275970Scy/* Mingw's headers don't define LPFN_ACCEPTEX. */ 57275970Scy 58275970Scytypedef BOOL (WINAPI *AcceptExPtr)(SOCKET, SOCKET, PVOID, DWORD, DWORD, DWORD, LPDWORD, LPOVERLAPPED); 59275970Scytypedef BOOL (WINAPI *ConnectExPtr)(SOCKET, const struct sockaddr *, int, PVOID, DWORD, LPDWORD, LPOVERLAPPED); 60275970Scytypedef void (WINAPI *GetAcceptExSockaddrsPtr)(PVOID, DWORD, DWORD, DWORD, LPSOCKADDR *, LPINT, LPSOCKADDR *, LPINT); 61275970Scy 62275970Scy/** Internal use only. Holds pointers to functions that only some versions of 63275970Scy Windows provide. 64275970Scy */ 65275970Scystruct win32_extension_fns { 66275970Scy AcceptExPtr AcceptEx; 67275970Scy ConnectExPtr ConnectEx; 68275970Scy GetAcceptExSockaddrsPtr GetAcceptExSockaddrs; 69275970Scy}; 70275970Scy 71275970Scy/** 72275970Scy Internal use only. Stores a Windows IO Completion port, along with 73275970Scy related data. 74275970Scy */ 75275970Scystruct event_iocp_port { 76275970Scy /** The port itself */ 77275970Scy HANDLE port; 78275970Scy /* A lock to cover internal structures. */ 79275970Scy CRITICAL_SECTION lock; 80275970Scy /** Number of threads ever open on the port. */ 81275970Scy short n_threads; 82275970Scy /** True iff we're shutting down all the threads on this port */ 83275970Scy short shutdown; 84275970Scy /** How often the threads on this port check for shutdown and other 85275970Scy * conditions */ 86275970Scy long ms; 87275970Scy /* The threads that are waiting for events. */ 88275970Scy HANDLE *threads; 89275970Scy /** Number of threads currently open on this port. */ 90275970Scy short n_live_threads; 91275970Scy /** A semaphore to signal when we are done shutting down. */ 92275970Scy HANDLE *shutdownSemaphore; 93275970Scy}; 94275970Scy 95275970Scyconst struct win32_extension_fns *event_get_win32_extension_fns_(void); 96275970Scy#else 97275970Scy/* Dummy definition so we can test-compile more things on unix. */ 98275970Scystruct event_overlapped { 99275970Scy iocp_callback cb; 100275970Scy}; 101275970Scy#endif 102275970Scy 103275970Scy/** Initialize the fields in an event_overlapped. 104275970Scy 105275970Scy @param overlapped The struct event_overlapped to initialize 106275970Scy @param cb The callback that should be invoked once the IO operation has 107275970Scy finished. 108275970Scy */ 109275970Scyvoid event_overlapped_init_(struct event_overlapped *, iocp_callback cb); 110275970Scy 111275970Scy/** Allocate and return a new evbuffer that supports overlapped IO on a given 112275970Scy socket. The socket must be associated with an IO completion port using 113275970Scy event_iocp_port_associate_. 114275970Scy*/ 115275970Scystruct evbuffer *evbuffer_overlapped_new_(evutil_socket_t fd); 116275970Scy 117275970Scy/** XXXX Document (nickm) */ 118275970Scyevutil_socket_t evbuffer_overlapped_get_fd_(struct evbuffer *buf); 119275970Scy 120275970Scyvoid evbuffer_overlapped_set_fd_(struct evbuffer *buf, evutil_socket_t fd); 121275970Scy 122275970Scy/** Start reading data onto the end of an overlapped evbuffer. 123275970Scy 124275970Scy An evbuffer can only have one read pending at a time. While the read 125275970Scy is in progress, no other data may be added to the end of the buffer. 126275970Scy The buffer must be created with event_overlapped_init_(). 127275970Scy evbuffer_commit_read_() must be called in the completion callback. 128275970Scy 129275970Scy @param buf The buffer to read onto 130275970Scy @param n The number of bytes to try to read. 131275970Scy @param ol Overlapped object with associated completion callback. 132275970Scy @return 0 on success, -1 on error. 133275970Scy */ 134275970Scyint evbuffer_launch_read_(struct evbuffer *buf, size_t n, struct event_overlapped *ol); 135275970Scy 136275970Scy/** Start writing data from the start of an evbuffer. 137275970Scy 138275970Scy An evbuffer can only have one write pending at a time. While the write is 139275970Scy in progress, no other data may be removed from the front of the buffer. 140275970Scy The buffer must be created with event_overlapped_init_(). 141275970Scy evbuffer_commit_write_() must be called in the completion callback. 142275970Scy 143275970Scy @param buf The buffer to read onto 144275970Scy @param n The number of bytes to try to read. 145275970Scy @param ol Overlapped object with associated completion callback. 146275970Scy @return 0 on success, -1 on error. 147275970Scy */ 148275970Scyint evbuffer_launch_write_(struct evbuffer *buf, ev_ssize_t n, struct event_overlapped *ol); 149275970Scy 150275970Scy/** XXX document */ 151275970Scyvoid evbuffer_commit_read_(struct evbuffer *, ev_ssize_t); 152275970Scyvoid evbuffer_commit_write_(struct evbuffer *, ev_ssize_t); 153275970Scy 154275970Scy/** Create an IOCP, and launch its worker threads. Internal use only. 155275970Scy 156275970Scy This interface is unstable, and will change. 157275970Scy */ 158275970Scystruct event_iocp_port *event_iocp_port_launch_(int n_cpus); 159275970Scy 160275970Scy/** Associate a file descriptor with an iocp, such that overlapped IO on the 161275970Scy fd will happen on one of the iocp's worker threads. 162275970Scy*/ 163275970Scyint event_iocp_port_associate_(struct event_iocp_port *port, evutil_socket_t fd, 164275970Scy ev_uintptr_t key); 165275970Scy 166275970Scy/** Tell all threads serving an iocp to stop. Wait for up to waitMsec for all 167275970Scy the threads to finish whatever they're doing. If waitMsec is -1, wait 168275970Scy as long as required. If all the threads are done, free the port and return 169275970Scy 0. Otherwise, return -1. If you get a -1 return value, it is safe to call 170275970Scy this function again. 171275970Scy*/ 172275970Scyint event_iocp_shutdown_(struct event_iocp_port *port, long waitMsec); 173275970Scy 174275970Scy/* FIXME document. */ 175275970Scyint event_iocp_activate_overlapped_(struct event_iocp_port *port, 176275970Scy struct event_overlapped *o, 177275970Scy ev_uintptr_t key, ev_uint32_t n_bytes); 178275970Scy 179275970Scystruct event_base; 180275970Scy/* FIXME document. */ 181275970Scystruct event_iocp_port *event_base_get_iocp_(struct event_base *base); 182275970Scy 183275970Scy/* FIXME document. */ 184275970Scyint event_base_start_iocp_(struct event_base *base, int n_cpus); 185275970Scyvoid event_base_stop_iocp_(struct event_base *base); 186275970Scy 187275970Scy/* FIXME document. */ 188275970Scystruct bufferevent *bufferevent_async_new_(struct event_base *base, 189275970Scy evutil_socket_t fd, int options); 190275970Scy 191275970Scy/* FIXME document. */ 192275970Scyvoid bufferevent_async_set_connected_(struct bufferevent *bev); 193275970Scyint bufferevent_async_can_connect_(struct bufferevent *bev); 194275970Scyint bufferevent_async_connect_(struct bufferevent *bev, evutil_socket_t fd, 195275970Scy const struct sockaddr *sa, int socklen); 196275970Scy 197275970Scy#ifdef __cplusplus 198275970Scy} 199275970Scy#endif 200275970Scy 201275970Scy#endif 202