1 module server.informer.informer;
2 
3 import core.thread : Thread;
4 import server.server : BesterServer;
5 import std.socket;
6 import server.informer.client : BesterInformerClient;
7 
8 /**
9 * The `BesterInformer` allows handlers to query (out-of-band)
10 * information regarding this bester server.
11 *
12 * This is useful when the message handler requires additional
13 * information before it sends its final message response.
14 */
15 public final class BesterInformer : Thread
16 {
17     /* The associated `BesterServer` */
18     private BesterServer server;
19 
20     /* Informer socket */
21     private Socket informerSocket;
22 
23     /* Whether or not the informer server is active */
24     private bool active = true;
25 
26     /* Connected clients */
27     private BesterInformerClient[] informerClients;
28 
29     /**
30     * Constructs a new `BesterInformer` object
31     * which will accept incoming connections
32     * (upon calling `.start`) from handlers,
33     * over a UNIX domain socket, requesting
34     * server information.
35     */
36     this(BesterServer server)
37     {
38         /* Set the worker function */
39         super(&worker);
40 
41         /* Setup the socket */
42         informerSocket = new Socket(AddressFamily.UNIX, SocketType.STREAM);
43         informerSocket.bind(new UnixAddress("bInformer"));
44         informerSocket.listen(1); /* TODO: Value */
45 
46         /* Set the associated BesterServer */
47         this.server = server;
48     }
49 
50     /**
51     * Client send-receive loop.
52     * Accepts incoming connections to the informer
53     * and dispatches them to a worker thread.
54     */
55     private void worker()
56     {
57         while(active)
58         {
59             /* Accept the queued incoming connection */
60             Socket handlerSocket = informerSocket.accept();
61 
62             /**
63             * Create a new worker for the informer client, adds it
64             * to the client queue and dispatches its worker thread.
65             */
66             BesterInformerClient newInformer = new BesterInformerClient(server, handlerSocket);
67             informerClients ~= newInformer;
68             newInformer.start();
69         }
70 
71         /* Close the informer socket */
72         informerSocket.close();
73     }
74 
75     public void shutdown()
76     {
77         for(ulong i = 0; i < informerClients.length; i++)
78         {
79             informerClients[i].shutdown();
80         }
81     }
82 
83 }