Merge branch 'insp3' into master.

This commit is contained in:
Sadie Powell 2019-07-27 19:12:29 +01:00
commit ada6646b65
42 changed files with 432 additions and 126 deletions

View File

@ -360,7 +360,7 @@ class ClientProtocol::Message : public ClientProtocol::MessageSource
/** Add a parameter to the parameter list.
* @param str String to add.
* The string will NOT be copied, it must remain alive until ClearParams() is called or until the object is destroyed.
* The string will NOT be copied, it must remain alive until ClearParams() is called or until the object is destroyed.
*/
void PushParamRef(const std::string& str) { params.push_back(str); }
@ -479,7 +479,7 @@ class ClientProtocol::Event
/** Constructor.
* @param protoeventprov Protocol event provider the event is an instance of.
* @param msg Message to include in this event by default.
* @param msg Message to include in this event by default.
*/
Event(EventProvider& protoeventprov, ClientProtocol::Message& msg)
: event(&protoeventprov)

View File

@ -494,11 +494,11 @@ class CoreExport InspIRCd
static unsigned long Duration(const std::string& str);
/** Calculate a duration in seconds from a string in the form 1y2w3d4h6m5s
* @param str A string containing a time in the form 1y2w3d4h6m5s
* (one year, two weeks, three days, four hours, six minutes and five seconds)
* @param duration The location to place the parsed duration valur
* @return Whether the duration was a valid format or not
*/
* @param str A string containing a time in the form 1y2w3d4h6m5s
* (one year, two weeks, three days, four hours, six minutes and five seconds)
* @param duration The location to place the parsed duration valur
* @return Whether the duration was a valid format or not
*/
static bool Duration(const std::string& str, unsigned long& duration);
/** Determines whether a string contains a valid duration.

View File

@ -275,7 +275,14 @@ class CoreExport StreamSocket : public EventHandler
int HookChainRead(IOHook* hook, std::string& rq);
protected:
/** The data which has been received from the socket. */
std::string recvq;
/** Swaps the internals of this StreamSocket with another one.
* @param other A StreamSocket to swap internals with.
*/
void SwapInternals(StreamSocket& other);
public:
const Type type;
StreamSocket(Type sstype = SS_UNKNOWN)

View File

@ -544,8 +544,12 @@ class CoreExport ModeWatcher : public classbase
class CoreExport ModeParser
{
public:
/** The maximum number of modes which can be created. */
static const ModeHandler::Id MODEID_MAX = 64;
/** The maximum length of a mode parameter. */
static const size_t MODE_PARAM_MAX = 250;
/** Type of the container that maps mode names to ModeHandlers
*/
typedef std::unordered_map<std::string, ModeHandler*, irc::insensitive, irc::StrHashComp> ModeHandlerMap;
@ -712,7 +716,7 @@ class CoreExport ModeParser
* @param user The source of the mode change, can be a server user.
* @param targetchannel Channel to apply the mode change on. NULL if changing modes on a channel.
* @param targetuser User to apply the mode change on. NULL if changing modes on a user.
* @param changelist Modes to change in form of a Modes::ChangeList. May not process
* @param changelist Modes to change in form of a Modes::ChangeList. May not process
* the entire list due to MODE line length and max modes limitations.
* @param flags Optional flags controlling how the mode change is processed,
* defaults to MODE_NONE.
@ -731,11 +735,11 @@ class CoreExport ModeParser
* is a channel mode change.
* @param parameters List of strings describing the mode change to convert to a ChangeList.
* Must be using the same format as the parameters of a MODE command.
* @param changelist ChangeList object to populate.
* @param beginindex Index of the first element that is part of the MODE list in the parameters
* container. Defaults to 1.
* @param endindex Index of the first element that is not part of the MODE list. By default,
* the entire container is considered part of the MODE list.
* @param changelist ChangeList object to populate.
* @param beginindex Index of the first element that is part of the MODE list in the parameters
* container. Defaults to 1.
* @param endindex Index of the first element that is not part of the MODE list. By default,
* the entire container is considered part of the MODE list.
*/
void ModeParamsToChangeList(User* user, ModeType type, const std::vector<std::string>& parameters, Modes::ChangeList& changelist, unsigned int beginindex = 1, unsigned int endindex = UINT_MAX);

View File

@ -223,7 +223,7 @@ enum Implementation
I_OnUserPostNick, I_OnPreMode, I_On005Numeric, I_OnKill, I_OnLoadModule,
I_OnUnloadModule, I_OnBackgroundTimer, I_OnPreCommand, I_OnCheckReady, I_OnCheckInvite,
I_OnRawMode, I_OnCheckKey, I_OnCheckLimit, I_OnCheckBan, I_OnCheckChannelBan, I_OnExtBanCheck,
I_OnPreChangeHost, I_OnPreTopicChange,
I_OnPreChangeHost, I_OnPreTopicChange, I_OnConnectionFail,
I_OnPostTopicChange, I_OnPostConnect, I_OnPostDeoper,
I_OnPreChangeRealName, I_OnUserRegister, I_OnChannelPreDelete, I_OnChannelDelete,
I_OnPostOper, I_OnPostCommand, I_OnPostJoin,
@ -942,6 +942,14 @@ class CoreExport Module : public classbase, public usecountbase
* deny the message from being sent, or MOD_RES_PASSTHRU to let another module handle the event.
*/
virtual ModResult OnUserWrite(LocalUser* user, ClientProtocol::Message& msg);
/** Called when a user connection has been unexpectedly disconnected.
* @param user The user who has been unexpectedly disconnected.
* @param error The type of error which caused this connection failure.
* @return MOD_RES_ALLOW to explicitly retain the user as a zombie, MOD_RES_DENY to explicitly
* disconnect the user, or MOD_RES_PASSTHRU to let another module handle the event.
*/
virtual ModResult OnConnectionFail(LocalUser* user, BufferedSocketError error);
};
/** ModuleManager takes care of all things module-related

View File

@ -67,6 +67,7 @@ class IRCv3::WriteNeighborsWithCap : public User::ForEachNeighborHandler
template <typename T>
class IRCv3::CapTag : public ClientProtocol::MessageTagProvider
{
protected:
Cap::Capability cap;
const std::string tagname;

View File

@ -0,0 +1,135 @@
/*
* InspIRCd -- Internet Relay Chat Daemon
*
* Copyright (C) 2019 Peter Powell <petpow@saberuk.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/>.
*/
// IMPORTANT: The contents of this file are experimental and are not presently
// covered by the InspIRCd API stability guarantee.
#pragma once
#include "modules/cap.h"
namespace IRCv3
{
namespace Replies
{
class Reply;
class Fail;
class Note;
class Warn;
}
}
/** Base class for standard replies. */
class IRCv3::Replies::Reply
{
private:
/** The name of the command for this reply. */
std::string cmd;
/** The event provider for this reply. */
ClientProtocol::EventProvider evprov;
protected:
/** Initializes a new instance of the Reply class.
* @param Creator The module which created this instance.
* @param Cmd The name of the command to reply with.
*/
Reply(Module* Creator, const std::string& Cmd)
: cmd(Cmd)
, evprov(Creator, Cmd)
{
}
public:
/**
* Sends a standard reply to the specified user.
* @param user The user to send the reply to.
* @param command The command that the reply relates to.
* @param code A machine readable code for this reply.
* @param description A human readable description of this reply.
*/
void Send(LocalUser* user, Command* command, const std::string& code, const std::string& description)
{
ClientProtocol::Message msg(cmd.c_str(), ServerInstance->Config->ServerName);
msg.PushParamRef(command->name);
msg.PushParam(code);
msg.PushParam(description);
ClientProtocol::Event ev(evprov, msg);
user->Send(ev);
}
/**
* Sends a standard reply to the specified user if they have the specified cap
* or a notice if they do not.s
* @param user The user to send the reply to.
* @param command The command that the reply relates to.
* @param code A machine readable code for this reply.
* @param description A human readable description of this reply.
*/
void SendIfCap(LocalUser* user, const Cap::Capability& cap, Command* command, const std::string& code, const std::string& description)
{
if (cap.get(user))
Send(user, command, code, description);
else
user->WriteNotice(InspIRCd::Format("*** %s: %s", command->name.c_str(), description.c_str()));
}
};
/** Sends a FAIL standard reply. */
class IRCv3::Replies::Fail
: public IRCv3::Replies::Reply
{
public:
/** Initializes a new instance of the Fail class.
* @param Creator The module which created this instance.
*/
Fail(Module* Creator)
: Reply(Creator, "FAIL")
{
}
};
/** Sends a NOTE standard reply. */
class IRCv3::Replies::Note
: public IRCv3::Replies::Reply
{
public:
/** Initializes a new instance of the Note class.
* @param Creator The module which created this instance.
*/
Note(Module* Creator)
: Reply(Creator, "NOTE")
{
}
};
/** Sends a WARN standard reply. */
class IRCv3::Replies::Warn
: public IRCv3::Replies::Reply
{
public:
/** Initializes a new instance of the Warn class.
* @param Creator The module which created this instance.
*/
Warn(Module* Creator)
: Reply(Creator, "WARN")
{
}
};

View File

@ -25,6 +25,7 @@ namespace ServerProtocol
{
class BroadcastEventListener;
class LinkEventListener;
class MessageEventListener;
class SyncEventListener;
}
@ -66,6 +67,30 @@ class ServerProtocol::LinkEventListener
virtual void OnServerSplit(const Server* server) { }
};
class ServerProtocol::MessageEventListener
: public Events::ModuleEventListener
{
public:
MessageEventListener(Module* mod)
: ModuleEventListener(mod, "event/server-message")
{
}
/** Fired when a server message is being sent by a user.
* @param source The user who sent the message.
* @param name The name of the command which was sent.
* @param tags The tags which will be sent with the message.
*/
virtual void OnBuildMessage(User* source, const char* name, ClientProtocol::TagMap& tags) { }
/** Fired when a server message is being sent by a server.
* @param source The server who sent the message.
* @param name The name of the command which was sent.
* @param tags The tags which will be sent with the message.
*/
virtual void OnBuildMessage(Server* source, const char* name, ClientProtocol::TagMap& tags) { }
};
class ServerProtocol::SyncEventListener
: public Events::ModuleEventListener
{

View File

@ -164,6 +164,12 @@ class CoreExport EventHandler : public classbase
* registered with the SocketEngine
*/
int fd;
/** Swaps the internals of this EventHandler with another one.
* @param other A EventHandler to swap internals with.
*/
void SwapInternals(EventHandler& other);
public:
/** Get the current file descriptor
* @return The file descriptor of this handler

View File

@ -616,6 +616,11 @@ class CoreExport UserIOHandler : public StreamSocket
* @param data The data to add to the write buffer
*/
void AddWriteBuf(const std::string &data);
/** Swaps the internals of this UserIOHandler with another one.
* @param other A UserIOHandler to swap internals with.
*/
void SwapInternals(UserIOHandler& other);
};
typedef unsigned int already_sent_t;

View File

@ -541,3 +541,17 @@ size_t StreamSocket::getSendQSize() const
}
return ret;
}
void StreamSocket::SwapInternals(StreamSocket& other)
{
if (type != other.type)
return;
EventHandler::SwapInternals(other);
std::swap(closeonempty, other.closeonempty);
std::swap(closing, other.closing);
std::swap(error, other.error);
std::swap(iohook, other.iohook);
std::swap(recvq, other.recvq);
std::swap(sendq, other.sendq);
}

View File

@ -160,9 +160,6 @@ ModeAction ListModeBase::OnModeChange(User* source, User*, Channel* channel, std
if (tidy)
ModeParser::CleanMask(parameter);
if (parameter.length() > 250)
return MODEACTION_DENY;
// If there was no list
if (!cd)
{

View File

@ -249,9 +249,9 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, Mode
const bool needs_param = mh->NeedsParam(adding);
std::string& parameter = mcitem.param;
// crop mode parameter size to 250 characters
if (parameter.length() > 250 && adding)
parameter.erase(250);
// crop mode parameter size to MODE_PARAM_MAX characters
if (parameter.length() > MODE_PARAM_MAX && adding)
parameter.erase(MODE_PARAM_MAX);
ModResult MOD_RESULT;
FIRST_MOD_RESULT(OnRawMode, MOD_RESULT, (user, chan, mh, parameter, adding));

View File

@ -140,6 +140,7 @@ void Module::OnSetUserIP(LocalUser*) { DetachEvent(I_OnSetUserIP); }
void Module::OnServiceAdd(ServiceProvider&) { DetachEvent(I_OnServiceAdd); }
void Module::OnServiceDel(ServiceProvider&) { DetachEvent(I_OnServiceDel); }
ModResult Module::OnUserWrite(LocalUser*, ClientProtocol::Message&) { DetachEvent(I_OnUserWrite); return MOD_RES_PASSTHRU; }
ModResult Module::OnConnectionFail(LocalUser*, BufferedSocketError) { DetachEvent(I_OnConnectionFail); return MOD_RES_PASSTHRU; }
ServiceProvider::ServiceProvider(Module* Creator, const std::string& Name, ServiceType Type)
: creator(Creator), name(Name), service(Type)

View File

@ -71,7 +71,7 @@ class ModuleChanFilter : public Module
{
ConfigTag* tag = ServerInstance->Config->ConfValue("chanfilter");
hidemask = tag->getBool("hidemask");
cf.maxlen = tag->getUInt("maxlen", 35, 10, 100);
cf.maxlen = tag->getUInt("maxlen", 35, 10, ModeParser::MODE_PARAM_MAX);
notifyuser = tag->getBool("notifyuser", true);
cf.DoRehash();
}

View File

@ -114,6 +114,7 @@ class ModuleChanHistory
: public Module
, public ServerProtocol::BroadcastEventListener
{
private:
HistoryMode m;
bool sendnotice;
UserModeReference botmode;
@ -123,6 +124,31 @@ class ModuleChanHistory
IRCv3::Batch::Batch batch;
IRCv3::ServerTime::API servertimemanager;
void SendHistory(LocalUser* user, Channel* channel, HistoryList* list, time_t mintime)
{
if (batchmanager)
{
batchmanager->Start(batch);
batch.GetBatchStartMessage().PushParamRef(channel->name);
}
for(std::deque<HistoryItem>::iterator i = list->lines.begin(); i != list->lines.end(); ++i)
{
const HistoryItem& item = *i;
if (item.ts >= mintime)
{
ClientProtocol::Messages::Privmsg msg(ClientProtocol::Messages::Privmsg::nocopy, item.sourcemask, channel, item.text);
if (servertimemanager)
servertimemanager->Set(msg, item.ts);
batch.AddToBatch(msg);
user->Send(ServerInstance->GetRFCEvents().privmsg, msg);
}
}
if (batchmanager)
batchmanager->End(batch);
}
public:
ModuleChanHistory()
: ServerProtocol::BroadcastEventListener(this)
@ -175,9 +201,6 @@ class ModuleChanHistory
HistoryList* list = m.ext.get(memb->chan);
if (!list)
return;
time_t mintime = 0;
if (list->maxtime)
mintime = ServerInstance->Time() - list->maxtime;
if ((sendnotice) && (!batchcap.get(localuser)))
{
@ -187,27 +210,11 @@ class ModuleChanHistory
memb->WriteNotice(message);
}
if (batchmanager)
{
batchmanager->Start(batch);
batch.GetBatchStartMessage().PushParamRef(memb->chan->name);
}
time_t mintime = 0;
if (list->maxtime)
mintime = ServerInstance->Time() - list->maxtime;
for(std::deque<HistoryItem>::iterator i = list->lines.begin(); i != list->lines.end(); ++i)
{
const HistoryItem& item = *i;
if (item.ts >= mintime)
{
ClientProtocol::Messages::Privmsg msg(ClientProtocol::Messages::Privmsg::nocopy, item.sourcemask, memb->chan, item.text);
if (servertimemanager)
servertimemanager->Set(msg, item.ts);
batch.AddToBatch(msg);
localuser->Send(ServerInstance->GetRFCEvents().privmsg, msg);
}
}
if (batchmanager)
batchmanager->End(batch);
SendHistory(localuser, memb->chan, list, mintime);
}
Version GetVersion() override

View File

@ -261,8 +261,8 @@ class CommandCheck : public Command
for (Channel::MemberMap::const_iterator i = ulist.begin(); i != ulist.end(); ++i)
{
/*
* Unlike Asuka, I define a clone as coming from the same host. --w00t
*/
* Unlike Asuka, I define a clone as coming from the same host. --w00t
*/
const UserManager::CloneCounts& clonecount = ServerInstance->Users.GetCloneCounts(i->first);
context.Write("member", InspIRCd::Format("%u %s%s (%s)", clonecount.global,
i->second->GetAllPrefixChars().c_str(), i->first->GetFullHost().c_str(),

View File

@ -20,8 +20,12 @@
#include "inspircd.h"
#include "modules/ircv3.h"
#include "modules/ircv3_servertime.h"
#include "modules/server.h"
class ServerTimeTag : public IRCv3::ServerTime::Manager, public IRCv3::CapTag<ServerTimeTag>
class ServerTimeTag
: public IRCv3::ServerTime::Manager
, public IRCv3::CapTag<ServerTimeTag>
, public ServerProtocol::MessageEventListener
{
time_t lasttime;
long lasttimens;
@ -45,6 +49,7 @@ class ServerTimeTag : public IRCv3::ServerTime::Manager, public IRCv3::CapTag<Se
ServerTimeTag(Module* mod)
: IRCv3::ServerTime::Manager(mod)
, IRCv3::CapTag<ServerTimeTag>(mod, "server-time", "time")
, ServerProtocol::MessageEventListener(mod)
, lasttime(0)
, lasttimens(0)
{
@ -53,9 +58,18 @@ class ServerTimeTag : public IRCv3::ServerTime::Manager, public IRCv3::CapTag<Se
const std::string* GetValue(const ClientProtocol::Message& msg)
{
// Client protocol.
RefreshTimeString();
return &lasttimestring;
}
void OnBuildMessage(User* source, const char* command, ClientProtocol::TagMap& tags) override
{
// Server protocol.
RefreshTimeString();
tags.insert(std::make_pair(tagname, ClientProtocol::MessageTagData(this, lasttimestring)));
}
};
class ModuleIRCv3ServerTime : public Module

View File

@ -285,7 +285,7 @@ class SaslAuthenticator
case SASL_OK:
this->user->WriteNumeric(RPL_SASLSUCCESS, "SASL authentication successful");
break;
case SASL_ABORT:
case SASL_ABORT:
this->user->WriteNumeric(ERR_SASLABORTED, "SASL authentication aborted");
break;
case SASL_FAIL:

View File

@ -33,7 +33,7 @@ class CommandSATopic : public Command
{
/*
* Handles a SATOPIC request. Notifies all +s users.
*/
*/
Channel* target = ServerInstance->FindChan(parameters[0]);
if(target)

View File

@ -26,28 +26,53 @@ class TreeServer;
class CmdBuilder
{
protected:
/** The raw message contents. */
std::string content;
/** Tags which have been added to this message. */
ClientProtocol::TagMap tags;
/** The size of tags within the contents. */
size_t tagsize;
/** Fires the ServerProtocol::MessageEventListener::OnBuildMessage event for a server target. */
void FireEvent(Server* target, const char* cmd, ClientProtocol::TagMap& taglist);
/** Fires the ServerProtocol::MessageEventListener::OnBuildMessage event for a user target. */
void FireEvent(User* target, const char* cmd, ClientProtocol::TagMap& taglist);
/** Updates the tag string within the buffer. */
void UpdateTags();
public:
CmdBuilder(const char* cmd)
: content(1, ':')
, tagsize(0)
{
content.append(ServerInstance->Config->GetSID());
push(cmd);
FireEvent(ServerInstance->FakeClient->server, cmd, tags);
}
CmdBuilder(const std::string& src, const char* cmd)
CmdBuilder(TreeServer* src, const char* cmd)
: content(1, ':')
, tagsize(0)
{
content.append(src);
content.append(src->GetID());
push(cmd);
FireEvent(src, cmd, tags);
}
CmdBuilder(User* src, const char* cmd)
: content(1, ':')
, tagsize(0)
{
content.append(src->uuid);
push(cmd);
if (InspIRCd::IsSID(src->uuid))
FireEvent(src->server, cmd, tags);
else
FireEvent(src, cmd, tags);
}
CmdBuilder& push_raw(const std::string& s)
@ -119,27 +144,12 @@ class CmdBuilder
return *this;
}
CmdBuilder& push_tags(const ClientProtocol::TagMap& tags)
CmdBuilder& push_tags(ClientProtocol::TagMap newtags)
{
if (!tags.empty())
{
char separator = '@';
std::string taglist;
for (ClientProtocol::TagMap::const_iterator iter = tags.begin(); iter != tags.end(); ++iter)
{
taglist.push_back(separator);
separator = ';';
taglist.append(iter->first);
if (!iter->second.value.empty())
{
taglist.push_back('=');
taglist.append(iter->second.value);
}
}
taglist.push_back(' ');
content.insert(0, taglist);
}
// It has to be this way around so new tags get priority.
newtags.insert(tags.begin(), tags.end());
std::swap(tags, newtags);
UpdateTags();
return *this;
}
@ -151,8 +161,6 @@ class CmdBuilder
return *this;
}
void push_back(const std::string& s) { push(s); }
const std::string& str() const { return content; }
operator const std::string&() const { return str(); }

View File

@ -286,7 +286,12 @@ void TreeSocket::WriteLine(const std::string& original_line)
// Synthesize a :<newserver> BURST <time> message
spcolon = line.find(" :");
line = CmdBuilder(line.substr(spcolon-3, 3), "BURST").push_int(ServerInstance->Time()).str();
TreeServer* const source = Utils->FindServerID(line.substr(spcolon-3, 3));
if (!source)
return;
line = CmdBuilder(source, "BURST").push_int(ServerInstance->Time()).str();
}
}
else if (command == "NUM")

View File

@ -295,7 +295,7 @@ void CommandFJoin::LowerTS(Channel* chan, time_t TS, const std::string& newname)
}
CommandFJoin::Builder::Builder(Channel* chan, TreeServer* source)
: CmdBuilder(source->GetID(), "FJOIN")
: CmdBuilder(source, "FJOIN")
{
push(chan->name).push_int(chan->age).push_raw(" +");
pos = str().size();

View File

@ -59,10 +59,10 @@ CmdResult CommandIdle::HandleRemote(RemoteUser* issuer, Params& params)
else
idle = ((unsigned int) (ServerInstance->Time() - localtarget->idle_lastmsg));
CmdBuilder reply(params[0], "IDLE");
reply.push_back(issuer->uuid);
reply.push_back(ConvToStr(target->signon));
reply.push_back(ConvToStr(idle));
CmdBuilder reply(target, "IDLE");
reply.push(issuer->uuid);
reply.push(ConvToStr(target->signon));
reply.push(ConvToStr(idle));
reply.Unicast(issuer);
}

View File

@ -25,7 +25,6 @@
#include "socket.h"
#include "xline.h"
#include "iohook.h"
#include "modules/server.h"
#include "resolvers.h"
#include "main.h"
@ -47,6 +46,7 @@ ModuleSpanningTree::ModuleSpanningTree()
, currmembid(0)
, broadcasteventprov(this, "event/server-broadcast")
, linkeventprov(this, "event/server-link")
, messageeventprov(this, "event/server-message")
, synceventprov(this, "event/server-sync")
, sslapi(this)
, DNS(this, "DNS")
@ -359,10 +359,10 @@ void ModuleSpanningTree::OnUserInvite(User* source, User* dest, Channel* channel
if (IS_LOCAL(source))
{
CmdBuilder params(source, "INVITE");
params.push_back(dest->uuid);
params.push_back(channel->name);
params.push(dest->uuid);
params.push(channel->name);
params.push_int(channel->age);
params.push_back(ConvToStr(expiry));
params.push(ConvToStr(expiry));
params.Broadcast();
}
}
@ -403,7 +403,7 @@ void ModuleSpanningTree::OnUserPostMessage(User* user, const MessageTarget& targ
{
CmdBuilder params(user, message_type);
params.push_tags(details.tags_out);
params.push_back(d->uuid);
params.push(d->uuid);
params.push_last(details.text);
params.Unicast(d);
}
@ -411,7 +411,7 @@ void ModuleSpanningTree::OnUserPostMessage(User* user, const MessageTarget& targ
}
case MessageTarget::TYPE_CHANNEL:
{
Utils->SendChannelMessage(user->uuid, target.Get<Channel>(), details.text, target.status, details.tags_out, details.exemptions, message_type);
Utils->SendChannelMessage(user, target.Get<Channel>(), details.text, target.status, details.tags_out, details.exemptions, message_type);
break;
}
case MessageTarget::TYPE_SERVER:
@ -419,7 +419,7 @@ void ModuleSpanningTree::OnUserPostMessage(User* user, const MessageTarget& targ
const std::string* serverglob = target.Get<std::string>();
CmdBuilder par(user, message_type);
par.push_tags(details.tags_out);
par.push_back(*serverglob);
par.push(*serverglob);
par.push_last(details.text);
par.Broadcast();
break;
@ -441,14 +441,14 @@ void ModuleSpanningTree::OnUserPostTagMessage(User* user, const MessageTarget& t
{
CmdBuilder params(user, "TAGMSG");
params.push_tags(details.tags_out);
params.push_back(d->uuid);
params.push(d->uuid);
params.Unicast(d);
}
break;
}
case MessageTarget::TYPE_CHANNEL:
{
Utils->SendChannelMessage(user->uuid, target.Get<Channel>(), "", target.status, details.tags_out, details.exemptions, "TAGMSG");
Utils->SendChannelMessage(user, target.Get<Channel>(), "", target.status, details.tags_out, details.exemptions, "TAGMSG");
break;
}
case MessageTarget::TYPE_SERVER:
@ -456,7 +456,7 @@ void ModuleSpanningTree::OnUserPostTagMessage(User* user, const MessageTarget& t
const std::string* serverglob = target.Get<std::string>();
CmdBuilder par(user, "TAGMSG");
par.push_tags(details.tags_out);
par.push_back(*serverglob);
par.push(*serverglob);
par.Broadcast();
break;
}
@ -513,12 +513,12 @@ void ModuleSpanningTree::OnUserJoin(Membership* memb, bool sync, bool created_by
else
{
CmdBuilder params(memb->user, "IJOIN");
params.push_back(memb->chan->name);
params.push(memb->chan->name);
params.push_int(memb->id);
if (!memb->modes.empty())
{
params.push_back(ConvToStr(memb->chan->age));
params.push_back(memb->modes);
params.push(ConvToStr(memb->chan->age));
params.push(memb->modes);
}
params.Broadcast();
}
@ -553,7 +553,7 @@ void ModuleSpanningTree::OnUserPart(Membership* memb, std::string &partmessage,
if (IS_LOCAL(memb->user))
{
CmdBuilder params(memb->user, "PART");
params.push_back(memb->chan->name);
params.push(memb->chan->name);
if (!partmessage.empty())
params.push_last(partmessage);
params.Broadcast();
@ -593,8 +593,8 @@ void ModuleSpanningTree::OnUserPostNick(User* user, const std::string &oldnick)
{
// The nick TS is updated by the core, we don't do it
CmdBuilder params(user, "NICK");
params.push_back(user->nick);
params.push_back(ConvToStr(user->age));
params.push(user->nick);
params.push(ConvToStr(user->age));
params.Broadcast();
}
else if (!loopCall)
@ -609,8 +609,8 @@ void ModuleSpanningTree::OnUserKick(User* source, Membership* memb, const std::s
return;
CmdBuilder params(source, "KICK");
params.push_back(memb->chan->name);
params.push_back(memb->user->uuid);
params.push(memb->chan->name);
params.push(memb->user->uuid);
// If a remote user is being kicked by us then send the membership id in the kick too
if (!IS_LOCAL(memb->user))
params.push_int(memb->id);
@ -625,8 +625,8 @@ void ModuleSpanningTree::OnPreRehash(User* user, const std::string &parameter)
// Send out to other servers
if (!parameter.empty() && parameter[0] != '-')
{
CmdBuilder params((user ? user->uuid : ServerInstance->Config->GetSID()), "REHASH");
params.push_back(parameter);
CmdBuilder params(user ? user : ServerInstance->FakeClient, "REHASH");
params.push(parameter);
params.Forward(user ? TreeServer::Get(user)->GetRoute() : NULL);
}
}
@ -749,8 +749,8 @@ void ModuleSpanningTree::OnDelLine(User* user, XLine *x)
user = ServerInstance->FakeClient;
CmdBuilder params(user, "DELLINE");
params.push_back(x->type);
params.push_back(x->Displayable());
params.push(x->type);
params.push(x->Displayable());
params.Broadcast();
}

View File

@ -29,6 +29,7 @@
#include "modules/ssl.h"
#include "modules/stats.h"
#include "modules/ctctags.h"
#include "modules/server.h"
#include "servercommand.h"
#include "commands.h"
#include "protocolinterface.h"
@ -99,6 +100,9 @@ class ModuleSpanningTree
/** Event provider for our link events. */
Events::ModuleEventProvider linkeventprov;
/** Event provider for our message events. */
Events::ModuleEventProvider messageeventprov;
/** Event provider for our sync events. */
Events::ModuleEventProvider synceventprov;
@ -169,6 +173,9 @@ class ModuleSpanningTree
/** Retrieves the event provider for link events. */
const Events::ModuleEventProvider& GetLinkEventProvider() const { return linkeventprov; }
/** Retrieves the event provider for message events. */
const Events::ModuleEventProvider& GetMessageEventProvider() const { return messageeventprov; }
/** Retrieves the event provider for sync events. */
const Events::ModuleEventProvider& GetSyncEventProvider() const { return synceventprov; }

View File

@ -29,6 +29,41 @@
#include "commands.h"
#include "treeserver.h"
void CmdBuilder::FireEvent(Server* target, const char* cmd, ClientProtocol::TagMap& taglist)
{
FOREACH_MOD_CUSTOM(Utils->Creator->GetMessageEventProvider(), ServerProtocol::MessageEventListener, OnBuildMessage, (target, cmd, taglist));
UpdateTags();
}
void CmdBuilder::FireEvent(User* target, const char* cmd, ClientProtocol::TagMap& taglist)
{
FOREACH_MOD_CUSTOM(Utils->Creator->GetMessageEventProvider(), ServerProtocol::MessageEventListener, OnBuildMessage, (target, cmd, taglist));
UpdateTags();
}
void CmdBuilder::UpdateTags()
{
std::string taglist;
if (!tags.empty())
{
char separator = '@';
for (ClientProtocol::TagMap::const_iterator iter = tags.begin(); iter != tags.end(); ++iter)
{
taglist.push_back(separator);
separator = ';';
taglist.append(iter->first);
if (!iter->second.value.empty())
{
taglist.push_back('=');
taglist.append(iter->second.value);
}
}
taglist.push_back(' ');
}
content.replace(0, tagsize, taglist);
tagsize = taglist.length();
}
CmdResult CommandSNONotice::Handle(User* user, Params& params)
{
ServerInstance->SNO.WriteToSnoMask(params[0][0], "From " + user->nick + ": " + params[1]);

View File

@ -27,7 +27,6 @@
#include "treeserver.h"
#include "main.h"
#include "commands.h"
#include "modules/server.h"
/**
* Creates FMODE messages, used only when syncing channels

View File

@ -108,8 +108,8 @@ bool SpanningTreeUtilities::DoCollision(User* u, TreeServer* server, time_t remo
* this "local" nick is actually behind us, send a SAVE out.
*/
CmdBuilder params("SAVE");
params.push_back(u->uuid);
params.push_back(ConvToStr(u->age));
params.push(u->uuid);
params.push(ConvToStr(u->age));
params.Broadcast();
u->ChangeNick(u->uuid, CommandSave::SavedTimestamp);

View File

@ -30,10 +30,10 @@ CmdResult CommandPing::Handle(User* user, Params& params)
{
// PING for us, reply with a PONG
CmdBuilder reply("PONG");
reply.push_back(user->uuid);
reply.push(user->uuid);
if (params.size() >= 2)
// If there is a second parameter, append it
reply.push_back(params[1]);
reply.push(params[1]);
reply.Unicast(user);
}

View File

@ -45,7 +45,7 @@ void SpanningTreeUtilities::RouteCommand(TreeServer* origin, CommandBase* thiscm
if (routing.type == ROUTE_TYPE_OPT_BCAST)
{
params.push('*');
params.push_back(command);
params.push(command);
}
else if (routing.type == ROUTE_TYPE_UNICAST || routing.type == ROUTE_TYPE_OPT_UCAST)
{
@ -64,8 +64,8 @@ void SpanningTreeUtilities::RouteCommand(TreeServer* origin, CommandBase* thiscm
if (encap)
{
params.push_back(sdest->GetID());
params.push_back(command);
params.push(sdest->GetID());
params.push(command);
}
}
else
@ -83,7 +83,7 @@ void SpanningTreeUtilities::RouteCommand(TreeServer* origin, CommandBase* thiscm
std::string output_text = CommandParser::TranslateUIDs(thiscmd->translation, parameters, true, thiscmd);
params.push_back(output_text);
params.push(output_text);
if (routing.type == ROUTE_TYPE_MESSAGE)
{
@ -104,7 +104,7 @@ void SpanningTreeUtilities::RouteCommand(TreeServer* origin, CommandBase* thiscm
std::string message;
if (parameters.size() >= 2)
message.assign(parameters[1]);
SendChannelMessage(user->uuid, c, message, pfx, parameters.GetTags(), exempts, command.c_str(), origin ? origin->GetSocket() : NULL);
SendChannelMessage(user, c, message, pfx, parameters.GetTags(), exempts, command.c_str(), origin ? origin->GetSocket() : NULL);
}
else if (dest[0] == '$')
{

View File

@ -112,13 +112,13 @@ void SpanningTreeProtocolInterface::SendMessage(Channel* target, char status, co
const char* cmd = (msgtype == MSG_PRIVMSG ? "PRIVMSG" : "NOTICE");
CUList exempt_list;
ClientProtocol::TagMap tags;
Utils->SendChannelMessage(ServerInstance->Config->GetSID(), target, text, status, tags, exempt_list, cmd);
Utils->SendChannelMessage(ServerInstance->FakeClient, target, text, status, tags, exempt_list, cmd);
}
void SpanningTreeProtocolInterface::SendMessage(User* target, const std::string& text, MessageType msgtype)
{
CmdBuilder p(msgtype == MSG_PRIVMSG ? "PRIVMSG" : "NOTICE");
p.push_back(target->uuid);
p.push(target->uuid);
p.push_last(text);
p.Unicast(target);
}

View File

@ -225,7 +225,7 @@ bool TreeSocket::Inbound_Server(CommandBase::Params& params)
}
CommandServer::Builder::Builder(TreeServer* server)
: CmdBuilder(server->GetParent()->GetID(), "SERVER")
: CmdBuilder(server->GetParent(), "SERVER")
{
push(server->GetName());
push(server->GetID());

View File

@ -49,7 +49,7 @@ CmdResult CommandSInfo::HandleServer(TreeServer* server, CommandBase::Params& pa
}
CommandSInfo::Builder::Builder(TreeServer* server, const char* key, const std::string& val)
: CmdBuilder(server->GetID(), "SINFO")
: CmdBuilder(server, "SINFO")
{
push(key).push_last(val);
}

View File

@ -23,7 +23,6 @@
#include "inspircd.h"
#include "xline.h"
#include "main.h"
#include "modules/server.h"
#include "utils.h"
#include "treeserver.h"

View File

@ -24,7 +24,6 @@
#include "iohook.h"
#include "main.h"
#include "modules/server.h"
#include "utils.h"
#include "treeserver.h"
#include "link.h"

View File

@ -152,7 +152,7 @@ CmdResult CommandFName::HandleRemote(RemoteUser* src, Params& params)
}
CommandUID::Builder::Builder(User* user)
: CmdBuilder(TreeServer::Get(user)->GetID(), "UID")
: CmdBuilder(TreeServer::Get(user), "UID")
{
push(user->uuid);
push_int(user->age);

View File

@ -28,7 +28,6 @@
#include "treesocket.h"
#include "resolvers.h"
#include "commandbuilder.h"
#include "modules/server.h"
SpanningTreeUtilities* Utils = NULL;
@ -351,9 +350,9 @@ Link* SpanningTreeUtilities::FindLink(const std::string& name)
return NULL;
}
void SpanningTreeUtilities::SendChannelMessage(const std::string& prefix, Channel* target, const std::string& text, char status, const ClientProtocol::TagMap& tags, const CUList& exempt_list, const char* message_type, TreeSocket* omit)
void SpanningTreeUtilities::SendChannelMessage(User* source, Channel* target, const std::string& text, char status, const ClientProtocol::TagMap& tags, const CUList& exempt_list, const char* message_type, TreeSocket* omit)
{
CmdBuilder msg(prefix, message_type);
CmdBuilder msg(source, message_type);
msg.push_tags(tags);
msg.push_raw(' ');
if (status != 0)

View File

@ -172,7 +172,7 @@ class SpanningTreeUtilities : public classbase
/** Sends a PRIVMSG or a NOTICE to a channel obeying an exempt list and an optional prefix
*/
void SendChannelMessage(const std::string& prefix, Channel* target, const std::string& text, char status, const ClientProtocol::TagMap& tags, const CUList& exempt_list, const char* message_type, TreeSocket* omit = NULL);
void SendChannelMessage(User* source, Channel* target, const std::string& text, char status, const ClientProtocol::TagMap& tags, const CUList& exempt_list, const char* message_type, TreeSocket* omit = NULL);
};
inline void SpanningTreeUtilities::DoOneToMany(const CmdBuilder& params)

View File

@ -50,6 +50,12 @@ EventHandler::EventHandler()
event_mask = 0;
}
void EventHandler::SwapInternals(EventHandler& other)
{
std::swap(fd, other.fd);
std::swap(event_mask, other.event_mask);
}
void EventHandler::SetFd(int FD)
{
this->fd = FD;

View File

@ -58,6 +58,16 @@ namespace
// This user didn't answer the last ping, remove them.
if (!user->lastping)
{
ModResult res;
FIRST_MOD_RESULT(OnConnectionFail, res, (user, I_ERR_TIMEOUT));
if (res == MOD_RES_ALLOW)
{
// A module is preventing this user from being timed out.
user->lastping = 1;
user->nextping = ServerInstance->Time() + user->MyClass->GetPingTime();
return;
}
time_t secs = ServerInstance->Time() - (user->nextping - user->MyClass->GetPingTime());
const std::string message = "Ping timeout: " + ConvToStr(secs) + (secs != 1 ? " seconds" : " second");
ServerInstance->Users.QuitUser(user, message);

View File

@ -301,6 +301,12 @@ void UserIOHandler::AddWriteBuf(const std::string &data)
WriteData(data);
}
void UserIOHandler::SwapInternals(UserIOHandler& other)
{
StreamSocket::SwapInternals(other);
std::swap(checked_until, other.checked_until);
}
bool UserIOHandler::OnSetEndPoint(const irc::sockets::sockaddrs& server, const irc::sockets::sockaddrs& client)
{
memcpy(&user->server_sa, &server, sizeof(irc::sockets::sockaddrs));
@ -308,9 +314,12 @@ bool UserIOHandler::OnSetEndPoint(const irc::sockets::sockaddrs& server, const i
return !user->quitting;
}
void UserIOHandler::OnError(BufferedSocketError)
void UserIOHandler::OnError(BufferedSocketError error)
{
ServerInstance->Users.QuitUser(user, getError());
ModResult res;
FIRST_MOD_RESULT(OnConnectionFail, res, (user, error));
if (res != MOD_RES_ALLOW)
ServerInstance->Users.QuitUser(user, getError());
}
CullResult User::cull()
@ -478,14 +487,20 @@ void LocalUser::CheckClass(bool clone_count)
{
ServerInstance->Users.QuitUser(this, "No more connections allowed from your host via this connect class (local)");
if (a->maxconnwarn)
ServerInstance->SNO.WriteToSnoMask('a', "WARNING: maximum LOCAL connections (%ld) exceeded for IP %s", a->GetMaxLocal(), this->GetIPString().c_str());
{
ServerInstance->SNO.WriteToSnoMask('a', "WARNING: maximum local connections for the %s class (%ld) exceeded by %s",
a->name.c_str(), a->GetMaxLocal(), this->GetIPString().c_str());
}
return;
}
else if ((a->GetMaxGlobal()) && (clonecounts.global > a->GetMaxGlobal()))
{
ServerInstance->Users.QuitUser(this, "No more connections allowed from your host via this connect class (global)");
if (a->maxconnwarn)
ServerInstance->SNO.WriteToSnoMask('a', "WARNING: maximum GLOBAL connections (%ld) exceeded for IP %s", a->GetMaxGlobal(), this->GetIPString().c_str());
{
ServerInstance->SNO.WriteToSnoMask('a', "WARNING: maximum global connections for the %s class (%ld) exceeded by %s",
a->name.c_str(), a->GetMaxGlobal(), this->GetIPString().c_str());
}
return;
}
}