]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - include/modules/ircv3_batch.h
Use IsCTCP in blockcolor for ignoring CTCPs.
[user/henk/code/inspircd.git] / include / modules / ircv3_batch.h
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2018-2020 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                 , batchendmsg(NULL)
116         {
117         }
118
119         /** Destructor.
120          * If the batch is running, it is ended.
121          */
122         ~Batch()
123         {
124                 if (manager)
125                         manager->End(*this);
126         }
127
128         /** Add a message to the batch.
129          * If the batch isn't running then this method does nothing.
130          * @param msg Message to add to the batch. If it is already part of any batch, this method is a no-op.
131          */
132         void AddToBatch(ClientProtocol::Message& msg)
133         {
134                 if (manager)
135                         msg.AddTag("batch", manager, reftagstr, this);
136         }
137
138         /** Get batch reference tag which is an opaque id for the batch and is used in the client protocol.
139          * Only running batches have a reference tag assigned.
140          * @return Reference tag as a string, only valid if the batch is running.
141          */
142         const std::string& GetRefTagStr() const { return reftagstr; }
143
144         /** Get batch type.
145          * @return Batch type string.
146          */
147         const std::string& GetType() const { return type; }
148
149         /** Check whether the batch is running.
150          * Batches can be started with Manager::Start() and stopped with Manager::End().
151          * @return True if the batch is running, false otherwise.
152          */
153         bool IsRunning() const { return (manager != NULL); }
154
155         /** Get the batch start client protocol message.
156          * The returned message object can be manipulated to add extra parameters or labels to the message. The first
157          * parameter of the message is the batch reference tag generated by the module providing batch support.
158          * If the batch type string was specified, it will be the second parameter of the message.
159          * May only be called if IsRunning() == true.
160          * @return Mutable batch start client protocol message.
161          */
162         ClientProtocol::Message& GetBatchStartMessage() { return *batchstartmsg; }
163
164         /** Get the batch end client protocol message.
165          * The returned message object can be manipulated to add extra parameters or labels to the message. The first
166          * parameter of the message is the batch reference tag generated by the module providing batch support.
167          * If the batch type string was specified, it will be the second parameter of the message.
168          * May only be called if IsRunning() == true.
169          * @return Mutable batch end client protocol message.
170          */
171         ClientProtocol::Message& GetBatchEndMessage() { return *batchendmsg; }
172
173         friend class ManagerImpl;
174 };
175
176 /** Batch API. Use this to access the Manager.
177  */
178 class IRCv3::Batch::API : public dynamic_reference_nocheck<Manager>
179 {
180  public:
181         API(Module* mod)
182                 : dynamic_reference_nocheck<Manager>(mod, "batchapi")
183         {
184         }
185 };
186
187 /** Reference to the batch cap.
188  * Can be used to check whether a user has the batch client cap enabled.
189  */
190 class IRCv3::Batch::CapReference : public Cap::Reference
191 {
192  public:
193         CapReference(Module* mod)
194                 : Cap::Reference(mod, "batch")
195         {
196         }
197 };