mirror of
https://github.com/inspircd/inspircd.git
synced 2025-03-09 10:39:02 -04:00
197 lines
6.1 KiB
C++
197 lines
6.1 KiB
C++
/*
|
|
* InspIRCd -- Internet Relay Chat Daemon
|
|
*
|
|
* Copyright (C) 2018-2022 Sadie Powell <sadie@witchery.services>
|
|
* Copyright (C) 2018 Attila Molnar <attilamolnar@hush.com>
|
|
*
|
|
* This file is part of InspIRCd. InspIRCd is free software: you can
|
|
* redistribute it and/or modify it under the terms of the GNU General Public
|
|
* License as published by the Free Software Foundation, version 2.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
|
|
#pragma once
|
|
|
|
#include "modules/cap.h"
|
|
|
|
namespace IRCv3
|
|
{
|
|
namespace Batch
|
|
{
|
|
typedef uint64_t RefTag;
|
|
class Manager;
|
|
class ManagerImpl;
|
|
class Batch;
|
|
struct BatchInfo;
|
|
class API;
|
|
class CapReference;
|
|
|
|
static constexpr unsigned int MAX_BATCHES = (sizeof(intptr_t) * 8) - 1;
|
|
}
|
|
}
|
|
|
|
/** Batch Manager.
|
|
* Implements batch starting and stopping. When it becomes unavailable (due to e.g. module unload)
|
|
* all running batches are stopped.
|
|
*/
|
|
class IRCv3::Batch::Manager
|
|
: public DataProvider
|
|
, public ClientProtocol::MessageTagProvider
|
|
{
|
|
public:
|
|
/** Constructor.
|
|
* @param mod Module that owns the Manager.
|
|
*/
|
|
Manager(Module* mod)
|
|
: DataProvider(mod, "batchapi")
|
|
, ClientProtocol::MessageTagProvider(mod)
|
|
{
|
|
}
|
|
|
|
/** Start a batch.
|
|
* Check Batch::IsRunning() to learn if the batch has been started.
|
|
* @param batch Batch to start.
|
|
*/
|
|
virtual void Start(Batch& batch) = 0;
|
|
|
|
/** End a batch.
|
|
* @param batch Batch to end.
|
|
*/
|
|
virtual void End(Batch& batch) = 0;
|
|
};
|
|
|
|
/** Represents a batch.
|
|
* Batches are used to group together physically separate client protocol messages that logically belong
|
|
* together for one reason or another. The type of a batch, if provided, indicates what kind of grouping
|
|
* it does.
|
|
*
|
|
* Batch objects have two states: running and stopped. If a batch is running, messages can be added to it.
|
|
* If a message has been added to a batch and that message is sent to a client that negotiated the batch
|
|
* capability then the client will receive a message tag attached to the message indicating the batch that
|
|
* 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
|
|
* received any message from batch B it will get a batch start message for B before M. When a batch B is
|
|
* stopped, every client that received at least one message which was in batch B will receive an end of
|
|
* batch message for B.
|
|
* A message may only be part of a single batch at any given time.
|
|
*/
|
|
class IRCv3::Batch::Batch final
|
|
{
|
|
Manager* manager = nullptr;
|
|
const std::string type;
|
|
RefTag reftag;
|
|
std::string reftagstr;
|
|
unsigned int bit;
|
|
BatchInfo* batchinfo = nullptr;
|
|
ClientProtocol::Message* batchstartmsg = nullptr;
|
|
ClientProtocol::Message* batchendmsg = nullptr;
|
|
|
|
void Setup(unsigned int b)
|
|
{
|
|
bit = b;
|
|
reftag = (static_cast<RefTag>(1) << bit);
|
|
reftagstr = ConvToStr(reftag);
|
|
}
|
|
|
|
unsigned int GetId() const { return bit; }
|
|
intptr_t GetBit() const { return reftag; }
|
|
|
|
public:
|
|
/** Constructor.
|
|
* The batch is initially stopped. To start it, pass it to Manager::Start().
|
|
* @param Type Batch type string, used to indicate what kind of grouping the batch does. May be empty.
|
|
*/
|
|
Batch(const std::string& Type)
|
|
: type(Type)
|
|
{
|
|
}
|
|
|
|
/** Destructor.
|
|
* If the batch is running, it is ended.
|
|
*/
|
|
~Batch()
|
|
{
|
|
if (manager)
|
|
manager->End(*this);
|
|
}
|
|
|
|
/** Add a message to the batch.
|
|
* If the batch isn't running then this method does nothing.
|
|
* @param msg Message to add to the batch. If it is already part of any batch, this method is a no-op.
|
|
*/
|
|
void AddToBatch(ClientProtocol::Message& msg)
|
|
{
|
|
if (manager)
|
|
msg.AddTag("batch", manager, reftagstr, this);
|
|
}
|
|
|
|
/** Get batch reference tag which is an opaque id for the batch and is used in the client protocol.
|
|
* Only running batches have a reference tag assigned.
|
|
* @return Reference tag as a string, only valid if the batch is running.
|
|
*/
|
|
const std::string& GetRefTagStr() const { return reftagstr; }
|
|
|
|
/** Get batch type.
|
|
* @return Batch type string.
|
|
*/
|
|
const std::string& GetType() const { return type; }
|
|
|
|
/** Check whether the batch is running.
|
|
* Batches can be started with Manager::Start() and stopped with Manager::End().
|
|
* @return True if the batch is running, false otherwise.
|
|
*/
|
|
bool IsRunning() const { return (manager != nullptr); }
|
|
|
|
/** Get the batch start client protocol message.
|
|
* The returned message object can be manipulated to add extra parameters or labels to the message. The first
|
|
* parameter of the message is the batch reference tag generated by the module providing batch support.
|
|
* If the batch type string was specified, it will be the second parameter of the message.
|
|
* May only be called if IsRunning() == true.
|
|
* @return Mutable batch start client protocol message.
|
|
*/
|
|
ClientProtocol::Message& GetBatchStartMessage() { return *batchstartmsg; }
|
|
|
|
/** Get the batch end client protocol message.
|
|
* The returned message object can be manipulated to add extra parameters or labels to the message. The first
|
|
* parameter of the message is the batch reference tag generated by the module providing batch support.
|
|
* If the batch type string was specified, it will be the second parameter of the message.
|
|
* May only be called if IsRunning() == true.
|
|
* @return Mutable batch end client protocol message.
|
|
*/
|
|
ClientProtocol::Message& GetBatchEndMessage() { return *batchendmsg; }
|
|
|
|
friend class ManagerImpl;
|
|
};
|
|
|
|
/** Batch API. Use this to access the Manager.
|
|
*/
|
|
class IRCv3::Batch::API final
|
|
: public dynamic_reference_nocheck<Manager>
|
|
{
|
|
public:
|
|
API(Module* mod)
|
|
: dynamic_reference_nocheck<Manager>(mod, "batchapi")
|
|
{
|
|
}
|
|
};
|
|
|
|
/** Reference to the batch cap.
|
|
* Can be used to check whether a user has the batch client cap enabled.
|
|
*/
|
|
class IRCv3::Batch::CapReference final
|
|
: public Cap::Reference
|
|
{
|
|
public:
|
|
CapReference(Module* mod)
|
|
: Cap::Reference(mod, "batch")
|
|
{
|
|
}
|
|
};
|