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.  */