1 module hunt.io.channel.posix.AbstractListener; 2 3 // dfmt off 4 version(Posix): 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.logging; 11 12 import std.conv; 13 import std.socket; 14 15 import core.sys.posix.sys.socket; 16 17 18 /** 19 * TCP Server 20 */ 21 abstract class AbstractListener : AbstractSocketChannel { 22 this(Selector loop, AddressFamily family = AddressFamily.INET) { 23 super(loop, ChannelType.Accept); 24 setFlag(ChannelFlag.Read, true); 25 this.socket = new TcpSocket(family); 26 } 27 28 protected bool onAccept(scope AcceptHandler handler) { 29 version (HUNT_DEBUG) 30 trace("new connection coming..."); 31 this.clearError(); 32 // http://man7.org/linux/man-pages/man2/accept.2.html 33 version(HAVE_EPOLL) { 34 socket_t clientFd = cast(socket_t)(accept4(this.handle, null, null, SOCK_NONBLOCK | SOCK_CLOEXEC)); 35 // socket_t clientFd = cast(socket_t)(accept(this.handle, null, null)); 36 } else { 37 socket_t clientFd = cast(socket_t)(accept(this.handle, null, null)); 38 } 39 if (clientFd == socket_t.init) 40 return false; 41 42 version (HUNT_DEBUG) 43 tracef("Listener fd=%d, client fd=%d", this.handle, clientFd); 44 45 if (handler !is null) 46 handler(new Socket(clientFd, this.localAddress.addressFamily)); 47 return true; 48 } 49 50 override void onWriteDone() { 51 version (HUNT_DEBUG) 52 tracef("a new connection created"); 53 } 54 } 55 56 57 extern (C) nothrow @nogc { 58 int accept4(int, sockaddr*, socklen_t*, int); 59 } 60 61 enum int SOCK_CLOEXEC = std.conv.octal!(2000000); /* Atomically set close-on-exec flag for the 62 new descriptor(s). */ 63 enum int SOCK_NONBLOCK = std.conv.octal!4000; /* Atomically mark descriptor(s) as 64 non-blocking. */