1 module hunt.io.channel.iocp.AbstractListener; 2 3 // dfmt off 4 version (HAVE_IOCP) : 5 // dfmt on 6 7 import hunt.event.selector.Selector; 8 import hunt.io.channel.AbstractSocketChannel; 9 import hunt.io.channel.Common; 10 import hunt.io.channel.iocp.Common; 11 import hunt.logging; 12 import hunt.Functions; 13 14 import core.sys.windows.windows; 15 import core.sys.windows.winsock2; 16 import core.sys.windows.mswsock; 17 18 import std.socket; 19 20 21 22 /** 23 TCP Server 24 */ 25 abstract class AbstractListener : AbstractSocketChannel { 26 this(Selector loop, AddressFamily family = AddressFamily.INET, size_t bufferSize = 4 * 1024) { 27 super(loop, ChannelType.Accept); 28 setFlag(ChannelFlag.Read, true); 29 _buffer = new ubyte[bufferSize]; 30 this.socket = new TcpSocket(family); 31 32 loadWinsockExtension(this.handle); 33 } 34 35 mixin CheckIocpError; 36 37 protected void doAccept() { 38 _iocp.channel = this; 39 _iocp.operation = IocpOperation.accept; 40 _clientSocket = new Socket(this.localAddress.addressFamily, 41 SocketType.STREAM, ProtocolType.TCP); 42 DWORD dwBytesReceived = 0; 43 44 version (HUNT_DEBUG) { 45 tracef("client socket: acceptor=%s inner socket=%s", this.handle, 46 _clientSocket.handle()); 47 // info("AcceptEx@", AcceptEx); 48 } 49 uint sockaddrSize = cast(uint) sockaddr_storage.sizeof; 50 // https://docs.microsoft.com/en-us/windows/desktop/api/mswsock/nf-mswsock-acceptex 51 BOOL ret = AcceptEx(this.handle, cast(SOCKET) _clientSocket.handle, _buffer.ptr, 52 0, sockaddrSize + 16, sockaddrSize + 16, &dwBytesReceived, &_iocp.overlapped); 53 version (HUNT_DEBUG) 54 trace("AcceptEx return: ", ret); 55 checkErro(ret, FALSE); 56 } 57 58 protected bool onAccept(scope AcceptHandler handler) { 59 version (HUNT_DEBUG) 60 trace("a new connection coming..."); 61 this.clearError(); 62 SOCKET slisten = cast(SOCKET) this.handle; 63 SOCKET slink = cast(SOCKET) this._clientSocket.handle; 64 // void[] value = (&slisten)[0..1]; 65 // setsockopt(slink, SocketOptionLevel.SOCKET, 0x700B, value.ptr, 66 // cast(uint) value.length); 67 version (HUNT_DEBUG) 68 tracef("slisten=%s, slink=%s", slisten, slink); 69 setsockopt(slink, SocketOptionLevel.SOCKET, 0x700B, cast(void*)&slisten, slisten.sizeof); 70 if (handler !is null) 71 handler(this._clientSocket); 72 73 version (HUNT_DEBUG) 74 trace("accepting next connection..."); 75 if (this.isRegistered) 76 this.doAccept(); 77 return true; 78 } 79 80 override void onClose() { 81 82 // version (HUNT_DEBUG) 83 // tracef("_isWritting=%s", _isWritting); 84 // _isWritting = false; 85 // assert(false, ""); 86 // TODO: created by Administrator @ 2018-3-27 15:51:52 87 } 88 89 private IocpContext _iocp; 90 private WSABUF _dataWriteBuffer; 91 private ubyte[] _buffer; 92 private Socket _clientSocket; 93 }