2 * InspIRCd -- Internet Relay Chat Daemon
4 * Copyright (C) 2018-2020 Sadie Powell <sadie@witchery.services>
5 * Copyright (C) 2018 Attila Molnar <attilamolnar@hush.com>
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.
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
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/>.
24 #include "modules/cap.h"
30 typedef uint64_t RefTag;
38 static const unsigned int MAX_BATCHES = (sizeof(intptr_t) * 8) - 1;
43 * Implements batch starting and stopping. When it becomes unavailable (due to e.g. module unload)
44 * all running batches are stopped.
46 class IRCv3::Batch::Manager : public DataProvider, public ClientProtocol::MessageTagProvider
50 * @param mod Module that owns the Manager.
53 : DataProvider(mod, "batchapi")
54 , ClientProtocol::MessageTagProvider(mod)
59 * Check Batch::IsRunning() to learn if the batch has been started.
60 * @param batch Batch to start.
62 virtual void Start(Batch& batch) = 0;
65 * @param batch Batch to end.
67 virtual void End(Batch& batch) = 0;
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
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.
84 class IRCv3::Batch::Batch
87 const std::string type;
89 std::string reftagstr;
92 ClientProtocol::Message* batchstartmsg;
93 ClientProtocol::Message* batchendmsg;
95 void Setup(unsigned int b)
99 reftagstr = ConvToStr(reftag);
102 unsigned int GetId() const { return bit; }
103 intptr_t GetBit() const { return reftag; }
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.
110 Batch(const std::string& Type)
114 , batchstartmsg(NULL)
120 * If the batch is running, it is ended.
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.
132 void AddToBatch(ClientProtocol::Message& msg)
135 msg.AddTag("batch", manager, reftagstr, this);
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.
142 const std::string& GetRefTagStr() const { return reftagstr; }
145 * @return Batch type string.
147 const std::string& GetType() const { return type; }
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.
153 bool IsRunning() const { return (manager != NULL); }
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.
162 ClientProtocol::Message& GetBatchStartMessage() { return *batchstartmsg; }
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.
171 ClientProtocol::Message& GetBatchEndMessage() { return *batchendmsg; }
173 friend class ManagerImpl;
176 /** Batch API. Use this to access the Manager.
178 class IRCv3::Batch::API : public dynamic_reference_nocheck<Manager>
182 : dynamic_reference_nocheck<Manager>(mod, "batchapi")
187 /** Reference to the batch cap.
188 * Can be used to check whether a user has the batch client cap enabled.
190 class IRCv3::Batch::CapReference : public Cap::Reference
193 CapReference(Module* mod)
194 : Cap::Reference(mod, "batch")