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