2 * InspIRCd -- Internet Relay Chat Daemon
4 * Copyright (C) 2016 Attila Molnar <attilamolnar@hush.com>
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.
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
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/>.
23 #include "modules/cap.h"
29 typedef uint64_t RefTag;
37 static const unsigned int MAX_BATCHES = (sizeof(intptr_t) * 8) - 1;
42 * Implements batch starting and stopping. When it becomes unavailable (due to e.g. module unload)
43 * all running batches are stopped.
45 class IRCv3::Batch::Manager : public DataProvider, public ClientProtocol::MessageTagProvider
49 * @param mod Module that owns the Manager.
52 : DataProvider(mod, "batchapi")
53 , ClientProtocol::MessageTagProvider(mod)
58 * Check Batch::IsRunning() to learn if the batch has been started.
59 * @param batch Batch to start.
61 virtual void Start(Batch& batch) = 0;
64 * @param batch Batch to end.
66 virtual void End(Batch& batch) = 0;
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
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.
83 class IRCv3::Batch::Batch
86 const std::string type;
88 std::string reftagstr;
91 ClientProtocol::Message* batchstartmsg;
93 void Setup(unsigned int b)
97 reftagstr = ConvToStr(reftag);
100 unsigned int GetId() const { return bit; }
101 intptr_t GetBit() const { return reftag; }
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.
108 Batch(const std::string& Type)
112 , batchstartmsg(NULL)
117 * If the batch is running, it is ended.
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.
129 void AddToBatch(ClientProtocol::Message& msg)
132 msg.AddTag("batch", manager, reftagstr, this);
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.
139 const std::string& GetRefTagStr() const { return reftagstr; }
142 * @return Batch type string.
144 const std::string& GetType() const { return type; }
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.
150 bool IsRunning() const { return (manager != NULL); }
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.
159 ClientProtocol::Message& GetBatchStartMessage() { return *batchstartmsg; }
161 friend class ManagerImpl;
164 /** Batch API. Use this to access the Manager.
166 class IRCv3::Batch::API : public dynamic_reference_nocheck<Manager>
170 : dynamic_reference_nocheck<Manager>(mod, "batchapi")
175 /** Reference to the batch cap.
176 * Can be used to check whether a user has the batch client cap enabled.
178 class IRCv3::Batch::CapReference : public Cap::Reference
181 CapReference(Module* mod)
182 : Cap::Reference(mod, "batch")