1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 /**
6  * Watchers register user's interest in some event.
7  *
8  * Copyright: Eugene Wissner 2016-2020.
9  * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
10  *                  Mozilla Public License, v. 2.0).
11  * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
12  * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/async/watcher.d,
13  *                 tanya/async/watcher.d)
14  */
15 module tanya.async.watcher;
16 
17 import tanya.async.loop;
18 import tanya.async.protocol;
19 import tanya.async.transport;
20 import tanya.container.buffer;
21 import tanya.container.list;
22 import tanya.memory.allocator;
23 import tanya.net.socket;
24 
25 /**
26  * A watcher is an opaque structure that you allocate and register to record
27  * your interest in some event. 
28  */
29 abstract class Watcher
30 {
31     /// Whether the watcher is active.
32     bool active;
33 
34     /**
35      * Invoke some action on event.
36      */
37     void invoke() @nogc;
38 }
39 
40 /**
41  * Socket watcher.
42  */
43 abstract class SocketWatcher : Watcher
44 {
45     /// Watched socket.
46     protected Socket socket_;
47 
48     /**
49      * Params:
50      *  socket = Socket.
51      *
52      * Precondition: $(D_INLINECODE socket !is null)
53      */
54     this(Socket socket) pure nothrow @safe @nogc
55     in
56     {
57         assert(socket !is null);
58     }
59     do
60     {
61         socket_ = socket;
62     }
63 
64     /**
65      * Returns: Socket.
66      */
67     @property Socket socket() pure nothrow @safe @nogc
68     {
69         return socket_;
70     }
71 }
72 
73 /**
74  * Connection watcher.
75  */
76 class ConnectionWatcher : SocketWatcher
77 {
78     /// Incoming connection queue.
79     DList!DuplexTransport incoming;
80 
81     private Protocol delegate() @nogc protocolFactory;
82 
83     /**
84      * Params:
85      *  socket = Socket.
86      */
87     this(Socket socket) @nogc
88     {
89         super(socket);
90     }
91 
92     /**
93      * Params:
94      *  P = Protocol should be used.
95      */
96     void setProtocol(P : Protocol)() @nogc
97     {
98         this.protocolFactory = () @nogc => cast(Protocol) defaultAllocator.make!P;
99     }
100 
101     /**
102      * Invokes new connection callback.
103      */
104     override void invoke() @nogc
105     in
106     {
107         assert(protocolFactory !is null, "Protocol isn't set.");
108     }
109     do
110     {
111         for (; !this.incoming.empty; this.incoming.removeFront())
112         {
113             this.incoming.front.protocol = protocolFactory();
114             this.incoming.front.protocol.connected(this.incoming.front);
115         }
116     }
117 }