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