]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - include/modules/ircv3_batch.h
Update my name and email address.
[user/henk/code/inspircd.git] / include / modules / ircv3_batch.h
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2016 Attila Molnar <attilamolnar@hush.com>
5  *
6  * This file is part of InspIRCd.  InspIRCd is free software: you can
7  * redistribute it and/or modify it under the terms of the GNU General Public
8  * License as published by the Free Software Foundation, version 2.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
13  * details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19
20 #pragma once
21
22 // For CapReference
23 #include "modules/cap.h"
24
25 namespace IRCv3
26 {
27         namespace Batch
28         {
29                 typedef uint64_t RefTag;
30                 class Manager;
31                 class ManagerImpl;
32                 class Batch;
33                 struct BatchInfo;
34                 class API;
35                 class CapReference;
36
37                 static const unsigned int MAX_BATCHES = (sizeof(intptr_t) * 8) - 1;
38         }
39 }
40
41 /** Batch Manager.
42  * Implements batch starting and stopping. When it becomes unavailable (due to e.g. module unload)
43  * all running batches are stopped.
44  */
45 class IRCv3::Batch::Manager : public DataProvider, public ClientProtocol::MessageTagProvider
46 {
47  public:
48         /** Constructor.
49          * @param mod Module that owns the Manager.
50          */
51         Manager(Module* mod)
52                 : DataProvider(mod, "batchapi")
53                 , ClientProtocol::MessageTagProvider(mod)
54         {
55         }
56
57         /** Start a batch.
58          * Check Batch::IsRunning() to learn if the batch has been started.
59          * @param batch Batch to start.
60          */
61         virtual void Start(Batch& batch) = 0;
62
63         /** End a batch.
64          * @param batch Batch to end.
65          */
66         virtual void End(Batch& batch) = 0;
67 };
68
69 /** Represents a batch.
70  * Batches are used to group together physically separate client protocol messages that logically belong
71  * together for one reason or another. The type of a batch, if provided, indicates what kind of grouping
72  * it does.
73  *
74  * Batch objects have two states: running and stopped. If a batch is running, messages can be added to it.
75  * If a message has been added to a batch and that message is sent to a client that negotiated the batch
76  * capability then the client will receive a message tag attached to the message indicating the batch that
77  * the message is a part of. If a message M is part of a batch B and M is sent to a client that hasn't yet
78  * received any message from batch B it will get a batch start message for B before M. When a batch B is
79  * stopped, every client that received at least one message which was in batch B will receive an end of
80  * batch message for B.
81  * A message may only be part of a single batch at any given time.
82  */
83 class IRCv3::Batch::Batch
84 {
85         Manager* manager;
86         const std::string type;
87         RefTag reftag;
88         std::string reftagstr;
89         unsigned int bit;
90         BatchInfo* batchinfo;
91         ClientProtocol::Message* batchstartmsg;
92         ClientProtocol::Message* batchendmsg;
93
94         void Setup(unsigned int b)
95         {
96                 bit = b;
97                 reftag = (1 << bit);
98                 reftagstr = ConvToStr(reftag);
99         }
100
101         unsigned int GetId() const { return bit; }
102         intptr_t GetBit() const { return reftag; }
103
104  public:
105         /** Constructor.
106          * The batch is initially stopped. To start it, pass it to Manager::Start().
107          * @param Type Batch type string, used to indicate what kind of grouping the batch does. May be empty.
108          */
109         Batch(const std::string& Type)
110                 : manager(NULL)
111                 , type(Type)
112                 , batchinfo(NULL)
113                 , batchstartmsg(NULL)
114         {
115         }
116
117         /** Destructor.
118          * If the batch is running, it is ended.
119          */
120         ~Batch()
121         {
122                 if (manager)
123                         manager->End(*this);
124         }
125
126         /** Add a message to the batch.
127          * If the batch isn't running then this method does nothing.
128          * @param msg Message to add to the batch. If it is already part of any batch, this method is a no-op.
129          */
130         void AddToBatch(ClientProtocol::Message& msg)
131         {
132                 if (manager)
133                         msg.AddTag("batch", manager, reftagstr, this);
134         }
135
136         /** Get batch reference tag which is an opaque id for the batch and is used in the client protocol.
137          * Only running batches have a reference tag assigned.
138          * @return Reference tag as a string, only valid if the batch is running.
139          */
140         const std::string& GetRefTagStr() const { return reftagstr; }
141
142         /** Get batch type.
143          * @return Batch type string.
144          */
145         const std::string& GetType() const { return type; }
146
147         /** Check whether the batch is running.
148          * Batches can be started with Manager::Start() and stopped with Manager::End().
149          * @return True if the batch is running, false otherwise.
150          */
151         bool IsRunning() const { return (manager != NULL); }
152
153         /** Get the batch start client protocol message.
154          * The returned message object can be manipulated to add extra parameters or labels to the message. The first
155          * parameter of the message is the batch reference tag generated by the module providing batch support.
156          * If the batch type string was specified, it will be the second parameter of the message.
157          * May only be called if IsRunning() == true.
158          * @return Mutable batch start client protocol message.
159          */
160         ClientProtocol::Message& GetBatchStartMessage() { return *batchstartmsg; }
161
162         /** Get the batch end client protocol message.
163          * The returned message object can be manipulated to add extra parameters or labels to the message. The first
164          * parameter of the message is the batch reference tag generated by the module providing batch support.
165          * If the batch type string was specified, it will be the second parameter of the message.
166          * May only be called if IsRunning() == true.
167          * @return Mutable batch end client protocol message.
168          */
169         ClientProtocol::Message& GetBatchEndMessage() { return *batchendmsg; }
170
171         friend class ManagerImpl;
172 };
173
174 /** Batch API. Use this to access the Manager.
175  */
176 class IRCv3::Batch::API : public dynamic_reference_nocheck<Manager>
177 {
178  public:
179         API(Module* mod)
180                 : dynamic_reference_nocheck<Manager>(mod, "batchapi")
181         {
182         }
183 };
184
185 /** Reference to the batch cap.
186  * Can be used to check whether a user has the batch client cap enabled.
187  */
188 class IRCv3::Batch::CapReference : public Cap::Reference
189 {
190  public:
191         CapReference(Module* mod)
192                 : Cap::Reference(mod, "batch")
193         {
194         }
195 };