Commit 2b4f46a3 authored by Kenton Varda's avatar Kenton Varda

Implement async-io for Windows.

parent f5268fb0
...@@ -20,12 +20,15 @@ ...@@ -20,12 +20,15 @@
// THE SOFTWARE. // THE SOFTWARE.
#include "async-io.h" #include "async-io.h"
#include "async-unix.h"
#include "debug.h" #include "debug.h"
#include <kj/compat/gtest.h> #include <kj/compat/gtest.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #if _WIN32
#include <ws2tcpip.h>
#include "windows-sanity.h"
#else
#include <netdb.h> #include <netdb.h>
#endif
namespace kj { namespace kj {
namespace { namespace {
...@@ -95,7 +98,9 @@ TEST(AsyncIo, AddressParsing) { ...@@ -95,7 +98,9 @@ TEST(AsyncIo, AddressParsing) {
EXPECT_EQ("0.0.0.0:0", tryParse(w, network, "0.0.0.0")); EXPECT_EQ("0.0.0.0:0", tryParse(w, network, "0.0.0.0"));
EXPECT_EQ("1.2.3.4:5678", tryParse(w, network, "1.2.3.4", 5678)); EXPECT_EQ("1.2.3.4:5678", tryParse(w, network, "1.2.3.4", 5678));
#if !_WIN32
EXPECT_EQ("unix:foo/bar/baz", tryParse(w, network, "unix:foo/bar/baz")); EXPECT_EQ("unix:foo/bar/baz", tryParse(w, network, "unix:foo/bar/baz"));
#endif
// We can parse services by name... // We can parse services by name...
#if !__ANDROID__ // Service names not supported on Android for some reason? #if !__ANDROID__ // Service names not supported on Android for some reason?
...@@ -220,6 +225,8 @@ TEST(AsyncIo, Timeouts) { ...@@ -220,6 +225,8 @@ TEST(AsyncIo, Timeouts) {
EXPECT_EQ(123, promise2.wait(ioContext.waitScope)); EXPECT_EQ(123, promise2.wait(ioContext.waitScope));
} }
#if !_WIN32 // datagrams not implemented on win32 yet
TEST(AsyncIo, Udp) { TEST(AsyncIo, Udp) {
auto ioContext = setupAsyncIo(); auto ioContext = setupAsyncIo();
...@@ -366,5 +373,7 @@ TEST(AsyncIo, Udp) { ...@@ -366,5 +373,7 @@ TEST(AsyncIo, Udp) {
} }
} }
#endif // !_WIN32
} // namespace } // namespace
} // namespace kj } // namespace kj
This diff is collapsed.
...@@ -19,6 +19,9 @@ ...@@ -19,6 +19,9 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
#if !_WIN32
// For Win32 implementation, see async-io-win32.c++.
#include "async-io.h" #include "async-io.h"
#include "async-unix.h" #include "async-unix.h"
#include "debug.h" #include "debug.h"
...@@ -1381,3 +1384,5 @@ AsyncIoContext setupAsyncIo() { ...@@ -1381,3 +1384,5 @@ AsyncIoContext setupAsyncIo() {
} }
} // namespace kj } // namespace kj
#endif // !_WIN32
...@@ -35,7 +35,12 @@ struct sockaddr; ...@@ -35,7 +35,12 @@ struct sockaddr;
namespace kj { namespace kj {
#if _WIN32
class Win32EventPort;
#else
class UnixEventPort; class UnixEventPort;
#endif
class NetworkAddress; class NetworkAddress;
// ======================================================================================= // =======================================================================================
...@@ -377,6 +382,7 @@ public: ...@@ -377,6 +382,7 @@ public:
// If this flag is not used, then the file descriptor is not automatically closed and the // If this flag is not used, then the file descriptor is not automatically closed and the
// close-on-exec flag is not modified. // close-on-exec flag is not modified.
#if !_WIN32
ALREADY_CLOEXEC = 1 << 1, ALREADY_CLOEXEC = 1 << 1,
// Indicates that the close-on-exec flag is known already to be set, so need not be set again. // Indicates that the close-on-exec flag is known already to be set, so need not be set again.
// Only relevant when combined with TAKE_OWNERSHIP. // Only relevant when combined with TAKE_OWNERSHIP.
...@@ -391,37 +397,56 @@ public: ...@@ -391,37 +397,56 @@ public:
// //
// On Linux, all system calls which yield new file descriptors have flags or variants which // On Linux, all system calls which yield new file descriptors have flags or variants which
// enable non-blocking mode immediately. Unfortunately, other OS's do not. // enable non-blocking mode immediately. Unfortunately, other OS's do not.
#endif
}; };
virtual Own<AsyncInputStream> wrapInputFd(int fd, uint flags = 0) = 0; #if _WIN32
typedef uintptr_t Fd;
// On Windows, the `fd` parameter to each of these methods must be a SOCKET, and must have the
// flag WSA_FLAG_OVERLAPPED (which socket() uses by default, but WSASocket() wants you to specify
// explicitly).
#else
typedef int Fd;
// On Unix, any arbitrary file descriptor is supported.
#endif
virtual Own<AsyncInputStream> wrapInputFd(Fd fd, uint flags = 0) = 0;
// Create an AsyncInputStream wrapping a file descriptor. // Create an AsyncInputStream wrapping a file descriptor.
// //
// `flags` is a bitwise-OR of the values of the `Flags` enum. // `flags` is a bitwise-OR of the values of the `Flags` enum.
virtual Own<AsyncOutputStream> wrapOutputFd(int fd, uint flags = 0) = 0; virtual Own<AsyncOutputStream> wrapOutputFd(Fd fd, uint flags = 0) = 0;
// Create an AsyncOutputStream wrapping a file descriptor. // Create an AsyncOutputStream wrapping a file descriptor.
// //
// `flags` is a bitwise-OR of the values of the `Flags` enum. // `flags` is a bitwise-OR of the values of the `Flags` enum.
virtual Own<AsyncIoStream> wrapSocketFd(int fd, uint flags = 0) = 0; virtual Own<AsyncIoStream> wrapSocketFd(Fd fd, uint flags = 0) = 0;
// Create an AsyncIoStream wrapping a socket file descriptor. // Create an AsyncIoStream wrapping a socket file descriptor.
// //
// `flags` is a bitwise-OR of the values of the `Flags` enum. // `flags` is a bitwise-OR of the values of the `Flags` enum.
virtual Promise<Own<AsyncIoStream>> wrapConnectingSocketFd(int fd, uint flags = 0) = 0; #if _WIN32
virtual Promise<Own<AsyncIoStream>> wrapConnectingSocketFd(
Fd fd, const struct sockaddr* addr, uint addrlen, uint flags = 0) = 0;
#else
virtual Promise<Own<AsyncIoStream>> wrapConnectingSocketFd(Fd fd, uint flags = 0) = 0;
#endif
// Create an AsyncIoStream wrapping a socket that is in the process of connecting. The returned // Create an AsyncIoStream wrapping a socket that is in the process of connecting. The returned
// promise should not resolve until connection has completed -- traditionally indicated by the // promise should not resolve until connection has completed -- traditionally indicated by the
// descriptor becoming writable. // descriptor becoming writable.
// //
// `flags` is a bitwise-OR of the values of the `Flags` enum. // `flags` is a bitwise-OR of the values of the `Flags` enum.
//
// On Windows, the callee initiates connect rather than the caller.
// TODO(now): Maybe on all systems?
virtual Own<ConnectionReceiver> wrapListenSocketFd(int fd, uint flags = 0) = 0; virtual Own<ConnectionReceiver> wrapListenSocketFd(Fd fd, uint flags = 0) = 0;
// Create an AsyncIoStream wrapping a listen socket file descriptor. This socket should already // Create an AsyncIoStream wrapping a listen socket file descriptor. This socket should already
// have had `bind()` and `listen()` called on it, so it's ready for `accept()`. // have had `bind()` and `listen()` called on it, so it's ready for `accept()`.
// //
// `flags` is a bitwise-OR of the values of the `Flags` enum. // `flags` is a bitwise-OR of the values of the `Flags` enum.
virtual Own<DatagramPort> wrapDatagramSocketFd(int fd, uint flags = 0); virtual Own<DatagramPort> wrapDatagramSocketFd(Fd fd, uint flags = 0);
virtual Timer& getTimer() = 0; virtual Timer& getTimer() = 0;
// Returns a `Timer` based on real time. Time does not pass while event handlers are running -- // Returns a `Timer` based on real time. Time does not pass while event handlers are running --
...@@ -440,9 +465,13 @@ struct AsyncIoContext { ...@@ -440,9 +465,13 @@ struct AsyncIoContext {
Own<AsyncIoProvider> provider; Own<AsyncIoProvider> provider;
WaitScope& waitScope; WaitScope& waitScope;
#if _WIN32
Win32EventPort& win32EventPort;
#else
UnixEventPort& unixEventPort; UnixEventPort& unixEventPort;
// TEMPORARY: Direct access to underlying UnixEventPort, mainly for waiting on signals. This // TEMPORARY: Direct access to underlying UnixEventPort, mainly for waiting on signals. This
// field will go away at some point when we have a chance to improve these interfaces. // field will go away at some point when we have a chance to improve these interfaces.
#endif
}; };
AsyncIoContext setupAsyncIo(); AsyncIoContext setupAsyncIo();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment