]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - include/modules/ircv3_batch.h
Add support for the IRCv3 batch specification.
[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
93         void Setup(unsigned int b)
94         {
95                 bit = b;
96                 reftag = (1 << bit);
97                 reftagstr = ConvToStr(reftag);
98         }
99
100         unsigned int GetId() const { return bit; }
101         intptr_t GetBit() const { return reftag; }
102
103  public:
104         /** Constructor.
105          * The batch is initially stopped. To start it, pass it to Manager::Start().
106          * @param Type Batch type string, used to indicate what kind of grouping the batch does. May be empty.
107          */
108         Batch(const std::string& Type)
109                 : manager(NULL)
110                 , type(Type)
111                 , batchinfo(NULL)
112                 , batchstartmsg(NULL)
113         {
114         }
115
116         /** Destructor.
117          * If the batch is running, it is ended.
118          */
119         ~Batch()
120         {
121                 if (manager)
122                         manager->End(*this);
123         }
124
125         /** Add a message to the batch.
126          * If the batch isn't running then this method does nothing.
127          * @param msg Message to add to the batch. If it is already part of any batch, this method is a no-op.
128          */
129         void AddToBatch(ClientProtocol::Message& msg)
130         {
131                 if (manager)
132                         msg.AddTag("batch", manager, reftagstr, this);
133         }
134
135         /** Get batch reference tag which is an opaque id for the batch and is used in the client protocol.
136          * Only running batches have a reference tag assigned.
137          * @return Reference tag as a string, only valid if the batch is running.
138          */
139         const std::string& GetRefTagStr() const { return reftagstr; }
140
141         /** Get batch type.
142          * @return Batch type string.
143          */
144         const std::string& GetType() const { return type; }
145
146         /** Check whether the batch is running.
147          * Batches can be started with Manager::Start() and stopped with Manager::End().
148          * @return True if the batch is running, false otherwise.
149          */
150         bool IsRunning() const { return (manager != NULL); }
151
152         /** Get the batch start client protocol message.
153          * The returned message object can be manipulated to add extra parameters or labels to the message. The first
154          * parameter of the message is the batch reference tag generated by the module providing batch support.
155          * If the batch type string was specified, it will be the second parameter of the message.
156          * May only be called if IsRunning() == true.
157          * @return Mutable batch start client protocol message.
158          */
159         ClientProtocol::Message& GetBatchStartMessage() { return *batchstartmsg; }
160
161         friend class ManagerImpl;
162 };
163
164 /** Batch API. Use this to access the Manager.
165  */
166 class IRCv3::Batch::API : public dynamic_reference_nocheck<Manager>
167 {
168  public:
169         API(Module* mod)
170                 : dynamic_reference_nocheck<Manager>(mod, "batchapi")
171         {
172         }
173 };
174
175 /** Reference to the batch cap.
176  * Can be used to check whether a user has the batch client cap enabled.
177  */
178 class IRCv3::Batch::CapReference : public Cap::Reference
179 {
180  public:
181         CapReference(Module* mod)
182                 : Cap::Reference(mod, "batch")
183         {
184         }
185 };