]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Introduce Stats::Context, pass it to the OnStats hook and switch all code to it
authorAttila Molnar <attilamolnar@hush.com>
Thu, 25 Feb 2016 16:02:03 +0000 (17:02 +0100)
committerAttila Molnar <attilamolnar@hush.com>
Thu, 25 Feb 2016 16:02:03 +0000 (17:02 +0100)
19 files changed:
include/inspircd.h
include/modules.h
include/modules/stats.h [new file with mode: 0644]
include/typedefs.h
include/xline.h
src/coremods/core_stats.cpp
src/coremods/core_whowas.cpp
src/modules.cpp
src/modules/extra/m_geoip.cpp
src/modules/m_cban.cpp
src/modules/m_dnsbl.cpp
src/modules/m_filter.cpp
src/modules/m_hideoper.cpp
src/modules/m_rline.cpp
src/modules/m_shun.cpp
src/modules/m_spanningtree/main.h
src/modules/m_spanningtree/override_stats.cpp
src/modules/m_svshold.cpp
src/xline.cpp

index 9311488842374005b4c0c25cbde4707fb7b88dc5..ee09070f858799d5ffca7c534769c9a96dadc3ca 100644 (file)
@@ -587,3 +587,4 @@ inline void stdalgo::culldeleter::operator()(classbase* item)
 
 #include "numericbuilder.h"
 #include "modules/whois.h"
+#include "modules/stats.h"
index 86ee7f4f3397341748d98fd76a31f16add378446..d97f02046cd24a3b1749e6105d11c62fb0f667a6 100644 (file)
@@ -873,14 +873,10 @@ class CoreExport Module : public classbase, public usecountbase
 
        /** Called on all /STATS commands
         * This method is triggered for all /STATS use, including stats symbols handled by the core.
-        * @param symbol the symbol provided to /STATS
-        * @param user the user issuing the /STATS command
-        * @param results A string_list to append results into. You should put all your results
-        * into this string_list, rather than displaying them directly, so that your handler will
-        * work when remote STATS queries are received.
+        * @param stats Context of the /STATS request, contains requesting user, list of answer rows etc.
         * @return 1 to block the /STATS from being processed by the core, 0 to allow it
         */
-       virtual ModResult OnStats(char symbol, User* user, string_list &results);
+       virtual ModResult OnStats(Stats::Context& stats);
 
        /** Called whenever a change of a local users displayed host is attempted.
         * Return 1 to deny the host change, or 0 to allow it.
diff --git a/include/modules/stats.h b/include/modules/stats.h
new file mode 100644 (file)
index 0000000..b1e27b4
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *   Copyright (C) 2016 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
+
+namespace Stats
+{
+       class Context;
+       class Row;
+}
+
+class Stats::Row : public Numeric::Numeric
+{
+ public:
+       Row(unsigned int num)
+               : Numeric(num)
+       {
+       }
+};
+
+class Stats::Context
+{
+       /** Source user of the STATS request
+        */
+       User* const source;
+
+       /** List of reply rows
+        */
+       std::vector<Row> rows;
+
+       /** Symbol indicating the type of this STATS request (usually a letter)
+        */
+       const char symbol;
+
+ public:
+       /** Constructor
+        * @param src Source user of the STATS request, can be a local or remote user
+        * @param sym Symbol (letter) indicating the type of the request
+        */
+       Context(User* src, char sym)
+               : source(src)
+               , symbol(sym)
+       {
+       }
+
+       /** Get the source user of the STATS request
+        * @return Source user of the STATS request
+        */
+       User* GetSource() const { return source; }
+
+       /** Get the list of reply rows
+        * @return List of rows generated as reply for the request
+        */
+       const std::vector<Row>& GetRows() const { return rows; }
+
+       /** Get the symbol (letter) indicating what type of STATS was requested
+        * @return Symbol specified by the requesting user
+        */
+       char GetSymbol() const { return symbol; }
+
+       /** Add a row to the reply list
+        * @param row Reply to add
+        */
+       void AddRow(const Row& row) { rows.push_back(row); }
+
+       template <typename T1>
+       void AddRow(unsigned int numeric, T1 p1)
+       {
+               Row n(numeric);
+               n.push(p1);
+               AddRow(n);
+       }
+
+       template <typename T1, typename T2>
+       void AddRow(unsigned int numeric, T1 p1, T2 p2)
+       {
+               Row n(numeric);
+               n.push(p1);
+               n.push(p2);
+               AddRow(n);
+       }
+
+       template <typename T1, typename T2, typename T3>
+       void AddRow(unsigned int numeric, T1 p1, T2 p2, T3 p3)
+       {
+               Row n(numeric);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               AddRow(n);
+       }
+
+       template <typename T1, typename T2, typename T3, typename T4>
+       void AddRow(unsigned int numeric, T1 p1, T2 p2, T3 p3, T4 p4)
+       {
+               Row n(numeric);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               n.push(p4);
+               AddRow(n);
+       }
+
+       template <typename T1, typename T2, typename T3, typename T4, typename T5>
+       void AddRow(unsigned int numeric, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5)
+       {
+               Row n(numeric);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               n.push(p4);
+               n.push(p5);
+               AddRow(n);
+       }
+
+       template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+       void AddRow(unsigned int numeric, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6)
+       {
+               Row n(numeric);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               n.push(p4);
+               n.push(p5);
+               n.push(p6);
+               AddRow(n);
+       }
+
+       template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
+       void AddRow(unsigned int numeric, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7)
+       {
+               Row n(numeric);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               n.push(p4);
+               n.push(p5);
+               n.push(p6);
+               n.push(p7);
+               AddRow(n);
+       }
+
+       template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
+       void AddRow(unsigned int numeric, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8)
+       {
+               Row n(numeric);
+               n.push(p1);
+               n.push(p2);
+               n.push(p3);
+               n.push(p4);
+               n.push(p5);
+               n.push(p6);
+               n.push(p7);
+               AddRow(n);
+       }
+};
index dfecb04837a5ce4220047764e8457e505db2d888..17c05d704a83b9e570e661388ad08b15c5a46a0c 100644 (file)
@@ -111,3 +111,8 @@ typedef XLineContainer::iterator ContainerIter;
 /** An interator in an XLineLookup
  */
 typedef XLineLookup::iterator LookupIter;
+
+namespace Stats
+{
+       class Context;
+}
index fe044d0f2d07b7ef119606dc0d7fd8464e979473..c2ede29dfb458c2904761fa8f0734d8d8b615a56 100644 (file)
@@ -520,8 +520,7 @@ class CoreExport XLineManager
         * will be expired and removed before the list is displayed.
         * @param type The type of stats to show
         * @param numeric The numeric to give to each result line
-        * @param user The username making the query
-        * @param results The string_list to receive the results
+        * @param stats Stats context
         */
-       void InvokeStats(const std::string &type, int numeric, User* user, string_list &results);
+       void InvokeStats(const std::string& type, unsigned int numeric, Stats::Context& stats);
 };
index 9fb232bc0192bb7a2e1d0210f1e580a09042df3d..69f1f3cf89e384d16568cf608e1231781cf30911 100644 (file)
@@ -31,7 +31,7 @@
  */
 class CommandStats : public Command
 {
-       void DoStats(char statschar, User* user, string_list &results);
+       void DoStats(Stats::Context& stats);
  public:
        /** Constructor for stats.
         */
@@ -50,20 +50,23 @@ class CommandStats : public Command
        }
 };
 
-static void GenerateStatsLl(User* user, string_list& results, char c)
+static void GenerateStatsLl(Stats::Context& stats)
 {
-       results.push_back(InspIRCd::Format("211 %s nick[ident@%s] sendq cmds_out bytes_out cmds_in bytes_in time_open", user->nick.c_str(), (c == 'l' ? "host" : "ip")));
+       stats.AddRow(211, InspIRCd::Format("nick[ident@%s] sendq cmds_out bytes_out cmds_in bytes_in time_open", (stats.GetSymbol() == 'l' ? "host" : "ip")));
 
        const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers();
        for (UserManager::LocalList::const_iterator i = list.begin(); i != list.end(); ++i)
        {
                LocalUser* u = *i;
-               results.push_back("211 "+user->nick+" "+u->nick+"["+u->ident+"@"+(c == 'l' ? u->dhost : u->GetIPString())+"] "+ConvToStr(u->eh.getSendQSize())+" "+ConvToStr(u->cmds_out)+" "+ConvToStr(u->bytes_out)+" "+ConvToStr(u->cmds_in)+" "+ConvToStr(u->bytes_in)+" "+ConvToStr(ServerInstance->Time() - u->signon));
+               stats.AddRow(211, u->nick+"["+u->ident+"@"+(stats.GetSymbol() == 'l' ? u->dhost : u->GetIPString())+"] "+ConvToStr(u->eh.getSendQSize())+" "+ConvToStr(u->cmds_out)+" "+ConvToStr(u->bytes_out)+" "+ConvToStr(u->cmds_in)+" "+ConvToStr(u->bytes_in)+" "+ConvToStr(ServerInstance->Time() - u->signon));
        }
 }
 
-void CommandStats::DoStats(char statschar, User* user, string_list &results)
+void CommandStats::DoStats(Stats::Context& stats)
 {
+       User* const user = stats.GetSource();
+       const char statschar = stats.GetSymbol();
+
        bool isPublic = ServerInstance->Config->UserStats.find(statschar) != std::string::npos;
        bool isRemoteOper = IS_REMOTE(user) && (user->IsOper());
        bool isLocalOperWithPrivs = IS_LOCAL(user) && user->HasPrivPermission("servers/auspex");
@@ -74,15 +77,15 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                                "%s '%c' denied for %s (%s@%s)",
                                (IS_LOCAL(user) ? "Stats" : "Remote stats"),
                                statschar, user->nick.c_str(), user->ident.c_str(), user->host.c_str());
-               results.push_back("481 " + user->nick + " :Permission Denied - STATS " + statschar + " requires the servers/auspex priv.");
+               stats.AddRow(481, (std::string("Permission Denied - STATS ") + statschar + " requires the servers/auspex priv."));
                return;
        }
 
        ModResult MOD_RESULT;
-       FIRST_MOD_RESULT(OnStats, MOD_RESULT, (statschar, user, results));
+       FIRST_MOD_RESULT(OnStats, MOD_RESULT, (stats));
        if (MOD_RESULT == MOD_RES_DENY)
        {
-               results.push_back("219 "+user->nick+" "+statschar+" :End of /STATS report");
+               stats.AddRow(219, statschar, "End of /STATS report");
                ServerInstance->SNO->WriteToSnoMask('t',"%s '%c' requested by %s (%s@%s)",
                        (IS_LOCAL(user) ? "Stats" : "Remote stats"), statschar, user->nick.c_str(), user->ident.c_str(), user->host.c_str());
                return;
@@ -107,8 +110,7 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                                std::string type = ls->bind_tag->getString("type", "clients");
                                std::string hook = ls->bind_tag->getString("ssl", "plaintext");
 
-                               results.push_back("249 "+user->nick+" :"+ ip + ":"+ConvToStr(ls->bind_port)+
-                                       " (" + type + ", " + hook + ")");
+                               stats.AddRow(249, ip + ":"+ConvToStr(ls->bind_port) + " (" + type + ", " + hook + ")");
                        }
                }
                break;
@@ -123,25 +125,29 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                        for (ServerConfig::ClassVector::const_iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); ++i)
                        {
                                ConnectClass* c = *i;
-                               std::stringstream res;
-                               res << "215 " << user->nick << " I " << c->name << ' ';
+                               Stats::Row row(215);
+                               row.push("I").push(c->name);
+
+                               std::string param;
                                if (c->type == CC_ALLOW)
-                                       res << '+';
+                                       param.push_back('+');
                                if (c->type == CC_DENY)
-                                       res << '-';
+                                       param.push_back('-');
 
                                if (c->type == CC_NAMED)
-                                       res << '*';
+                                       param.push_back('*');
                                else
-                                       res << c->host;
+                                       param.append(c->host);
 
-                               res << ' ' << c->config->getString("port", "*") << ' ';
+                               row.push(param).push(c->config->getString("port", "*"));
+                               row.push(ConvToStr(c->GetRecvqMax())).push(ConvToStr(c->GetSendqSoftMax())).push(ConvToStr(c->GetSendqHardMax())).push(ConvToStr(c->GetCommandRate()));
 
-                               res << c->GetRecvqMax() << ' ' << c->GetSendqSoftMax() << ' ' << c->GetSendqHardMax()
-                                       << ' ' << c->GetCommandRate() << ' ' << c->GetPenaltyThreshold();
+                               param = ConvToStr(c->GetPenaltyThreshold());
                                if (c->fakelag)
-                                       res << '*';
-                               results.push_back(res.str());
+                                       param.push_back('*');
+                               row.push(param);
+
+                               stats.AddRow(row);
                        }
                }
                break;
@@ -152,9 +158,8 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                        for (ServerConfig::ClassVector::const_iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++)
                        {
                                ConnectClass* c = *i;
-                               results.push_back("215 "+user->nick+" i NOMATCH * "+c->GetHost()+" "+ConvToStr(c->limit ? c->limit : SocketEngine::GetMaxFds())+" "+ConvToStr(idx)+" "+ServerInstance->Config->ServerName+" *");
-                               results.push_back("218 "+user->nick+" Y "+ConvToStr(idx)+" "+ConvToStr(c->GetPingTime())+" 0 "+ConvToStr(c->GetSendqHardMax())+" :"+
-                                               ConvToStr(c->GetRecvqMax())+" "+ConvToStr(c->GetRegTimeout()));
+                               stats.AddRow(215, 'i', "NOMATCH", '*', c->GetHost(), (c->limit ? c->limit : SocketEngine::GetMaxFds()), idx, ServerInstance->Config->ServerName, '*');
+                               stats.AddRow(218, 'Y', idx, c->GetPingTime(), '0', c->GetSendqHardMax(), ConvToStr(c->GetRecvqMax())+" "+ConvToStr(c->GetRegTimeout()));
                                idx++;
                        }
                }
@@ -170,37 +175,37 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                                if (!oper->server->IsULine())
                                {
                                        LocalUser* lu = IS_LOCAL(oper);
-                                       results.push_back("249 " + user->nick + " :" + oper->nick + " (" + oper->ident + "@" + oper->dhost + ") Idle: " +
+                                       stats.AddRow(249, oper->nick + " (" + oper->ident + "@" + oper->dhost + ") Idle: " +
                                                        (lu ? ConvToStr(ServerInstance->Time() - lu->idle_lastmsg) + " secs" : "unavailable"));
                                        idx++;
                                }
                        }
-                       results.push_back("249 "+user->nick+" :"+ConvToStr(idx)+" OPER(s)");
+                       stats.AddRow(249, ConvToStr(idx)+" OPER(s)");
                }
                break;
 
                case 'k':
-                       ServerInstance->XLines->InvokeStats("K",216,user,results);
+                       ServerInstance->XLines->InvokeStats("K",216,stats);
                break;
                case 'g':
-                       ServerInstance->XLines->InvokeStats("G",223,user,results);
+                       ServerInstance->XLines->InvokeStats("G",223,stats);
                break;
                case 'q':
-                       ServerInstance->XLines->InvokeStats("Q",217,user,results);
+                       ServerInstance->XLines->InvokeStats("Q",217,stats);
                break;
                case 'Z':
-                       ServerInstance->XLines->InvokeStats("Z",223,user,results);
+                       ServerInstance->XLines->InvokeStats("Z",223,stats);
                break;
                case 'e':
-                       ServerInstance->XLines->InvokeStats("E",223,user,results);
+                       ServerInstance->XLines->InvokeStats("E",223,stats);
                break;
                case 'E':
                {
-                       const SocketEngine::Statistics& stats = SocketEngine::GetStats();
-                       results.push_back("249 "+user->nick+" :Total events: "+ConvToStr(stats.TotalEvents));
-                       results.push_back("249 "+user->nick+" :Read events:  "+ConvToStr(stats.ReadEvents));
-                       results.push_back("249 "+user->nick+" :Write events: "+ConvToStr(stats.WriteEvents));
-                       results.push_back("249 "+user->nick+" :Error events: "+ConvToStr(stats.ErrorEvents));
+                       const SocketEngine::Statistics& sestats = SocketEngine::GetStats();
+                       stats.AddRow(249, "Total events: "+ConvToStr(sestats.TotalEvents));
+                       stats.AddRow(249, "Read events:  "+ConvToStr(sestats.ReadEvents));
+                       stats.AddRow(249, "Write events: "+ConvToStr(sestats.WriteEvents));
+                       stats.AddRow(249, "Error events: "+ConvToStr(sestats.ErrorEvents));
                        break;
                }
 
@@ -213,7 +218,7 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                                if (i->second->use_count)
                                {
                                        /* RPL_STATSCOMMANDS */
-                                       results.push_back("212 "+user->nick+" "+i->second->name+" "+ConvToStr(i->second->use_count));
+                                       stats.AddRow(212, i->second->name, i->second->use_count);
                                }
                        }
                }
@@ -222,9 +227,9 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                /* stats z (debug and memory info) */
                case 'z':
                {
-                       results.push_back("249 "+user->nick+" :Users: "+ConvToStr(ServerInstance->Users->GetUsers().size()));
-                       results.push_back("249 "+user->nick+" :Channels: "+ConvToStr(ServerInstance->GetChans().size()));
-                       results.push_back("249 "+user->nick+" :Commands: "+ConvToStr(ServerInstance->Parser.GetCommands().size()));
+                       stats.AddRow(249, "Users: "+ConvToStr(ServerInstance->Users->GetUsers().size()));
+                       stats.AddRow(249, "Channels: "+ConvToStr(ServerInstance->GetChans().size()));
+                       stats.AddRow(249, "Commands: "+ConvToStr(ServerInstance->Parser.GetCommands().size()));
 
                        float kbitpersec_in, kbitpersec_out, kbitpersec_total;
                        char kbitpersec_in_s[30], kbitpersec_out_s[30], kbitpersec_total_s[30];
@@ -235,9 +240,9 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                        snprintf(kbitpersec_out_s, 30, "%03.5f", kbitpersec_out);
                        snprintf(kbitpersec_in_s, 30, "%03.5f", kbitpersec_in);
 
-                       results.push_back("249 "+user->nick+" :Bandwidth total:  "+ConvToStr(kbitpersec_total_s)+" kilobits/sec");
-                       results.push_back("249 "+user->nick+" :Bandwidth out:    "+ConvToStr(kbitpersec_out_s)+" kilobits/sec");
-                       results.push_back("249 "+user->nick+" :Bandwidth in:     "+ConvToStr(kbitpersec_in_s)+" kilobits/sec");
+                       stats.AddRow(249, "Bandwidth total:  "+ConvToStr(kbitpersec_total_s)+" kilobits/sec");
+                       stats.AddRow(249, "Bandwidth out:    "+ConvToStr(kbitpersec_out_s)+" kilobits/sec");
+                       stats.AddRow(249, "Bandwidth in:     "+ConvToStr(kbitpersec_in_s)+" kilobits/sec");
 
 #ifndef _WIN32
                        /* Moved this down here so all the not-windows stuff (look w00tie, I didn't say win32!) is in one ifndef.
@@ -248,11 +253,11 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                        /* Not sure why we were doing '0' with a RUSAGE_SELF comment rather than just using RUSAGE_SELF -- Om */
                        if (!getrusage(RUSAGE_SELF,&R)) /* RUSAGE_SELF */
                        {
-                               results.push_back("249 "+user->nick+" :Total allocation: "+ConvToStr(R.ru_maxrss)+"K");
-                               results.push_back("249 "+user->nick+" :Signals:          "+ConvToStr(R.ru_nsignals));
-                               results.push_back("249 "+user->nick+" :Page faults:      "+ConvToStr(R.ru_majflt));
-                               results.push_back("249 "+user->nick+" :Swaps:            "+ConvToStr(R.ru_nswap));
-                               results.push_back("249 "+user->nick+" :Context Switches: Voluntary; "+ConvToStr(R.ru_nvcsw)+" Involuntary; "+ConvToStr(R.ru_nivcsw));
+                               stats.AddRow(249, "Total allocation: "+ConvToStr(R.ru_maxrss)+"K");
+                               stats.AddRow(249, "Signals:          "+ConvToStr(R.ru_nsignals));
+                               stats.AddRow(249, "Page faults:      "+ConvToStr(R.ru_majflt));
+                               stats.AddRow(249, "Swaps:            "+ConvToStr(R.ru_nswap));
+                               stats.AddRow(249, "Context Switches: Voluntary; "+ConvToStr(R.ru_nvcsw)+" Involuntary; "+ConvToStr(R.ru_nivcsw));
 
                                char percent[30];
 
@@ -262,21 +267,21 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                                float per = (n_eaten / n_elapsed) * 100;
 
                                snprintf(percent, 30, "%03.5f%%", per);
-                               results.push_back("249 "+user->nick+" :CPU Use (now):    "+percent);
+                               stats.AddRow(249, std::string("CPU Use (now):    ")+percent);
 
                                n_elapsed = ServerInstance->Time() - ServerInstance->startup_time;
                                n_eaten = (float)R.ru_utime.tv_sec + R.ru_utime.tv_usec / 100000.0;
                                per = (n_eaten / n_elapsed) * 100;
                                snprintf(percent, 30, "%03.5f%%", per);
-                               results.push_back("249 "+user->nick+" :CPU Use (total):  "+percent);
+                               stats.AddRow(249, std::string("CPU Use (total):  ")+percent);
                        }
 #else
                        PROCESS_MEMORY_COUNTERS MemCounters;
                        if (GetProcessMemoryInfo(GetCurrentProcess(), &MemCounters, sizeof(MemCounters)))
                        {
-                               results.push_back("249 "+user->nick+" :Total allocation: "+ConvToStr((MemCounters.WorkingSetSize + MemCounters.PagefileUsage) / 1024)+"K");
-                               results.push_back("249 "+user->nick+" :Pagefile usage:   "+ConvToStr(MemCounters.PagefileUsage / 1024)+"K");
-                               results.push_back("249 "+user->nick+" :Page faults:      "+ConvToStr(MemCounters.PageFaultCount));
+                               stats.AddRow(249, "Total allocation: "+ConvToStr((MemCounters.WorkingSetSize + MemCounters.PagefileUsage) / 1024)+"K");
+                               stats.AddRow(249, "Pagefile usage:   "+ConvToStr(MemCounters.PagefileUsage / 1024)+"K");
+                               stats.AddRow(249, "Page faults:      "+ConvToStr(MemCounters.PageFaultCount));
                        }
 
                        FILETIME CreationTime;
@@ -296,13 +301,13 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                                char percent[30];
 
                                snprintf(percent, 30, "%03.5f%%", per);
-                               results.push_back("249 "+user->nick+" :CPU Use (now):    "+percent);
+                               stats.AddRow(249, std::string("CPU Use (now):    ")+percent);
 
                                n_elapsed = ServerInstance->Time() - ServerInstance->startup_time;
                                n_eaten = (double)(( (uint64_t)(KernelTime.dwHighDateTime) << 32 ) + (uint64_t)(KernelTime.dwLowDateTime))/100000;
                                per = (n_eaten / n_elapsed);
                                snprintf(percent, 30, "%03.5f%%", per);
-                               results.push_back("249 "+user->nick+" :CPU Use (total):  "+percent);
+                               stats.AddRow(249, std::string("CPU Use (total):  ")+percent));
                        }
 #endif
                }
@@ -310,12 +315,12 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
 
                case 'T':
                {
-                       results.push_back("249 "+user->nick+" :accepts "+ConvToStr(ServerInstance->stats.Accept)+" refused "+ConvToStr(ServerInstance->stats.Refused));
-                       results.push_back("249 "+user->nick+" :unknown commands "+ConvToStr(ServerInstance->stats.Unknown));
-                       results.push_back("249 "+user->nick+" :nick collisions "+ConvToStr(ServerInstance->stats.Collisions));
-                       results.push_back("249 "+user->nick+" :dns requests "+ConvToStr(ServerInstance->stats.DnsGood+ServerInstance->stats.DnsBad)+" succeeded "+ConvToStr(ServerInstance->stats.DnsGood)+" failed "+ConvToStr(ServerInstance->stats.DnsBad));
-                       results.push_back("249 "+user->nick+" :connection count "+ConvToStr(ServerInstance->stats.Connects));
-                       results.push_back(InspIRCd::Format("249 %s :bytes sent %5.2fK recv %5.2fK", user->nick.c_str(),
+                       stats.AddRow(249, "accepts "+ConvToStr(ServerInstance->stats.Accept)+" refused "+ConvToStr(ServerInstance->stats.Refused));
+                       stats.AddRow(249, "unknown commands "+ConvToStr(ServerInstance->stats.Unknown));
+                       stats.AddRow(249, "nick collisions "+ConvToStr(ServerInstance->stats.Collisions));
+                       stats.AddRow(249, "dns requests "+ConvToStr(ServerInstance->stats.DnsGood+ServerInstance->stats.DnsBad)+" succeeded "+ConvToStr(ServerInstance->stats.DnsGood)+" failed "+ConvToStr(ServerInstance->stats.DnsBad));
+                       stats.AddRow(249, "connection count "+ConvToStr(ServerInstance->stats.Connects));
+                       stats.AddRow(249, InspIRCd::Format("bytes sent %5.2fK recv %5.2fK",
                                ServerInstance->stats.Sent / 1024.0, ServerInstance->stats.Recv / 1024.0));
                }
                break;
@@ -327,8 +332,7 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                        for(ConfigIter i = tags.first; i != tags.second; ++i)
                        {
                                ConfigTag* tag = i->second;
-                               results.push_back("243 "+user->nick+" O "+tag->getString("host")+" * "+
-                                       tag->getString("name") + " " + tag->getString("type")+" 0");
+                               stats.AddRow(243, 'O', tag->getString("host"), '*', tag->getString("name"), tag->getString("type"), '0');
                        }
                }
                break;
@@ -349,7 +353,7 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                                        if (mh && mh->NeedsOper() && tag->AllowedChanModes[c - 'A'])
                                                cmodes.push_back(c);
                                }
-                               results.push_back("243 "+user->nick+" O "+tag->name.c_str() + " " + umodes + " " + cmodes);
+                               stats.AddRow(243, 'O', tag->name, umodes, cmodes);
                        }
                }
                break;
@@ -358,14 +362,14 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                case 'l':
                /* stats L (show user I/O stats with IP addresses) */
                case 'L':
-                       GenerateStatsLl(user, results, statschar);
+                       GenerateStatsLl(stats);
                break;
 
                /* stats u (show server uptime) */
                case 'u':
                {
                        unsigned int up = static_cast<unsigned int>(ServerInstance->Time() - ServerInstance->startup_time);
-                       results.push_back(InspIRCd::Format("242 %s :Server up %u days, %.2u:%.2u:%.2u", user->nick.c_str(),
+                       stats.AddRow(242, InspIRCd::Format("Server up %u days, %.2u:%.2u:%.2u",
                                up / 86400, (up / 3600) % 24, (up / 60) % 60, up % 60));
                }
                break;
@@ -374,7 +378,7 @@ void CommandStats::DoStats(char statschar, User* user, string_list &results)
                break;
        }
 
-       results.push_back("219 "+user->nick+" "+statschar+" :End of /STATS report");
+       stats.AddRow(219, statschar, "End of /STATS report");
        ServerInstance->SNO->WriteToSnoMask('t',"%s '%c' requested by %s (%s@%s)",
                (IS_LOCAL(user) ? "Stats" : "Remote stats"), statschar, user->nick.c_str(), user->ident.c_str(), user->host.c_str());
        return;
@@ -390,13 +394,14 @@ CmdResult CommandStats::Handle (const std::vector<std::string>& parameters, User
                        localuser->CommandFloodPenalty += 2000;
                return CMD_SUCCESS;
        }
-       string_list values;
-       char search = parameters[0][0];
-       DoStats(search, user, values);
-
-       const std::string p = ":" + ServerInstance->Config->ServerName + " ";
-       for (size_t i = 0; i < values.size(); i++)
-               user->SendText(p + values[i]);
+       Stats::Context stats(user, parameters[0][0]);
+       DoStats(stats);
+       const std::vector<Stats::Row>& rows = stats.GetRows();
+       for (std::vector<Stats::Row>::const_iterator i = rows.begin(); i != rows.end(); ++i)
+       {
+               const Stats::Row& row = *i;
+               user->WriteRemoteNumeric(row);
+       }
 
        return CMD_SUCCESS;
 }
index e04a69200ac010a83ce679b0c9a877d88b1decca..f52fb0174e849bc20790095ae190e5069c007fb4 100644 (file)
@@ -270,10 +270,10 @@ class ModuleWhoWas : public Module
                cmd.manager.Add(user);
        }
 
-       ModResult OnStats(char symbol, User* user, string_list &results)
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
        {
-               if (symbol == 'z')
-                       results.push_back("249 "+user->nick+" :Whowas entries: "+ConvToStr(cmd.manager.GetStats().entrycount));
+               if (stats.GetSymbol() == 'z')
+                       stats.AddRow(249, "Whowas entries: "+ConvToStr(cmd.manager.GetStats().entrycount));
 
                return MOD_RES_PASSTHRU;
        }
index 28ded66d84dca6acc8e737404b0a13c2f9ff3971..b107a4b439d801174495267854284ac7e002eda6 100644 (file)
@@ -107,7 +107,7 @@ ModResult   Module::OnCheckLimit(User*, Channel*) { DetachEvent(I_OnCheckLimit); r
 ModResult      Module::OnCheckChannelBan(User*, Channel*) { DetachEvent(I_OnCheckChannelBan); return MOD_RES_PASSTHRU; }
 ModResult      Module::OnCheckBan(User*, Channel*, const std::string&) { DetachEvent(I_OnCheckBan); return MOD_RES_PASSTHRU; }
 ModResult      Module::OnExtBanCheck(User*, Channel*, char) { DetachEvent(I_OnExtBanCheck); return MOD_RES_PASSTHRU; }
-ModResult      Module::OnStats(char, User*, string_list&) { DetachEvent(I_OnStats); return MOD_RES_PASSTHRU; }
+ModResult      Module::OnStats(Stats::Context&) { DetachEvent(I_OnStats); return MOD_RES_PASSTHRU; }
 ModResult      Module::OnChangeLocalUserHost(LocalUser*, const std::string&) { DetachEvent(I_OnChangeLocalUserHost); return MOD_RES_PASSTHRU; }
 ModResult      Module::OnChangeLocalUserGECOS(LocalUser*, const std::string&) { DetachEvent(I_OnChangeLocalUserGECOS); return MOD_RES_PASSTHRU; }
 ModResult      Module::OnPreTopicChange(User*, Channel*, const std::string&) { DetachEvent(I_OnPreTopicChange); return MOD_RES_PASSTHRU; }
index d21a82149b423cbbe84fca796fff24f5dbddff5f..967c6a761f2c80a94058ca71381ad616a16768ca 100644 (file)
@@ -97,9 +97,9 @@ class ModuleGeoIP : public Module
                return MOD_RES_DENY;
        }
 
-       ModResult OnStats(char symbol, User* user, string_list &out) CXX11_OVERRIDE
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
        {
-               if (symbol != 'G')
+               if (stats.GetSymbol() != 'G')
                        return MOD_RES_PASSTHRU;
 
                unsigned int unknown = 0;
@@ -115,14 +115,13 @@ class ModuleGeoIP : public Module
                                unknown++;
                }
 
-               std::string p = "801 " + user->nick + " :GeoIPSTATS ";
                for (std::map<std::string, unsigned int>::const_iterator i = results.begin(); i != results.end(); ++i)
                {
-                       out.push_back(p + i->first + " " + ConvToStr(i->second));
+                       stats.AddRow(801, "GeoIPSTATS " + i->first + " " + ConvToStr(i->second));
                }
 
                if (unknown)
-                       out.push_back(p + "Unknown " + ConvToStr(unknown));
+                       stats.AddRow(801, "GeoIPSTATS Unknown " + ConvToStr(unknown));
 
                return MOD_RES_DENY;
        }
index 1ddc625db5fd69c96a3ad4dd92d8c2d1d58934d9..2a969bec7cb594666bd6d5d5b8680773fc241f24 100644 (file)
@@ -165,12 +165,12 @@ class ModuleCBan : public Module
                ServerInstance->XLines->UnregisterFactory(&f);
        }
 
-       ModResult OnStats(char symbol, User* user, string_list &out) CXX11_OVERRIDE
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
        {
-               if (symbol != 'C')
+               if (stats.GetSymbol() != 'C')
                        return MOD_RES_PASSTHRU;
 
-               ServerInstance->XLines->InvokeStats("CBAN", 210, user, out);
+               ServerInstance->XLines->InvokeStats("CBAN", 210, stats);
                return MOD_RES_DENY;
        }
 
index 726ee13510d08c6eeb08de0f69954667f7f74736..44328480e3fe4bd54c4b74e28028f7bf7d64b94b 100644 (file)
@@ -406,9 +406,9 @@ class ModuleDNSBL : public Module
                return MOD_RES_PASSTHRU;
        }
 
-       ModResult OnStats(char symbol, User* user, string_list &results) CXX11_OVERRIDE
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
        {
-               if (symbol != 'd')
+               if (stats.GetSymbol() != 'd')
                        return MOD_RES_PASSTHRU;
 
                unsigned long total_hits = 0, total_misses = 0;
@@ -418,12 +418,12 @@ class ModuleDNSBL : public Module
                        total_hits += (*i)->stats_hits;
                        total_misses += (*i)->stats_misses;
 
-                       results.push_back("304 " + user->nick + " :DNSBLSTATS DNSbl \"" + (*i)->name + "\" had " +
+                       stats.AddRow(304, "DNSBLSTATS DNSbl \"" + (*i)->name + "\" had " +
                                        ConvToStr((*i)->stats_hits) + " hits and " + ConvToStr((*i)->stats_misses) + " misses");
                }
 
-               results.push_back("304 " + user->nick + " :DNSBLSTATS Total hits: " + ConvToStr(total_hits));
-               results.push_back("304 " + user->nick + " :DNSBLSTATS Total misses: " + ConvToStr(total_misses));
+               stats.AddRow(304, "DNSBLSTATS Total hits: " + ConvToStr(total_hits));
+               stats.AddRow(304, "DNSBLSTATS Total misses: " + ConvToStr(total_misses));
 
                return MOD_RES_PASSTHRU;
        }
index bd1022a0824a291340dd53cb36820c62095d589c..a3e30ecb463f4137f3cdbb09051a3c4bf5791ede 100644 (file)
@@ -187,7 +187,7 @@ class ModuleFilter : public Module
        FilterResult DecodeFilter(const std::string &data);
        void OnSyncNetwork(ProtocolInterface::Server& server) CXX11_OVERRIDE;
        void OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata) CXX11_OVERRIDE;
-       ModResult OnStats(char symbol, User* user, string_list &results) CXX11_OVERRIDE;
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE;
        ModResult OnPreCommand(std::string &command, std::vector<std::string> &parameters, LocalUser *user, bool validated, const std::string &original_line) CXX11_OVERRIDE;
        void OnUnloadModule(Module* mod) CXX11_OVERRIDE;
        bool AppliesToMe(User* user, FilterResult* filter, int flags);
@@ -693,21 +693,21 @@ void ModuleFilter::ReadFilters()
        }
 }
 
-ModResult ModuleFilter::OnStats(char symbol, User* user, string_list &results)
+ModResult ModuleFilter::OnStats(Stats::Context& stats)
 {
-       if (symbol == 's')
+       if (stats.GetSymbol() == 's')
        {
                for (std::vector<FilterResult>::iterator i = filters.begin(); i != filters.end(); i++)
                {
-                       results.push_back("223 "+user->nick+" :"+RegexEngine.GetProvider()+":"+i->freeform+" "+i->GetFlags()+" "+FilterActionToString(i->action)+" "+ConvToStr(i->gline_time)+" :"+i->reason);
+                       stats.AddRow(223, RegexEngine.GetProvider()+":"+i->freeform+" "+i->GetFlags()+" "+FilterActionToString(i->action)+" "+ConvToStr(i->gline_time)+" :"+i->reason);
                }
                for (ExemptTargetSet::const_iterator i = exemptedchans.begin(); i != exemptedchans.end(); ++i)
                {
-                       results.push_back("223 "+user->nick+" :EXEMPT "+(*i));
+                       stats.AddRow(223, "EXEMPT "+(*i));
                }
                for (ExemptTargetSet::const_iterator i = exemptednicks.begin(); i != exemptednicks.end(); ++i)
                {
-                       results.push_back("223 "+user->nick+" :EXEMPT "+(*i));
+                       stats.AddRow(223, "EXEMPT "+(*i));
                }
        }
        return MOD_RES_PASSTHRU;
index 92af045d5b1c653f6db6f434aa71d1ffba39ed65..0fa5206eaea2eb5b44c142534f900245d3863bde 100644 (file)
@@ -122,9 +122,9 @@ class ModuleHideOper : public Module, public Whois::LineEventListener
                }
        }
 
-       ModResult OnStats(char symbol, User* user, string_list& results) CXX11_OVERRIDE
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
        {
-               if (symbol != 'P')
+               if (stats.GetSymbol() != 'P')
                        return MOD_RES_PASSTHRU;
 
                unsigned int count = 0;
@@ -132,15 +132,15 @@ class ModuleHideOper : public Module, public Whois::LineEventListener
                for (UserManager::OperList::const_iterator i = opers.begin(); i != opers.end(); ++i)
                {
                        User* oper = *i;
-                       if (!oper->server->IsULine() && (user->IsOper() || !oper->IsModeSet(hm)))
+                       if (!oper->server->IsULine() && (stats.GetSource()->IsOper() || !oper->IsModeSet(hm)))
                        {
                                LocalUser* lu = IS_LOCAL(oper);
-                               results.push_back("249 " + user->nick + " :" + oper->nick + " (" + oper->ident + "@" + oper->dhost + ") Idle: " +
+                               stats.AddRow(249, oper->nick + " (" + oper->ident + "@" + oper->dhost + ") Idle: " +
                                                (lu ? ConvToStr(ServerInstance->Time() - lu->idle_lastmsg) + " secs" : "unavailable"));
                                count++;
                        }
                }
-               results.push_back("249 "+user->nick+" :"+ConvToStr(count)+" OPER(s)");
+               stats.AddRow(249, ConvToStr(count)+" OPER(s)");
 
                return MOD_RES_DENY;
        }
index 2aee89ad282b300053dbbf4aca3adb93a49c94bc..97fbf169a2b13247fb3511fefc38a50b8b846f76 100644 (file)
@@ -284,12 +284,12 @@ class ModuleRLine : public Module
                initing = false;
        }
 
-       ModResult OnStats(char symbol, User* user, string_list &results) CXX11_OVERRIDE
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
        {
-               if (symbol != 'R')
+               if (stats.GetSymbol() != 'R')
                        return MOD_RES_PASSTHRU;
 
-               ServerInstance->XLines->InvokeStats("R", 223, user, results);
+               ServerInstance->XLines->InvokeStats("R", 223, stats);
                return MOD_RES_DENY;
        }
 
index a3a2909a08bb9427704d3b2eb3498da6070eb943..5388bb4856da5a2b078d3a9a8cce9c72a742956e 100644 (file)
@@ -194,12 +194,12 @@ class ModuleShun : public Module
                ServerInstance->Modules->SetPriority(this, I_OnPreCommand, PRIORITY_BEFORE, alias);
        }
 
-       ModResult OnStats(char symbol, User* user, string_list& out) CXX11_OVERRIDE
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
        {
-               if (symbol != 'H')
+               if (stats.GetSymbol() != 'H')
                        return MOD_RES_PASSTHRU;
 
-               ServerInstance->XLines->InvokeStats("SHUN", 223, user, out);
+               ServerInstance->XLines->InvokeStats("SHUN", 223, stats);
                return MOD_RES_DENY;
        }
 
index 3e02ce93f8ba119ae18a47a61e26049160e8df5b..2490c83ef65133252cc606af4f76b42063484ce5 100644 (file)
@@ -165,7 +165,7 @@ class ModuleSpanningTree : public Module
        void OnOper(User* user, const std::string &opertype) CXX11_OVERRIDE;
        void OnAddLine(User *u, XLine *x) CXX11_OVERRIDE;
        void OnDelLine(User *u, XLine *x) CXX11_OVERRIDE;
-       ModResult OnStats(char statschar, User* user, string_list &results) CXX11_OVERRIDE;
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE;
        ModResult OnSetAway(User* user, const std::string &awaymsg) CXX11_OVERRIDE;
        void OnLoadModule(Module* mod) CXX11_OVERRIDE;
        void OnUnloadModule(Module* mod) CXX11_OVERRIDE;
index 14b3f5ef74b10a6936eb26d9859d4eb6c78421db..b28c2d98436db9eae5b1a8c5c27e740be7739018 100644 (file)
 #include "utils.h"
 #include "link.h"
 
-ModResult ModuleSpanningTree::OnStats(char statschar, User* user, string_list &results)
+ModResult ModuleSpanningTree::OnStats(Stats::Context& stats)
 {
-       if ((statschar == 'c') || (statschar == 'n'))
+       if ((stats.GetSymbol() == 'c') || (stats.GetSymbol() == 'n'))
        {
                for (std::vector<reference<Link> >::iterator i = Utils->LinkBlocks.begin(); i != Utils->LinkBlocks.end(); ++i)
                {
                        Link* L = *i;
-                       results.push_back("213 "+user->nick+" "+statschar+" *@"+(L->HiddenFromStats ? "<hidden>" : L->IPAddr)+" * "+(*i)->Name.c_str()+" "+ConvToStr(L->Port)+" "+(L->Hook.empty() ? "plaintext" : L->Hook));
-                       if (statschar == 'c')
-                               results.push_back("244 "+user->nick+" H * * "+L->Name.c_str());
+                       std::string ipaddr = "*@";
+                       if (L->HiddenFromStats)
+                               ipaddr.append("<hidden>");
+                       else
+                               ipaddr.append(L->IPAddr);
+
+                       const std::string hook = (L->Hook.empty() ? "plaintext" : L->Hook);
+                       stats.AddRow(213, stats.GetSymbol(), ipaddr, '*', L->Name.c_str(), L->Port, hook);
+                       if (stats.GetSymbol() == 'c')
+                               stats.AddRow(244, 'H', '*', '*', L->Name.c_str());
                }
                return MOD_RES_DENY;
        }
-       else if (statschar == 'U')
+       else if (stats.GetSymbol() == 'U')
        {
                ConfigTagList tags = ServerInstance->Config->ConfTags("uline");
                for (ConfigIter i = tags.first; i != tags.second; ++i)
                {
                        std::string name = i->second->getString("server");
                        if (!name.empty())
-                               results.push_back("248 "+user->nick+" U "+name);
+                               stats.AddRow(248, 'U', name);
                }
                return MOD_RES_DENY;
        }
index b95a847a5cbbd9c99997ea1869decb01dab3f526..ad6a4d1aaa15255020389a116cf86f047053be51 100644 (file)
@@ -183,12 +183,12 @@ class ModuleSVSHold : public Module
                silent = tag->getBool("silent", true);
        }
 
-       ModResult OnStats(char symbol, User* user, string_list &out) CXX11_OVERRIDE
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
        {
-               if(symbol != 'S')
+               if (stats.GetSymbol() != 'S')
                        return MOD_RES_PASSTHRU;
 
-               ServerInstance->XLines->InvokeStats("SVSHOLD", 210, user, out);
+               ServerInstance->XLines->InvokeStats("SVSHOLD", 210, stats);
                return MOD_RES_DENY;
        }
 
index 003d77e80ef4facc76d73b42c6b25c3d5e15c417..30a1d7c9cc97428904084c1115779c6f0fc2dce0 100644 (file)
@@ -447,7 +447,7 @@ void XLineManager::ApplyLines()
        pending_lines.clear();
 }
 
-void XLineManager::InvokeStats(const std::string &type, int numeric, User* user, string_list &results)
+void XLineManager::InvokeStats(const std::string& type, unsigned int numeric, Stats::Context& stats)
 {
        ContainerIter n = lookup_lines.find(type);
 
@@ -468,7 +468,7 @@ void XLineManager::InvokeStats(const std::string &type, int numeric, User* user,
                                ExpireLine(n, i);
                        }
                        else
-                               results.push_back(ConvToStr(numeric)+" "+user->nick+" :"+i->second->Displayable()+" "+
+                               stats.AddRow(numeric, i->second->Displayable()+" "+
                                        ConvToStr(i->second->set_time)+" "+ConvToStr(i->second->duration)+" "+i->second->source+" :"+i->second->reason);
                        i = safei;
                }