12b15cb3dSCy Schubert /* 22b15cb3dSCy Schubert * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson 32b15cb3dSCy Schubert * 42b15cb3dSCy Schubert * Redistribution and use in source and binary forms, with or without 52b15cb3dSCy Schubert * modification, are permitted provided that the following conditions 62b15cb3dSCy Schubert * are met: 72b15cb3dSCy Schubert * 1. Redistributions of source code must retain the above copyright 82b15cb3dSCy Schubert * notice, this list of conditions and the following disclaimer. 92b15cb3dSCy Schubert * 2. Redistributions in binary form must reproduce the above copyright 102b15cb3dSCy Schubert * notice, this list of conditions and the following disclaimer in the 112b15cb3dSCy Schubert * documentation and/or other materials provided with the distribution. 122b15cb3dSCy Schubert * 3. The name of the author may not be used to endorse or promote products 132b15cb3dSCy Schubert * derived from this software without specific prior written permission. 142b15cb3dSCy Schubert * 152b15cb3dSCy Schubert * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 162b15cb3dSCy Schubert * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 172b15cb3dSCy Schubert * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 182b15cb3dSCy Schubert * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 192b15cb3dSCy Schubert * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 202b15cb3dSCy Schubert * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 212b15cb3dSCy Schubert * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 222b15cb3dSCy Schubert * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 232b15cb3dSCy Schubert * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 242b15cb3dSCy Schubert * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 252b15cb3dSCy Schubert */ 262b15cb3dSCy Schubert 272b15cb3dSCy Schubert #ifndef IOCP_INTERNAL_H_INCLUDED_ 282b15cb3dSCy Schubert #define IOCP_INTERNAL_H_INCLUDED_ 292b15cb3dSCy Schubert 302b15cb3dSCy Schubert #ifdef __cplusplus 312b15cb3dSCy Schubert extern "C" { 322b15cb3dSCy Schubert #endif 332b15cb3dSCy Schubert 342b15cb3dSCy Schubert struct event_overlapped; 352b15cb3dSCy Schubert struct event_iocp_port; 362b15cb3dSCy Schubert struct evbuffer; 372b15cb3dSCy Schubert typedef void (*iocp_callback)(struct event_overlapped *, ev_uintptr_t, ev_ssize_t, int success); 382b15cb3dSCy Schubert 392b15cb3dSCy Schubert /* This whole file is actually win32 only. We wrap the structures in a win32 402b15cb3dSCy Schubert * ifdef so that we can test-compile code that uses these interfaces on 412b15cb3dSCy Schubert * non-win32 platforms. */ 422b15cb3dSCy Schubert #ifdef _WIN32 432b15cb3dSCy Schubert 442b15cb3dSCy Schubert /** 452b15cb3dSCy Schubert Internal use only. Wraps an OVERLAPPED that we're using for libevent 462b15cb3dSCy Schubert functionality. Whenever an event_iocp_port gets an event for a given 472b15cb3dSCy Schubert OVERLAPPED*, it upcasts the pointer to an event_overlapped, and calls the 482b15cb3dSCy Schubert iocp_callback function with the event_overlapped, the iocp key, and the 492b15cb3dSCy Schubert number of bytes transferred as arguments. 502b15cb3dSCy Schubert */ 512b15cb3dSCy Schubert struct event_overlapped { 522b15cb3dSCy Schubert OVERLAPPED overlapped; 532b15cb3dSCy Schubert iocp_callback cb; 542b15cb3dSCy Schubert }; 552b15cb3dSCy Schubert 562b15cb3dSCy Schubert /* Mingw's headers don't define LPFN_ACCEPTEX. */ 572b15cb3dSCy Schubert 582b15cb3dSCy Schubert typedef BOOL (WINAPI *AcceptExPtr)(SOCKET, SOCKET, PVOID, DWORD, DWORD, DWORD, LPDWORD, LPOVERLAPPED); 592b15cb3dSCy Schubert typedef BOOL (WINAPI *ConnectExPtr)(SOCKET, const struct sockaddr *, int, PVOID, DWORD, LPDWORD, LPOVERLAPPED); 602b15cb3dSCy Schubert typedef void (WINAPI *GetAcceptExSockaddrsPtr)(PVOID, DWORD, DWORD, DWORD, LPSOCKADDR *, LPINT, LPSOCKADDR *, LPINT); 612b15cb3dSCy Schubert 622b15cb3dSCy Schubert /** Internal use only. Holds pointers to functions that only some versions of 632b15cb3dSCy Schubert Windows provide. 642b15cb3dSCy Schubert */ 652b15cb3dSCy Schubert struct win32_extension_fns { 662b15cb3dSCy Schubert AcceptExPtr AcceptEx; 672b15cb3dSCy Schubert ConnectExPtr ConnectEx; 682b15cb3dSCy Schubert GetAcceptExSockaddrsPtr GetAcceptExSockaddrs; 692b15cb3dSCy Schubert }; 702b15cb3dSCy Schubert 712b15cb3dSCy Schubert /** 722b15cb3dSCy Schubert Internal use only. Stores a Windows IO Completion port, along with 732b15cb3dSCy Schubert related data. 742b15cb3dSCy Schubert */ 752b15cb3dSCy Schubert struct event_iocp_port { 762b15cb3dSCy Schubert /** The port itself */ 772b15cb3dSCy Schubert HANDLE port; 782b15cb3dSCy Schubert /* A lock to cover internal structures. */ 792b15cb3dSCy Schubert CRITICAL_SECTION lock; 802b15cb3dSCy Schubert /** Number of threads ever open on the port. */ 812b15cb3dSCy Schubert short n_threads; 822b15cb3dSCy Schubert /** True iff we're shutting down all the threads on this port */ 832b15cb3dSCy Schubert short shutdown; 842b15cb3dSCy Schubert /** How often the threads on this port check for shutdown and other 852b15cb3dSCy Schubert * conditions */ 862b15cb3dSCy Schubert long ms; 872b15cb3dSCy Schubert /* The threads that are waiting for events. */ 882b15cb3dSCy Schubert HANDLE *threads; 892b15cb3dSCy Schubert /** Number of threads currently open on this port. */ 902b15cb3dSCy Schubert short n_live_threads; 912b15cb3dSCy Schubert /** A semaphore to signal when we are done shutting down. */ 922b15cb3dSCy Schubert HANDLE *shutdownSemaphore; 932b15cb3dSCy Schubert }; 942b15cb3dSCy Schubert 95*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 962b15cb3dSCy Schubert const struct win32_extension_fns *event_get_win32_extension_fns_(void); 972b15cb3dSCy Schubert #else 982b15cb3dSCy Schubert /* Dummy definition so we can test-compile more things on unix. */ 992b15cb3dSCy Schubert struct event_overlapped { 1002b15cb3dSCy Schubert iocp_callback cb; 1012b15cb3dSCy Schubert }; 1022b15cb3dSCy Schubert #endif 1032b15cb3dSCy Schubert 1042b15cb3dSCy Schubert /** Initialize the fields in an event_overlapped. 1052b15cb3dSCy Schubert 1062b15cb3dSCy Schubert @param overlapped The struct event_overlapped to initialize 1072b15cb3dSCy Schubert @param cb The callback that should be invoked once the IO operation has 1082b15cb3dSCy Schubert finished. 1092b15cb3dSCy Schubert */ 110*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 1112b15cb3dSCy Schubert void event_overlapped_init_(struct event_overlapped *, iocp_callback cb); 1122b15cb3dSCy Schubert 1132b15cb3dSCy Schubert /** Allocate and return a new evbuffer that supports overlapped IO on a given 1142b15cb3dSCy Schubert socket. The socket must be associated with an IO completion port using 1152b15cb3dSCy Schubert event_iocp_port_associate_. 1162b15cb3dSCy Schubert */ 117*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 1182b15cb3dSCy Schubert struct evbuffer *evbuffer_overlapped_new_(evutil_socket_t fd); 1192b15cb3dSCy Schubert 1202b15cb3dSCy Schubert /** XXXX Document (nickm) */ 1212b15cb3dSCy Schubert evutil_socket_t evbuffer_overlapped_get_fd_(struct evbuffer *buf); 1222b15cb3dSCy Schubert 1232b15cb3dSCy Schubert void evbuffer_overlapped_set_fd_(struct evbuffer *buf, evutil_socket_t fd); 1242b15cb3dSCy Schubert 1252b15cb3dSCy Schubert /** Start reading data onto the end of an overlapped evbuffer. 1262b15cb3dSCy Schubert 1272b15cb3dSCy Schubert An evbuffer can only have one read pending at a time. While the read 1282b15cb3dSCy Schubert is in progress, no other data may be added to the end of the buffer. 1292b15cb3dSCy Schubert The buffer must be created with event_overlapped_init_(). 1302b15cb3dSCy Schubert evbuffer_commit_read_() must be called in the completion callback. 1312b15cb3dSCy Schubert 1322b15cb3dSCy Schubert @param buf The buffer to read onto 1332b15cb3dSCy Schubert @param n The number of bytes to try to read. 1342b15cb3dSCy Schubert @param ol Overlapped object with associated completion callback. 1352b15cb3dSCy Schubert @return 0 on success, -1 on error. 1362b15cb3dSCy Schubert */ 137*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 1382b15cb3dSCy Schubert int evbuffer_launch_read_(struct evbuffer *buf, size_t n, struct event_overlapped *ol); 1392b15cb3dSCy Schubert 1402b15cb3dSCy Schubert /** Start writing data from the start of an evbuffer. 1412b15cb3dSCy Schubert 1422b15cb3dSCy Schubert An evbuffer can only have one write pending at a time. While the write is 1432b15cb3dSCy Schubert in progress, no other data may be removed from the front of the buffer. 1442b15cb3dSCy Schubert The buffer must be created with event_overlapped_init_(). 1452b15cb3dSCy Schubert evbuffer_commit_write_() must be called in the completion callback. 1462b15cb3dSCy Schubert 1472b15cb3dSCy Schubert @param buf The buffer to read onto 1482b15cb3dSCy Schubert @param n The number of bytes to try to read. 1492b15cb3dSCy Schubert @param ol Overlapped object with associated completion callback. 1502b15cb3dSCy Schubert @return 0 on success, -1 on error. 1512b15cb3dSCy Schubert */ 152*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 1532b15cb3dSCy Schubert int evbuffer_launch_write_(struct evbuffer *buf, ev_ssize_t n, struct event_overlapped *ol); 1542b15cb3dSCy Schubert 1552b15cb3dSCy Schubert /** XXX document */ 156*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 1572b15cb3dSCy Schubert void evbuffer_commit_read_(struct evbuffer *, ev_ssize_t); 158*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 1592b15cb3dSCy Schubert void evbuffer_commit_write_(struct evbuffer *, ev_ssize_t); 1602b15cb3dSCy Schubert 1612b15cb3dSCy Schubert /** Create an IOCP, and launch its worker threads. Internal use only. 1622b15cb3dSCy Schubert 1632b15cb3dSCy Schubert This interface is unstable, and will change. 1642b15cb3dSCy Schubert */ 165*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 1662b15cb3dSCy Schubert struct event_iocp_port *event_iocp_port_launch_(int n_cpus); 1672b15cb3dSCy Schubert 1682b15cb3dSCy Schubert /** Associate a file descriptor with an iocp, such that overlapped IO on the 1692b15cb3dSCy Schubert fd will happen on one of the iocp's worker threads. 1702b15cb3dSCy Schubert */ 171*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 1722b15cb3dSCy Schubert int event_iocp_port_associate_(struct event_iocp_port *port, evutil_socket_t fd, 1732b15cb3dSCy Schubert ev_uintptr_t key); 1742b15cb3dSCy Schubert 1752b15cb3dSCy Schubert /** Tell all threads serving an iocp to stop. Wait for up to waitMsec for all 1762b15cb3dSCy Schubert the threads to finish whatever they're doing. If waitMsec is -1, wait 1772b15cb3dSCy Schubert as long as required. If all the threads are done, free the port and return 1782b15cb3dSCy Schubert 0. Otherwise, return -1. If you get a -1 return value, it is safe to call 1792b15cb3dSCy Schubert this function again. 1802b15cb3dSCy Schubert */ 181*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 1822b15cb3dSCy Schubert int event_iocp_shutdown_(struct event_iocp_port *port, long waitMsec); 1832b15cb3dSCy Schubert 1842b15cb3dSCy Schubert /* FIXME document. */ 185*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 1862b15cb3dSCy Schubert int event_iocp_activate_overlapped_(struct event_iocp_port *port, 1872b15cb3dSCy Schubert struct event_overlapped *o, 1882b15cb3dSCy Schubert ev_uintptr_t key, ev_uint32_t n_bytes); 1892b15cb3dSCy Schubert 1902b15cb3dSCy Schubert struct event_base; 1912b15cb3dSCy Schubert /* FIXME document. */ 192*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 1932b15cb3dSCy Schubert struct event_iocp_port *event_base_get_iocp_(struct event_base *base); 1942b15cb3dSCy Schubert 1952b15cb3dSCy Schubert /* FIXME document. */ 196*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 1972b15cb3dSCy Schubert int event_base_start_iocp_(struct event_base *base, int n_cpus); 1982b15cb3dSCy Schubert void event_base_stop_iocp_(struct event_base *base); 1992b15cb3dSCy Schubert 2002b15cb3dSCy Schubert /* FIXME document. */ 201*a466cc55SCy Schubert EVENT2_EXPORT_SYMBOL 2022b15cb3dSCy Schubert struct bufferevent *bufferevent_async_new_(struct event_base *base, 2032b15cb3dSCy Schubert evutil_socket_t fd, int options); 2042b15cb3dSCy Schubert 2052b15cb3dSCy Schubert /* FIXME document. */ 2062b15cb3dSCy Schubert void bufferevent_async_set_connected_(struct bufferevent *bev); 2072b15cb3dSCy Schubert int bufferevent_async_can_connect_(struct bufferevent *bev); 2082b15cb3dSCy Schubert int bufferevent_async_connect_(struct bufferevent *bev, evutil_socket_t fd, 2092b15cb3dSCy Schubert const struct sockaddr *sa, int socklen); 2102b15cb3dSCy Schubert 2112b15cb3dSCy Schubert #ifdef __cplusplus 2122b15cb3dSCy Schubert } 2132b15cb3dSCy Schubert #endif 2142b15cb3dSCy Schubert 2152b15cb3dSCy Schubert #endif 216