mirror of
https://github.com/matrix-construct/construct
synced 2024-12-25 23:14:13 +01:00
Refactor whowas.
This commit is contained in:
parent
5f218cdbb2
commit
9c16de2d41
12 changed files with 275 additions and 258 deletions
|
@ -94,8 +94,8 @@ struct client
|
|||
struct client *servptr; /* Points to server this Client is on */
|
||||
struct client *from; /* == self, if Local Client, *NEVER* NULL! */
|
||||
|
||||
rb_dlink_list whowas_clist;
|
||||
|
||||
// unique whowas id associating any history to *this (TODO: replace with connid)
|
||||
whowas::id_t wwid;
|
||||
time_t tsinfo; /* TS on the nick, SVINFO on server */
|
||||
mode::mode mode;
|
||||
uint64_t flags; /* client flags */
|
||||
|
@ -927,7 +927,7 @@ extern void del_all_accepts(client *client_p);
|
|||
extern void dead_link(client *client_p, int sendqex);
|
||||
extern int show_ip(client *source_p, client *target_p);
|
||||
extern int show_ip_conf(struct ConfItem *aconf, client *source_p);
|
||||
extern int show_ip_whowas(struct Whowas *whowas, client *source_p);
|
||||
extern int show_ip_whowas(const whowas::whowas &, client &source);
|
||||
|
||||
extern void close_connection(client *);
|
||||
extern void init_uid(void);
|
||||
|
|
|
@ -52,7 +52,6 @@ namespace ircd
|
|||
}
|
||||
|
||||
struct ConfItem;
|
||||
struct Whowas;
|
||||
struct DNSReply;
|
||||
struct Listener;
|
||||
struct Blacklist;
|
||||
|
@ -75,6 +74,7 @@ namespace ircd
|
|||
#include "match.h"
|
||||
|
||||
#include "cache.h"
|
||||
#include "whowas.h"
|
||||
#include "tgchange.h"
|
||||
#include "msgbuf.h"
|
||||
#include "msg.h"
|
||||
|
@ -119,6 +119,5 @@ namespace ircd
|
|||
#include "substitution.h"
|
||||
#include "supported.h"
|
||||
#include "s_user.h"
|
||||
#include "whowas.h"
|
||||
#include "wsproc.h"
|
||||
#include "stringops.h"
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
|
||||
* Copyright (C) 1996-2002 Hybrid Development Team
|
||||
* Copyright (C) 2002-2004 ircd-ratbox development team
|
||||
* Copyright (C) 2016 Charybdis Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -26,73 +27,60 @@
|
|||
#define HAVE_IRCD_WHOWAS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace ircd {
|
||||
namespace ircd {
|
||||
namespace whowas {
|
||||
|
||||
struct User;
|
||||
using client::client;
|
||||
using id_t = uint64_t;
|
||||
|
||||
/*
|
||||
lets speed this up...
|
||||
also removed away information. *tough*
|
||||
- Dianora
|
||||
/* lets speed this up... also removed away information. *tough*
|
||||
* - Dianora
|
||||
*/
|
||||
struct Whowas
|
||||
struct whowas
|
||||
{
|
||||
struct whowas_top *wtop;
|
||||
rb_dlink_node wnode; /* for the wtop linked list */
|
||||
rb_dlink_node cnode; /* node for online clients */
|
||||
rb_dlink_node whowas_node; /* node for the whowas linked list */
|
||||
enum flag
|
||||
{
|
||||
IP_SPOOFING = 0x01,
|
||||
DYNSPOOF = 0x02,
|
||||
};
|
||||
|
||||
id_t wwid; // Unique whowas index ID
|
||||
client *online; // Pointer to online client or nullptr
|
||||
time_t logoff;
|
||||
std::shared_ptr<cache::serv::entry> scache;
|
||||
char name[NICKLEN + 1];
|
||||
char username[USERLEN + 1];
|
||||
char hostname[HOSTLEN + 1];
|
||||
char sockhost[HOSTIPLEN + 1];
|
||||
char realname[REALLEN + 1];
|
||||
char suser[NICKLEN + 1];
|
||||
unsigned char flags;
|
||||
std::shared_ptr<cache::serv::entry> scache;
|
||||
time_t logoff;
|
||||
client::client *online; /* Pointer to new nickname for chasing or NULL */
|
||||
enum flag flag;
|
||||
|
||||
whowas(client &client);
|
||||
};
|
||||
|
||||
/* Flags */
|
||||
#define WHOWAS_IP_SPOOFING 0x1
|
||||
#define WHOWAS_DYNSPOOF 0x2
|
||||
// Get a full history for nickname (may contain different users!)
|
||||
std::vector<std::shared_ptr<whowas>> history(const std::string &name, const time_t &limit = 0, const bool &online = false);
|
||||
|
||||
/*
|
||||
** initwhowas
|
||||
*/
|
||||
extern void whowas_init(void);
|
||||
// Get a full history for this unique whowas ID. This is effectively similar to
|
||||
// a lookup by a client pointer address; allocators may reuse the same address,
|
||||
// so this ID is used as the index instead.
|
||||
std::vector<std::shared_ptr<whowas>> history(const id_t &wwid);
|
||||
|
||||
/*
|
||||
** add_history
|
||||
** Add the currently defined name of the client to history.
|
||||
** usually called before changing to a new name (nick).
|
||||
** Client must be a fully registered user (specifically,
|
||||
** the user structure must have been allocated).
|
||||
*/
|
||||
void whowas_add_history(client::client *, int);
|
||||
// Get a full history for this client (must be online);
|
||||
std::vector<std::shared_ptr<whowas>> history(const client &);
|
||||
|
||||
/*
|
||||
** off_history
|
||||
** This must be called when the client structure is about to
|
||||
** be released. History mechanism keeps pointers to client
|
||||
** structures and it must know when they cease to exist. This
|
||||
** also implicitly calls AddHistory.
|
||||
*/
|
||||
void whowas_off_history(client::client *);
|
||||
// Add whowas information about client *before* a nick change or logoff.
|
||||
void add(client &);
|
||||
|
||||
/*
|
||||
** get_history
|
||||
** Return the current client that was using the given
|
||||
** nickname within the timelimit. Returns NULL, if no
|
||||
** one found...
|
||||
*/
|
||||
client::client *whowas_get_history(const char *, time_t);
|
||||
/* Nick name */
|
||||
/* Time limit in seconds */
|
||||
// Notify this subsystem the client pointer is about to be invalidated (does not call add())
|
||||
void off(client &);
|
||||
|
||||
rb_dlink_list *whowas_get_list(const char *name);
|
||||
void whowas_set_size(int whowas_length);
|
||||
void whowas_memory_usage(size_t *count, size_t *memused);
|
||||
// Util
|
||||
void memory_usage(size_t *const &count, size_t *const &memused);
|
||||
void set_size(const size_t &max);
|
||||
void init();
|
||||
|
||||
} // namespace whowas
|
||||
} // namespace ircd
|
||||
#endif // __cplusplus
|
||||
|
|
|
@ -90,6 +90,24 @@ using namespace ircd;
|
|||
|
||||
|
||||
client::client::client()
|
||||
:servptr{0}
|
||||
,from{nullptr}
|
||||
,wwid{0}
|
||||
,tsinfo{0}
|
||||
,mode{(umode)0}
|
||||
,flags{(enum flags)0}
|
||||
,snomask{0}
|
||||
,hopcount{0}
|
||||
,status{(enum status)0}
|
||||
,handler{0}
|
||||
,serial{0}
|
||||
,first_received_message_time{0}
|
||||
,received_number_of_privmsgs{0}
|
||||
,flood_noticed{0}
|
||||
,localClient{nullptr}
|
||||
,preClient{nullptr}
|
||||
,large_ctcp_sent{0}
|
||||
,certfp{nullptr}
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -773,7 +791,7 @@ client::resv_nick_fnc(const char *mask, const char *reason, int temp_time)
|
|||
|
||||
/* Do all of the nick-changing gymnastics. */
|
||||
client_p->tsinfo = rb_current_time();
|
||||
whowas_add_history(client_p, 1);
|
||||
whowas::add(*client_p);
|
||||
|
||||
monitor_signoff(client_p);
|
||||
|
||||
|
@ -954,15 +972,17 @@ client::find_chasing(client *source_p, const char *user, int *chasing)
|
|||
if(who || rfc1459::is_digit(*user))
|
||||
return who;
|
||||
|
||||
if(!(who = whowas_get_history(user, (long) KILLCHASETIMELIMIT)))
|
||||
const auto history(whowas::history(user, KILLCHASETIMELIMIT));
|
||||
if(history.empty())
|
||||
{
|
||||
sendto_one_numeric(source_p, ERR_NOSUCHNICK,
|
||||
form_str(ERR_NOSUCHNICK), user);
|
||||
return (NULL);
|
||||
sendto_one_numeric(source_p, ERR_NOSUCHNICK, form_str(ERR_NOSUCHNICK), user);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(chasing)
|
||||
*chasing = 1;
|
||||
return who;
|
||||
|
||||
return history.back()->online;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1323,8 +1343,8 @@ client::exit_generic_client(client *client_p, client *source_p, client *from,
|
|||
/* Clean up allow lists */
|
||||
del_all_accepts(source_p);
|
||||
|
||||
whowas_add_history(source_p, 0);
|
||||
whowas_off_history(source_p);
|
||||
whowas::add(*source_p);
|
||||
whowas::off(*source_p);
|
||||
|
||||
monitor_signoff(source_p);
|
||||
|
||||
|
@ -1806,14 +1826,16 @@ client::show_ip_conf(struct ConfItem *aconf, client *source_p)
|
|||
}
|
||||
|
||||
int
|
||||
client::show_ip_whowas(struct Whowas *whowas, client *source_p)
|
||||
client::show_ip_whowas(const whowas::whowas &whowas, client &source)
|
||||
{
|
||||
if(whowas->flags & WHOWAS_IP_SPOOFING)
|
||||
if(ConfigFileEntry.hide_spoof_ips || !my_oper(*source_p))
|
||||
if(whowas.flag & whowas.IP_SPOOFING)
|
||||
if(ConfigFileEntry.hide_spoof_ips || !my_oper(source))
|
||||
return 0;
|
||||
if(whowas->flags & WHOWAS_DYNSPOOF)
|
||||
if(!is(*source_p, umode::OPER))
|
||||
|
||||
if(whowas.flag & whowas.DYNSPOOF)
|
||||
if(!is(source, umode::OPER))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -630,7 +630,7 @@ charybdis_main(int argc, char * const argv[])
|
|||
init_hook();
|
||||
chan::init();
|
||||
initclass();
|
||||
whowas_init();
|
||||
whowas::init();
|
||||
init_reject();
|
||||
cache::init();
|
||||
init_monitor();
|
||||
|
|
|
@ -1569,7 +1569,7 @@ change_nick_user_host(client::client *target_p, const char *nick, const char *us
|
|||
rb_strlcpy(target_p->host, host, sizeof target_p->host);
|
||||
|
||||
if (changed)
|
||||
whowas_add_history(target_p, 1);
|
||||
whowas::add(*target_p);
|
||||
|
||||
del_from_client_hash(target_p->name, target_p);
|
||||
rb_strlcpy(target_p->name, nick, NICKLEN);
|
||||
|
|
304
ircd/whowas.cc
304
ircd/whowas.cc
|
@ -5,7 +5,9 @@
|
|||
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
|
||||
* Copyright (C) 1996-2002 Hybrid Development Team
|
||||
* Copyright (C) 2002-2012 ircd-ratbox development team
|
||||
* Copyright (C) 2016 Charybdis Development Team
|
||||
* Copyright (C) 2016 William Pitcock <nenolod@dereferenced.org>
|
||||
* Copyright (C) 2016 Jason Volk <jason@zemos.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -23,185 +25,175 @@
|
|||
* USA
|
||||
*/
|
||||
|
||||
namespace ircd {
|
||||
namespace ircd {
|
||||
namespace whowas {
|
||||
|
||||
struct whowas_top
|
||||
id_t id_ctr = 1;
|
||||
size_t list_max;
|
||||
std::multimap<id_t, std::shared_ptr<struct whowas>> ids;
|
||||
std::multimap<std::string, std::shared_ptr<struct whowas>, rfc1459::less> nicks;
|
||||
|
||||
void trim();
|
||||
|
||||
} // namespace whowas
|
||||
} // namespace ircd
|
||||
|
||||
using namespace ircd;
|
||||
|
||||
void
|
||||
whowas::init()
|
||||
{
|
||||
char *name;
|
||||
rb_dlink_list wwlist;
|
||||
};
|
||||
|
||||
static rb_radixtree *whowas_tree = NULL;
|
||||
static rb_dlink_list whowas_list = {NULL, NULL, 0};
|
||||
static unsigned int whowas_list_length = NICKNAMEHISTORYLENGTH;
|
||||
static void whowas_trim(void *unused);
|
||||
|
||||
static void
|
||||
whowas_free_wtop(struct whowas_top *wtop)
|
||||
{
|
||||
if(rb_dlink_list_length(&wtop->wwlist) == 0)
|
||||
{
|
||||
rb_radixtree_delete(whowas_tree, wtop->name);
|
||||
rb_free(wtop->name);
|
||||
rb_free(wtop);
|
||||
}
|
||||
}
|
||||
|
||||
static struct whowas_top *
|
||||
whowas_get_top(const char *name)
|
||||
{
|
||||
struct whowas_top *wtop;
|
||||
|
||||
wtop = (whowas_top *)rb_radixtree_retrieve(whowas_tree, name);
|
||||
if (wtop != NULL)
|
||||
return wtop;
|
||||
|
||||
wtop = (whowas_top *)rb_malloc(sizeof(struct whowas_top));
|
||||
wtop->name = rb_strdup(name);
|
||||
rb_radixtree_add(whowas_tree, wtop->name, wtop);
|
||||
|
||||
return wtop;
|
||||
}
|
||||
|
||||
rb_dlink_list *
|
||||
whowas_get_list(const char *name)
|
||||
{
|
||||
struct whowas_top *wtop;
|
||||
wtop = (whowas_top *)rb_radixtree_retrieve(whowas_tree, name);
|
||||
if(wtop == NULL)
|
||||
return NULL;
|
||||
return &wtop->wwlist;
|
||||
if(!list_max)
|
||||
list_max = NICKNAMEHISTORYLENGTH;
|
||||
}
|
||||
|
||||
void
|
||||
whowas_add_history(client::client *client_p, int online)
|
||||
whowas::set_size(const size_t &max)
|
||||
{
|
||||
struct whowas_top *wtop;
|
||||
struct Whowas *who;
|
||||
s_assert(NULL != client_p);
|
||||
|
||||
if(client_p == NULL)
|
||||
return;
|
||||
|
||||
/* trim some of the entries if we're getting well over our history length */
|
||||
if(rb_dlink_list_length(&whowas_list) > whowas_list_length + 100)
|
||||
whowas_trim(NULL);
|
||||
|
||||
wtop = whowas_get_top(client_p->name);
|
||||
who = (Whowas *)rb_malloc(sizeof(struct Whowas));
|
||||
who->wtop = wtop;
|
||||
who->logoff = rb_current_time();
|
||||
|
||||
rb_strlcpy(who->name, client_p->name, sizeof(who->name));
|
||||
rb_strlcpy(who->username, client_p->username, sizeof(who->username));
|
||||
rb_strlcpy(who->hostname, client_p->host, sizeof(who->hostname));
|
||||
rb_strlcpy(who->realname, client_p->info, sizeof(who->realname));
|
||||
rb_strlcpy(who->sockhost, client_p->sockhost, sizeof(who->sockhost));
|
||||
|
||||
who->flags = (is_ip_spoof(*client_p) ? WHOWAS_IP_SPOOFING : 0) |
|
||||
(is_dyn_spoof(*client_p) ? WHOWAS_DYNSPOOF : 0);
|
||||
|
||||
who->scache = nameinfo(serv(*client_p));
|
||||
|
||||
if(online)
|
||||
{
|
||||
who->online = client_p;
|
||||
rb_dlinkAdd(who, &who->cnode, &client_p->whowas_clist);
|
||||
}
|
||||
else
|
||||
who->online = NULL;
|
||||
|
||||
rb_dlinkAdd(who, &who->wnode, &wtop->wwlist);
|
||||
rb_dlinkAdd(who, &who->whowas_node, &whowas_list);
|
||||
list_max = max;
|
||||
trim();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
whowas_off_history(client::client *client_p)
|
||||
whowas::memory_usage(size_t *const &count,
|
||||
size_t *const &memused)
|
||||
{
|
||||
rb_dlink_node *ptr, *next;
|
||||
|
||||
RB_DLINK_FOREACH_SAFE(ptr, next, client_p->whowas_clist.head)
|
||||
{
|
||||
struct Whowas *who = (Whowas *)ptr->data;
|
||||
who->online = NULL;
|
||||
rb_dlinkDelete(&who->cnode, &client_p->whowas_clist);
|
||||
}
|
||||
*count = ids.size();
|
||||
*memused = ids.size() * sizeof(struct whowas);
|
||||
}
|
||||
|
||||
client::client *
|
||||
whowas_get_history(const char *nick, time_t timelimit)
|
||||
void
|
||||
whowas::off(client &client)
|
||||
{
|
||||
struct whowas_top *wtop;
|
||||
rb_dlink_node *ptr;
|
||||
|
||||
wtop = (whowas_top *)rb_radixtree_retrieve(whowas_tree, nick);
|
||||
if(wtop == NULL)
|
||||
return NULL;
|
||||
|
||||
timelimit = rb_current_time() - timelimit;
|
||||
|
||||
RB_DLINK_FOREACH_PREV(ptr, wtop->wwlist.tail)
|
||||
const auto &id(client.wwid);
|
||||
const auto ppit(ids.equal_range(id));
|
||||
std::for_each(ppit.first, ppit.second, []
|
||||
(const auto &pit)
|
||||
{
|
||||
struct Whowas *who = (Whowas *)ptr->data;
|
||||
if(who->logoff >= timelimit)
|
||||
auto &whowas(pit.second);
|
||||
whowas->online = nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
whowas::add(client &client)
|
||||
{
|
||||
// trim some of the entries if we're getting well over our history length
|
||||
trim();
|
||||
|
||||
// Client's wwid will be 0 if never seen before
|
||||
auto &id(client.wwid);
|
||||
if(!id)
|
||||
id = id_ctr++;
|
||||
|
||||
// This is an unconditional add to both maps.
|
||||
auto it(ids.lower_bound(id));
|
||||
it = ids.emplace_hint(it, id, std::make_shared<struct whowas>(client));
|
||||
nicks.emplace(client.name, it->second);
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<whowas::whowas>>
|
||||
whowas::history(const std::string &nick,
|
||||
const time_t &limit,
|
||||
const bool &online)
|
||||
{
|
||||
const auto ppit(nicks.equal_range(nick));
|
||||
const auto num(std::distance(ppit.first, ppit.second));
|
||||
std::vector<std::shared_ptr<struct whowas>> ret(num);
|
||||
std::transform(ppit.first, ppit.second, begin(ret), []
|
||||
(const auto &pit)
|
||||
{
|
||||
return pit.second;
|
||||
});
|
||||
|
||||
// C++11 says the multimap has stronger ordering and preserves
|
||||
// the insert order, which should already be the logoff time, so stuff below
|
||||
// this comment can be optimized at a later pass.
|
||||
std::sort(begin(ret), end(ret), []
|
||||
(const auto &a, const auto &b)
|
||||
{
|
||||
return a->logoff < b->logoff;
|
||||
});
|
||||
|
||||
const auto e(std::remove_if(begin(ret), end(ret), [&limit, &online]
|
||||
(const auto &whowas)
|
||||
{
|
||||
if(online && !whowas->online)
|
||||
return true;
|
||||
|
||||
if(limit && whowas->logoff + limit < rb_current_time())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}));
|
||||
|
||||
ret.erase(e, end(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<whowas::whowas>>
|
||||
whowas::history(const client &client)
|
||||
{
|
||||
return history(client.wwid);
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<whowas::whowas>>
|
||||
whowas::history(const id_t &wwid)
|
||||
{
|
||||
const auto ppit(ids.equal_range(wwid));
|
||||
const auto num(std::distance(ppit.first, ppit.second));
|
||||
std::vector<std::shared_ptr<struct whowas>> ret(num);
|
||||
std::transform(ppit.first, ppit.second, begin(ret), []
|
||||
(const auto &pit)
|
||||
{
|
||||
return pit.second;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
whowas::trim()
|
||||
{
|
||||
// Trims by oldest ID until satisfied.
|
||||
|
||||
auto it(begin(ids));
|
||||
while(it != end(ids) && nicks.size() > list_max)
|
||||
{
|
||||
const auto &id(it->first);
|
||||
const auto &whowas(it->second);
|
||||
const auto nick_ppit(nicks.equal_range(whowas->name));
|
||||
for(auto pit(nick_ppit.first); pit != nick_ppit.second; )
|
||||
{
|
||||
return who->online;
|
||||
const auto &nick_whowas(pit->second);
|
||||
if(nick_whowas->wwid == whowas->wwid)
|
||||
nicks.erase(pit++);
|
||||
else
|
||||
++pit;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
whowas_trim(void *unused)
|
||||
{
|
||||
long over;
|
||||
|
||||
if(rb_dlink_list_length(&whowas_list) < whowas_list_length)
|
||||
return;
|
||||
over = rb_dlink_list_length(&whowas_list) - whowas_list_length;
|
||||
|
||||
/* remove whowas entries over the configured length */
|
||||
for(long i = 0; i < over; i++)
|
||||
{
|
||||
if(whowas_list.tail != NULL && whowas_list.tail->data != NULL)
|
||||
{
|
||||
struct Whowas *twho = (Whowas *)whowas_list.tail->data;
|
||||
if(twho->online != NULL)
|
||||
rb_dlinkDelete(&twho->cnode, &twho->online->whowas_clist);
|
||||
rb_dlinkDelete(&twho->wnode, &twho->wtop->wwlist);
|
||||
rb_dlinkDelete(&twho->whowas_node, &whowas_list);
|
||||
whowas_free_wtop(twho->wtop);
|
||||
rb_free(twho);
|
||||
}
|
||||
ids.erase(it++);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
whowas_init(void)
|
||||
whowas::whowas::whowas(client &client)
|
||||
:wwid{client.wwid}
|
||||
,online{&client}
|
||||
,logoff{rb_current_time()}
|
||||
,scache
|
||||
{
|
||||
whowas_tree = rb_radixtree_create("whowas", irccasecanon);
|
||||
if(whowas_list_length == 0)
|
||||
{
|
||||
whowas_list_length = NICKNAMEHISTORYLENGTH;
|
||||
}
|
||||
rb_event_add("whowas_trim", whowas_trim, NULL, 10);
|
||||
client.serv? nameinfo(serv(client)) : nullptr
|
||||
}
|
||||
|
||||
void
|
||||
whowas_set_size(int len)
|
||||
,flag
|
||||
{
|
||||
whowas_list_length = len;
|
||||
whowas_trim(NULL);
|
||||
is_ip_spoof(client)? IP_SPOOFING : (enum flag)0 |
|
||||
is_dyn_spoof(client)? DYNSPOOF : (enum flag)0
|
||||
}
|
||||
|
||||
void
|
||||
whowas_memory_usage(size_t * count, size_t * memused)
|
||||
{
|
||||
*count = rb_dlink_list_length(&whowas_list);
|
||||
*memused += *count * sizeof(struct Whowas);
|
||||
*memused += sizeof(struct whowas_top) * rb_radixtree_size(whowas_tree);
|
||||
}
|
||||
|
||||
rb_strlcpy(name, client.name, sizeof(name));
|
||||
rb_strlcpy(username, client.username, sizeof(username));
|
||||
rb_strlcpy(hostname, client.host, sizeof(hostname));
|
||||
rb_strlcpy(realname, client.info, sizeof(realname));
|
||||
rb_strlcpy(sockhost, client.sockhost, sizeof(sockhost));
|
||||
assert(wwid);
|
||||
}
|
||||
|
|
|
@ -88,16 +88,21 @@ mo_kill(struct MsgBuf *msgbuf_p, client::client &client, client::client &source,
|
|||
** rewrite the KILL for this new nickname--this keeps
|
||||
** servers in synch when nick change and kill collide
|
||||
*/
|
||||
if((target_p = whowas_get_history(user, (long) KILLCHASETIMELIMIT)) == NULL)
|
||||
const auto history(whowas::history(user, KILLCHASETIMELIMIT, true));
|
||||
if(history.empty())
|
||||
{
|
||||
if (strchr(user, '.'))
|
||||
sendto_one_numeric(&source, ERR_CANTKILLSERVER, form_str(ERR_CANTKILLSERVER));
|
||||
else
|
||||
sendto_one_numeric(&source, ERR_NOSUCHNICK,
|
||||
form_str(ERR_NOSUCHNICK), user);
|
||||
sendto_one_numeric(&source, ERR_NOSUCHNICK, form_str(ERR_NOSUCHNICK),
|
||||
user);
|
||||
return;
|
||||
}
|
||||
sendto_one_notice(&source, ":KILL changed from %s to %s", user, target_p->name);
|
||||
|
||||
target_p = history.back()->online;
|
||||
sendto_one_notice(&source, ":KILL changed from %s to %s",
|
||||
user,
|
||||
target_p->name);
|
||||
}
|
||||
|
||||
if(!my_connect(*target_p) && (!IsOperGlobalKill(&source)))
|
||||
|
@ -205,12 +210,20 @@ ms_kill(struct MsgBuf *msgbuf_p, client::client &client, client::client &source,
|
|||
* not an uid, automatically rewrite the KILL for this new nickname.
|
||||
* --this keeps servers in synch when nick change and kill collide
|
||||
*/
|
||||
if(rfc1459::is_digit(*user) || (!(target_p = whowas_get_history(user, (long) KILLCHASETIMELIMIT))))
|
||||
if(rfc1459::is_digit(*user))
|
||||
{
|
||||
sendto_one_numeric(&source, ERR_NOSUCHNICK,
|
||||
form_str(ERR_NOSUCHNICK), rfc1459::is_digit(*user) ? "*" : user);
|
||||
sendto_one_numeric(&source, ERR_NOSUCHNICK, form_str(ERR_NOSUCHNICK), "*");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto history(whowas::history(user, KILLCHASETIMELIMIT, true));
|
||||
if(history.empty())
|
||||
{
|
||||
sendto_one_numeric(&source, ERR_NOSUCHNICK, form_str(ERR_NOSUCHNICK), user);
|
||||
return;
|
||||
}
|
||||
|
||||
target_p = history.back()->online;
|
||||
sendto_one_notice(&source, ":KILL changed from %s to %s", user, target_p->name);
|
||||
}
|
||||
|
||||
|
|
|
@ -648,7 +648,7 @@ change_local_nick(client::client &client, client::client &source,
|
|||
/* send the nick change to servers.. */
|
||||
if(source.user)
|
||||
{
|
||||
whowas_add_history(&source, 1);
|
||||
whowas::add(source);
|
||||
|
||||
if (dosend)
|
||||
{
|
||||
|
@ -708,7 +708,7 @@ change_remote_nick(client::client &client, client::client &source,
|
|||
|
||||
if(source.user)
|
||||
{
|
||||
whowas_add_history(&source, 1);
|
||||
whowas::add(source);
|
||||
if (dosend)
|
||||
{
|
||||
sendto_server(&client, NULL, CAP_TS6, NOCAPS, ":%s NICK %s :%ld",
|
||||
|
|
|
@ -223,7 +223,7 @@ doit:
|
|||
target_p->name, target_p->username,
|
||||
target_p->host, parv[2]);
|
||||
|
||||
whowas_add_history(target_p, 1);
|
||||
whowas::add(*target_p);
|
||||
sendto_server(NULL, NULL, CAP_TS6, NOCAPS, ":%s NICK %s :%ld",
|
||||
use_id(target_p), parv[2], (long) target_p->tsinfo);
|
||||
|
||||
|
|
|
@ -1322,7 +1322,7 @@ stats_memory (client::client &source)
|
|||
|
||||
size_t total_memory = 0;
|
||||
|
||||
whowas_memory_usage(&ww, &wwm);
|
||||
whowas::memory_usage(&ww, &wwm);
|
||||
|
||||
RB_DLINK_FOREACH(ptr, global_client_list.head)
|
||||
{
|
||||
|
|
|
@ -89,44 +89,47 @@ m_whowas(struct MsgBuf *msgbuf_p, client::client &client, client::client &source
|
|||
nick = parv[1];
|
||||
|
||||
sendq_limit = get_sendq(&client) * 9 / 10;
|
||||
whowas_list = whowas_get_list(nick);
|
||||
|
||||
if(whowas_list == NULL)
|
||||
const auto history(whowas::history(nick));
|
||||
if(history.empty())
|
||||
{
|
||||
sendto_one_numeric(&source, ERR_WASNOSUCHNICK, form_str(ERR_WASNOSUCHNICK), nick);
|
||||
sendto_one_numeric(&source, RPL_ENDOFWHOWAS, form_str(RPL_ENDOFWHOWAS), parv[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
RB_DLINK_FOREACH(ptr, whowas_list->head)
|
||||
for(const auto &ww : history)
|
||||
{
|
||||
struct Whowas *temp = (Whowas *)ptr->data;
|
||||
if(cur > 0 && rb_linebuf_len(&client.localClient->buf_sendq) > sendq_limit)
|
||||
{
|
||||
sendto_one(&source, form_str(ERR_TOOMANYMATCHES),
|
||||
me.name, source.name, "WHOWAS");
|
||||
me.name,
|
||||
source.name,
|
||||
"WHOWAS");
|
||||
break;
|
||||
}
|
||||
|
||||
sendto_one(&source, form_str(RPL_WHOWASUSER),
|
||||
me.name, source.name, temp->name,
|
||||
temp->username, temp->hostname, temp->realname);
|
||||
if (!EmptyString(temp->sockhost) &&
|
||||
strcmp(temp->sockhost, "0") &&
|
||||
show_ip_whowas(temp, &source))
|
||||
sendto_one_numeric(&source, RPL_WHOISACTUALLY,
|
||||
form_str(RPL_WHOISACTUALLY),
|
||||
temp->name, temp->sockhost);
|
||||
me.name,
|
||||
source.name,
|
||||
ww->name,
|
||||
ww->username,
|
||||
ww->hostname,
|
||||
ww->realname);
|
||||
|
||||
if (!EmptyString(temp->suser))
|
||||
sendto_one_numeric(&source, RPL_WHOISLOGGEDIN,
|
||||
"%s %s :was logged in as",
|
||||
temp->name, temp->suser);
|
||||
if(!EmptyString(ww->sockhost) && strcmp(ww->sockhost, "0") && show_ip_whowas(*ww, source))
|
||||
sendto_one_numeric(&source, RPL_WHOISACTUALLY, form_str(RPL_WHOISACTUALLY),
|
||||
ww->name,
|
||||
ww->sockhost);
|
||||
|
||||
if(!EmptyString(ww->suser))
|
||||
sendto_one_numeric(&source, RPL_WHOISLOGGEDIN, "%s %s :was logged in as",
|
||||
ww->name,
|
||||
ww->suser);
|
||||
|
||||
sendto_one_numeric(&source, RPL_WHOISSERVER, form_str(RPL_WHOISSERVER),
|
||||
temp->name,
|
||||
temp->scache? name(*temp->scache).c_str() : "*",
|
||||
rb_ctime(temp->logoff, tbuf, sizeof(tbuf)));
|
||||
ww->name,
|
||||
ww->scache? name(*ww->scache).c_str() : "*",
|
||||
rb_ctime(ww->logoff, tbuf, sizeof(tbuf)));
|
||||
|
||||
cur++;
|
||||
if(max > 0 && cur >= max)
|
||||
|
|
Loading…
Reference in a new issue