1 module dast.async.iocp; 2 3 version (Windows) : import dast.async.tcpserver; 4 package import core.sys.windows.windows, 5 core.sys.windows.mswsock; 6 7 package(dast.async) bool checkErr()(int ret, string prefix = null) nothrow { 8 import core.sys.windows.winerror; 9 10 const err = WSAGetLastError(); 11 if (ret != 0 || err == 0) 12 return false; 13 14 if (err == WSAEWOULDBLOCK || err == ERROR_IO_PENDING) 15 return false; 16 onError(text(prefix, " error: code=", err)); 17 return true; 18 } 19 20 enum IocpOperation { 21 accept, 22 connect, 23 read, 24 write, 25 event, 26 close 27 } 28 29 struct IocpContext { 30 OVERLAPPED overlapped; 31 IocpOperation operation; 32 } 33 34 alias LPWSAOVERLAPPED = OVERLAPPED*, 35 GROUP = uint; 36 package alias LPWSAPROTOCOL_INFO = void*; 37 38 immutable { 39 LPFN_ACCEPTEX AcceptEx; 40 extern(Windows) BOOL function(SOCKET, const sockaddr*, int, PVOID, DWORD, LPDWORD, LPOVERLAPPED) nothrow ConnectEx; 41 /* 42 LPFN_DISCONNECTEX DisconnectEx; 43 LPFN_GETACCEPTEXSOCKADDRS GetAcceptexSockAddrs; 44 LPFN_TRANSMITFILE TransmitFile; 45 LPFN_TRANSMITPACKETS TransmitPackets; 46 LPFN_WSARECVMSG WSARecvMsg; 47 LPFN_WSASENDMSG WSASendMsg;*/ 48 } 49 50 shared static this() { 51 auto sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 52 scope (exit) 53 closesocket(sock); 54 sock.getFuncPointer!AcceptEx(WSAID_ACCEPTEX); 55 sock.getFuncPointer!ConnectEx(WSAID_CONNECTEX); 56 /* sock.getFuncPointer!DisconnectEx(WSAID_DISCONNECTEX); 57 sock.getFuncPointer!GetAcceptexSockAddrs(WSAID_GETACCEPTEXSOCKADDRS); 58 sock.getFuncPointer!TransmitFile(WSAID_TRANSMITFILE); 59 sock.getFuncPointer!TransmitPackets(WSAID_TRANSMITPACKETS); 60 sock.getFuncPointer!WSARecvMsg(WSAID_WSARECVMSG); */ 61 } 62 63 private void getFuncPointer(alias pfn)(SOCKET sock, GUID guid) { 64 import std.exception; 65 66 DWORD bytesReturned = void; 67 if (WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, guid.sizeof, 68 cast(void*)&pfn, pfn.sizeof, &bytesReturned, null, null) == SOCKET_ERROR) 69 throw new ErrnoException("Get function failed", WSAGetLastError()); 70 } 71 72 enum : DWORD { 73 IOCPARAM_MASK = 0x7f, 74 IOC_VOID = 0x20000000, 75 IOC_OUT = 0x40000000, 76 IOC_IN = 0x80000000, 77 IOC_INOUT = IOC_IN | IOC_OUT 78 } 79 80 enum { 81 IOC_UNIX = 0x00000000, 82 IOC_WS2 = 0x08000000, 83 IOC_PROTOCOL = 0x10000000, 84 IOC_VENDOR = 0x18000000 85 } 86 87 enum _WSAIORW(int x, int y) = IOC_INOUT | x | y; 88 89 enum SIO_GET_EXTENSION_FUNCTION_POINTER = _WSAIORW!(IOC_WS2, 6); 90 enum WSA_FLAG_OVERLAPPED = 1; 91 92 extern (Windows) nothrow @nogc: 93 94 int WSARecv(SOCKET, LPWSABUF, DWORD, LPDWORD, LPDWORD, LPWSAOVERLAPPED, 95 LPWSAOVERLAPPED_COMPLETION_ROUTINE); 96 int WSARecvDisconnect(SOCKET, LPWSABUF); 97 int WSARecvFrom(SOCKET, LPWSABUF, DWORD, LPDWORD, LPDWORD, SOCKADDR*, LPINT, 98 LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE); 99 100 int WSASend(SOCKET, LPWSABUF, DWORD, LPDWORD, DWORD, LPWSAOVERLAPPED, 101 LPWSAOVERLAPPED_COMPLETION_ROUTINE); 102 int WSASendDisconnect(SOCKET, LPWSABUF); 103 int WSASendTo(SOCKET, LPWSABUF, DWORD, LPDWORD, DWORD, const(SOCKADDR)*, int, 104 LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE); 105 106 int GetQueuedCompletionStatusEx(HANDLE, LPOVERLAPPED_ENTRY, ULONG, PULONG, 107 DWORD, BOOL); 108 109 SOCKET WSASocketW(int af, int type, int protocol, LPWSAPROTOCOL_INFO lpProtocolInfo, GROUP g, DWORD dwFlags); 110 111 alias WSASocket = WSASocketW; 112 alias LPOVERLAPPED_ENTRY = OVERLAPPED_ENTRY*; 113 114 struct OVERLAPPED_ENTRY { 115 ULONG_PTR lpCompletionKey; 116 LPOVERLAPPED lpOverlapped; 117 ULONG_PTR Internal; 118 DWORD dwNumberOfBytesTransferred; 119 }