iocp-internal.h revision 285612
166458Sdfr/* 266458Sdfr * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson 366458Sdfr * 466458Sdfr * Redistribution and use in source and binary forms, with or without 566458Sdfr * modification, are permitted provided that the following conditions 666458Sdfr * are met: 766458Sdfr * 1. Redistributions of source code must retain the above copyright 866458Sdfr * notice, this list of conditions and the following disclaimer. 966458Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1066458Sdfr * notice, this list of conditions and the following disclaimer in the 1166458Sdfr * documentation and/or other materials provided with the distribution. 1266458Sdfr * 3. The name of the author may not be used to endorse or promote products 1366458Sdfr * derived from this software without specific prior written permission. 1466458Sdfr * 1566458Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1666458Sdfr * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1766458Sdfr * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1866458Sdfr * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1966458Sdfr * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2066458Sdfr * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2166458Sdfr * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2266458Sdfr * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2366458Sdfr * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2466458Sdfr * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2566458Sdfr */ 2666458Sdfr 2766458Sdfr#ifndef IOCP_INTERNAL_H_INCLUDED_ 2866458Sdfr#define IOCP_INTERNAL_H_INCLUDED_ 2966458Sdfr 3066458Sdfr#ifdef __cplusplus 3166458Sdfrextern "C" { 3266458Sdfr#endif 3366458Sdfr 3466458Sdfrstruct event_overlapped; 3583511Sdfrstruct event_iocp_port; 3666458Sdfrstruct evbuffer; 3788088Sjhbtypedef void (*iocp_callback)(struct event_overlapped *, ev_uintptr_t, ev_ssize_t, int success); 3888088Sjhb 3966458Sdfr/* This whole file is actually win32 only. We wrap the structures in a win32 4066458Sdfr * ifdef so that we can test-compile code that uses these interfaces on 4166458Sdfr * non-win32 platforms. */ 4266458Sdfr#ifdef _WIN32 4366458Sdfr 4466458Sdfr/** 4566458Sdfr Internal use only. Wraps an OVERLAPPED that we're using for libevent 4666458Sdfr functionality. Whenever an event_iocp_port gets an event for a given 4766458Sdfr OVERLAPPED*, it upcasts the pointer to an event_overlapped, and calls the 4866458Sdfr iocp_callback function with the event_overlapped, the iocp key, and the 4983511Sdfr number of bytes transferred as arguments. 5083511Sdfr */ 5183511Sdfrstruct event_overlapped { 5283511Sdfr OVERLAPPED overlapped; 5383511Sdfr iocp_callback cb; 5483511Sdfr}; 5583511Sdfr 5683511Sdfr/* Mingw's headers don't define LPFN_ACCEPTEX. */ 5783511Sdfr 5883511Sdfrtypedef BOOL (WINAPI *AcceptExPtr)(SOCKET, SOCKET, PVOID, DWORD, DWORD, DWORD, LPDWORD, LPOVERLAPPED); 5983836Sdfrtypedef BOOL (WINAPI *ConnectExPtr)(SOCKET, const struct sockaddr *, int, PVOID, DWORD, LPDWORD, LPOVERLAPPED); 6084581Smarceltypedef void (WINAPI *GetAcceptExSockaddrsPtr)(PVOID, DWORD, DWORD, DWORD, LPSOCKADDR *, LPINT, LPSOCKADDR *, LPINT); 6183836Sdfr 6284581Smarcel/** Internal use only. Holds pointers to functions that only some versions of 6383836Sdfr Windows provide. 6483836Sdfr */ 6566458Sdfrstruct win32_extension_fns { 6666458Sdfr AcceptExPtr AcceptEx; 6766458Sdfr ConnectExPtr ConnectEx; 6883511Sdfr GetAcceptExSockaddrsPtr GetAcceptExSockaddrs; 6983511Sdfr}; 7083511Sdfr 7183511Sdfr/** 7283511Sdfr Internal use only. Stores a Windows IO Completion port, along with 7366458Sdfr related data. 7466458Sdfr */ 7566458Sdfrstruct event_iocp_port { 7666458Sdfr /** The port itself */ 7766458Sdfr HANDLE port; 7883511Sdfr /* A lock to cover internal structures. */ 7983511Sdfr CRITICAL_SECTION lock; 8083511Sdfr /** Number of threads ever open on the port. */ 8183511Sdfr short n_threads; 8283511Sdfr /** True iff we're shutting down all the threads on this port */ 8366458Sdfr short shutdown; 8466458Sdfr /** How often the threads on this port check for shutdown and other 8566458Sdfr * conditions */ 8666458Sdfr long ms; 8766458Sdfr /* The threads that are waiting for events. */ 8883511Sdfr HANDLE *threads; 8983511Sdfr /** Number of threads currently open on this port. */ 9083511Sdfr short n_live_threads; 9183511Sdfr /** A semaphore to signal when we are done shutting down. */ 9283511Sdfr HANDLE *shutdownSemaphore; 9366458Sdfr}; 9466458Sdfr 9566458Sdfrconst struct win32_extension_fns *event_get_win32_extension_fns_(void); 9666458Sdfr#else 9766458Sdfr/* Dummy definition so we can test-compile more things on unix. */ 9866458Sdfrstruct event_overlapped { 9966458Sdfr iocp_callback cb; 10066458Sdfr}; 10166458Sdfr#endif 10266458Sdfr 10366458Sdfr/** Initialize the fields in an event_overlapped. 10466458Sdfr 10566458Sdfr @param overlapped The struct event_overlapped to initialize 10666458Sdfr @param cb The callback that should be invoked once the IO operation has 10766458Sdfr finished. 10866458Sdfr */ 10966458Sdfrvoid event_overlapped_init_(struct event_overlapped *, iocp_callback cb); 11066458Sdfr 11166458Sdfr/** Allocate and return a new evbuffer that supports overlapped IO on a given 11266458Sdfr socket. The socket must be associated with an IO completion port using 11366458Sdfr event_iocp_port_associate_. 11466458Sdfr*/ 11566458Sdfrstruct evbuffer *evbuffer_overlapped_new_(evutil_socket_t fd); 11666458Sdfr 11766458Sdfr/** XXXX Document (nickm) */ 11866458Sdfrevutil_socket_t evbuffer_overlapped_get_fd_(struct evbuffer *buf); 11966458Sdfr 12066458Sdfrvoid evbuffer_overlapped_set_fd_(struct evbuffer *buf, evutil_socket_t fd); 12166458Sdfr 12283511Sdfr/** Start reading data onto the end of an overlapped evbuffer. 12383511Sdfr 12483511Sdfr An evbuffer can only have one read pending at a time. While the read 12583511Sdfr is in progress, no other data may be added to the end of the buffer. 12666458Sdfr The buffer must be created with event_overlapped_init_(). 12766458Sdfr evbuffer_commit_read_() must be called in the completion callback. 12866458Sdfr 12966458Sdfr @param buf The buffer to read onto 13066458Sdfr @param n The number of bytes to try to read. 13183511Sdfr @param ol Overlapped object with associated completion callback. 13283511Sdfr @return 0 on success, -1 on error. 13383511Sdfr */ 13483511Sdfrint evbuffer_launch_read_(struct evbuffer *buf, size_t n, struct event_overlapped *ol); 13566458Sdfr 13666458Sdfr/** Start writing data from the start of an evbuffer. 13766458Sdfr 13866458Sdfr An evbuffer can only have one write pending at a time. While the write is 13966458Sdfr in progress, no other data may be removed from the front of the buffer. 14083511Sdfr The buffer must be created with event_overlapped_init_(). 14183511Sdfr evbuffer_commit_write_() must be called in the completion callback. 14283511Sdfr 14383511Sdfr @param buf The buffer to read onto 14466458Sdfr @param n The number of bytes to try to read. 14566458Sdfr @param ol Overlapped object with associated completion callback. 14666458Sdfr @return 0 on success, -1 on error. 14766458Sdfr */ 14866458Sdfrint evbuffer_launch_write_(struct evbuffer *buf, ev_ssize_t n, struct event_overlapped *ol); 14966458Sdfr 15066458Sdfr/** XXX document */ 15166458Sdfrvoid evbuffer_commit_read_(struct evbuffer *, ev_ssize_t); 15266458Sdfrvoid evbuffer_commit_write_(struct evbuffer *, ev_ssize_t); 15366458Sdfr 15466458Sdfr/** Create an IOCP, and launch its worker threads. Internal use only. 15566458Sdfr 15666458Sdfr This interface is unstable, and will change. 15766458Sdfr */ 15866458Sdfrstruct event_iocp_port *event_iocp_port_launch_(int n_cpus); 15966458Sdfr 16066458Sdfr/** Associate a file descriptor with an iocp, such that overlapped IO on the 16166458Sdfr fd will happen on one of the iocp's worker threads. 16266458Sdfr*/ 16366458Sdfrint event_iocp_port_associate_(struct event_iocp_port *port, evutil_socket_t fd, 16466458Sdfr ev_uintptr_t key); 16566458Sdfr 16666458Sdfr/** Tell all threads serving an iocp to stop. Wait for up to waitMsec for all 16766458Sdfr the threads to finish whatever they're doing. If waitMsec is -1, wait 16866458Sdfr as long as required. If all the threads are done, free the port and return 16966458Sdfr 0. Otherwise, return -1. If you get a -1 return value, it is safe to call 17066458Sdfr this function again. 17166458Sdfr*/ 17266458Sdfrint event_iocp_shutdown_(struct event_iocp_port *port, long waitMsec); 17383836Sdfr 17483836Sdfr/* FIXME document. */ 17583836Sdfrint event_iocp_activate_overlapped_(struct event_iocp_port *port, 17683836Sdfr struct event_overlapped *o, 17783836Sdfr ev_uintptr_t key, ev_uint32_t n_bytes); 17866458Sdfr 17966458Sdfrstruct event_base; 18066458Sdfr/* FIXME document. */ 18166458Sdfrstruct event_iocp_port *event_base_get_iocp_(struct event_base *base); 18266458Sdfr 18383836Sdfr/* FIXME document. */ 18483836Sdfrint event_base_start_iocp_(struct event_base *base, int n_cpus); 18583836Sdfrvoid event_base_stop_iocp_(struct event_base *base); 18683836Sdfr 18783836Sdfr/* FIXME document. */ 18866458Sdfrstruct bufferevent *bufferevent_async_new_(struct event_base *base, 18966458Sdfr evutil_socket_t fd, int options); 19066458Sdfr 19166458Sdfr/* FIXME document. */ 19266458Sdfrvoid bufferevent_async_set_connected_(struct bufferevent *bev); 19383836Sdfrint bufferevent_async_can_connect_(struct bufferevent *bev); 19483836Sdfrint bufferevent_async_connect_(struct bufferevent *bev, evutil_socket_t fd, 19583836Sdfr const struct sockaddr *sa, int socklen); 19683836Sdfr 19783836Sdfr#ifdef __cplusplus 19866458Sdfr} 19966458Sdfr#endif 20066458Sdfr 20166458Sdfr#endif 20266458Sdfr