0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2025-01-13 08:23:56 +01:00

ircd: Towards a comprehensive capability C -> C++ refactor.

This commit is contained in:
Jason Volk 2016-08-12 15:20:34 -07:00
parent 10946db85e
commit fb8792da3d
8 changed files with 171 additions and 156 deletions

View file

@ -1,5 +1,7 @@
/*
* Copyright (c) 2016 Charybdis development team
* Copyright (c) 2012 - 2016 William Pitcock <nenolod@dereferenced.org>.
* Copyright (c) 2016 Jason Volk <jason@zemos.net>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -18,46 +20,48 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __CAPABILITY_H__
#define __CAPABILITY_H__
#pragma once
#define HAVE_IRCD_CAPABILITY_H
#include "stdinc.h"
#ifdef __cplusplus
namespace ircd {
namespace capability {
struct CapabilityEntry {
struct entry
{
std::string cap;
unsigned int value;
uint32_t value;
bool require;
bool orphan;
void *ownerdata;
void *ownerdata; //TODO: inheritance model
CapabilityEntry(std::string cap_, unsigned int value_, void *ownerdata_)
: cap(cap_), value(value_), require(false), orphan(false), ownerdata(ownerdata_) { }
entry(const std::string &cap, const uint32_t &value, void *const &ownerdata);
};
struct CapabilityIndex {
struct index
{
std::string name;
std::map<std::string, std::shared_ptr<CapabilityEntry>, case_insensitive_less> cap_dict;
unsigned int highest_bit;
uint32_t highest_bit;
std::list<index *>::iterator indexes_it;
std::map<std::string, std::shared_ptr<entry>, case_insensitive_less> caps;
CapabilityIndex(std::string name_);
~CapabilityIndex();
void stats(void (*cb)(const std::string &line, void *privdata), void *privdata) const;
std::string list(const uint32_t &cap_mask);
uint32_t required();
uint32_t mask();
std::shared_ptr<CapabilityEntry> find(std::string cap_name);
bool orphan(const std::string &cap_name);
bool require(const std::string &cap_name);
uint32_t get(const std::string &cap_name, void **ownerdata);
uint32_t put(const std::string &cap_name = "", void *ownerdata = nullptr);
uint32_t put_anonymous();
unsigned int get(std::string cap_name, void **ownerdata);
unsigned int put(std::string cap_name, void *ownerdata);
unsigned int put_anonymous();
void orphan(std::string cap_name);
void require(std::string cap_name);
void stats(void (*cb)(std::string &line, void *privdata), void *privdata);
const char *list(unsigned int cap_mask);
unsigned int mask();
unsigned int required();
index(const std::string &name);
~index();
};
extern void capability_stats(void (*cb)(std::string &line, void *privdata), void *privdata);
void stats(void (*cb)(const std::string &line, void *privdata), void *privdata);
#endif
} // namespace capability
} // namespace ircd
#endif // __cplusplus

View file

@ -46,8 +46,8 @@ struct server_conf;
struct Channel;
/* Capabilities */
extern struct CapabilityIndex serv_capindex;
extern struct CapabilityIndex cli_capindex;
extern ircd::capability::index serv_capindex; //TODO: namespace
extern ircd::capability::index cli_capindex; //TODO: namespace
/* register client capabilities with this structure for 3.2 enhanced capability negotiation */
#define CLICAP_FLAGS_STICKY 0x001

View file

@ -23,138 +23,127 @@
#include <ircd/s_assert.h>
#include <rb/format.h>
static std::list<CapabilityIndex *> capability_indexes;
using namespace ircd::capability;
CapabilityIndex::CapabilityIndex(std::string name_) : name(name_), highest_bit(1)
std::list<capability::index *> indexes;
entry::entry(const std::string &cap,
const uint32_t &value,
void *const &ownerdata)
:cap(cap)
,value(value)
,require(false)
,orphan(false)
,ownerdata(ownerdata)
{
capability_indexes.push_back(this);
}
CapabilityIndex::~CapabilityIndex()
index::index(const std::string &name)
:name(name)
,highest_bit(1)
,indexes_it(indexes.emplace(end(indexes), this))
{
for (auto it = capability_indexes.begin(); it != capability_indexes.end(); it++)
{
if (*it == this)
{
capability_indexes.erase(it);
break;
}
}
}
std::shared_ptr<CapabilityEntry>
CapabilityIndex::find(std::string cap)
index::~index()
{
return cap_dict[cap];
indexes.erase(indexes_it);
}
unsigned int
CapabilityIndex::get(std::string cap, void **ownerdata)
uint32_t
index::put(const std::string &cap,
void *ownerdata)
{
std::shared_ptr<CapabilityEntry> entry;
entry = find(cap);
if (entry != NULL && !entry->orphan)
{
if (ownerdata != NULL)
*ownerdata = entry->ownerdata;
return (1 << entry->value);
}
return 0;
}
unsigned int
CapabilityIndex::put(std::string cap, void *ownerdata)
{
std::shared_ptr<CapabilityEntry> entry;
if (highest_bit == 0)
return 0xFFFFFFFF;
if ((entry = find(cap)) != NULL)
auto it(caps.lower_bound(cap));
if (it != end(caps) && it->second->cap == cap)
{
auto &entry(it->second);
entry->orphan = false;
return (1 << entry->value);
return 1 << entry->value;
}
entry = cap_dict[cap] = std::make_shared<CapabilityEntry>(cap, highest_bit, ownerdata);
auto entry(std::make_shared<entry>(cap, highest_bit, ownerdata));
caps.emplace_hint(it, cap, entry);
highest_bit++;
if (highest_bit % (sizeof(unsigned int) * 8) == 0)
if (highest_bit % (sizeof(uint32_t) * 8) == 0)
highest_bit = 0;
return (1 << entry->value);
return 1 << entry->value;
}
unsigned int
CapabilityIndex::put_anonymous()
uint32_t
index::put_anonymous()
{
unsigned int value;
if (!highest_bit)
return 0xFFFFFFFF;
value = 1 << highest_bit;
const uint32_t value(1 << highest_bit);
highest_bit++;
if (highest_bit % (sizeof(unsigned int) * 8) == 0)
if (highest_bit % (sizeof(uint32_t) * 8) == 0)
highest_bit = 0;
return value;
}
void
CapabilityIndex::orphan(std::string cap)
uint32_t
index::get(const std::string &cap,
void **ownerdata)
try
{
std::shared_ptr<CapabilityEntry> entry;
auto &entry(caps.at(cap));
if (entry->orphan)
return 0;
entry = cap_dict[cap];
if (entry != NULL)
{
entry->require = false;
entry->orphan = true;
entry->ownerdata = NULL;
}
if (ownerdata != NULL)
*ownerdata = entry->ownerdata;
return 1 << entry->value;
}
catch(const std::out_of_range &e)
{
return 0;
}
void
CapabilityIndex::require(std::string cap)
bool
index::require(const std::string &cap)
{
std::shared_ptr<CapabilityEntry> entry;
const auto it(caps.find(cap));
if (it == end(caps))
return false;
entry = cap_dict[cap];
if (entry != NULL)
entry->require = true;
auto &entry(it->second);
entry->require = true;
return true;
}
const char *
CapabilityIndex::list(unsigned int cap_mask)
bool
index::orphan(const std::string &cap)
{
static std::string buf;
const auto it(caps.find(cap));
if (it == end(caps))
return false;
buf.clear();
for (auto it = cap_dict.begin(); it != cap_dict.end(); it++)
{
auto entry = it->second;
if ((1 << entry->value) & cap_mask)
{
buf += entry->cap + " ";
}
}
return buf.c_str();
auto &entry(it->second);
entry->require = false;
entry->orphan = true;
entry->ownerdata = NULL;
return true;
}
unsigned int
CapabilityIndex::mask()
uint32_t
index::mask()
{
unsigned int mask = 0;
for (auto it = cap_dict.begin(); it != cap_dict.end(); it++)
uint32_t mask(0);
for (const auto &it : caps)
{
auto entry = it->second;
const auto &entry(it.second);
if (!entry->orphan)
mask |= (1 << entry->value);
}
@ -162,14 +151,13 @@ CapabilityIndex::mask()
return mask;
}
unsigned int
CapabilityIndex::required()
uint32_t
index::required()
{
unsigned int mask = 0;
for (auto it = cap_dict.begin(); it != cap_dict.end(); it++)
uint32_t mask(0);
for (const auto &it : caps)
{
auto entry = it->second;
const auto &entry(it.second);
if (!entry->orphan && entry->require)
mask |= (1 << entry->value);
}
@ -177,20 +165,34 @@ CapabilityIndex::required()
return mask;
}
void
CapabilityIndex::stats(void (*cb)(std::string &line, void *privdata), void *privdata)
std::string
index::list(const uint32_t &cap_mask)
{
std::string out = fmt::format("'{0}': {1} allocated:", name, highest_bit - 1);
std::stringstream buf;
for (const auto &it : caps)
{
const auto &entry(it.second);
if ((1 << entry->value) & cap_mask)
buf << entry->cap << " ";
}
for (auto it = cap_dict.begin(); it != cap_dict.end(); it++)
out += fmt::format(" {0}<{1}>", it->first, it->second->value);
return buf.str();
}
void
index::stats(void (*cb)(const std::string &line, void *privdata), void *privdata)
const
{
std::string out(fmt::format("'{0}': {1} allocated:", name, highest_bit - 1));
for (const auto &it : caps)
out += fmt::format(" {0}<{1}>", it.first, it.second->value);
cb(out, privdata);
}
void
capability_stats(void (*cb)(std::string &line, void *privdata), void *privdata)
capability::stats(void (*cb)(const std::string &line, void *privdata), void *privdata)
{
for (auto it = capability_indexes.begin(); it != capability_indexes.end(); it++)
(*it)->stats(cb, privdata);
for (const auto &index : indexes)
index->stats(cb, privdata);
}

View file

@ -364,7 +364,9 @@ static
bool init_module__cap(struct module *const mod,
mapi_cap_list_av2 *const m)
{
struct CapabilityIndex *idx;
using ircd::capability::index;
index *idx;
switch(m->cap_index)
{
case MAPI_CAP_CLIENT: idx = &cli_capindex; break;
@ -392,7 +394,9 @@ static
void fini_module__cap(struct module *const mod,
mapi_cap_list_av2 *const m)
{
struct CapabilityIndex *idx;
using ircd::capability::index;
index *idx;
switch(m->cap_index)
{
case MAPI_CAP_CLIENT: idx = &cli_capindex; break;

View file

@ -53,6 +53,8 @@
#include <ircd/capability.h>
#include <ircd/s_assert.h>
using namespace ircd;
int MaxConnectionCount = 1;
int MaxClientCount = 1;
int refresh_user_links = 0;
@ -64,8 +66,8 @@ static char buf[BUFSIZE];
* because all servers that we talk to already do TS, and the kludged
* extra argument to "PASS" takes care of checking that. -orabidoo
*/
struct CapabilityIndex serv_capindex {"server capabilities"};
struct CapabilityIndex cli_capindex {"client capabilities"};
capability::index serv_capindex {"server capabilities"};
capability::index cli_capindex {"client capabilities"};
unsigned int CAP_CAP;
unsigned int CAP_QS;
@ -458,7 +460,7 @@ check_server(const char *name, struct Client *client_p)
void
send_capabilities(struct Client *client_p, unsigned int cap_can_send)
{
sendto_one(client_p, "CAPAB :%s", serv_capindex.list(cap_can_send));
sendto_one(client_p, "CAPAB :%s", serv_capindex.list(cap_can_send).c_str());
}
static void
@ -766,7 +768,7 @@ show_capabilities(struct Client *target_p)
return msgbuf + 1;
rb_strlcat(msgbuf, " ", sizeof(msgbuf));
rb_strlcat(msgbuf, serv_capindex.list(target_p->serv->caps), sizeof(msgbuf));
rb_strlcat(msgbuf, serv_capindex.list(target_p->serv->caps).c_str(), sizeof(msgbuf));
return msgbuf + 1;
}

View file

@ -76,7 +76,6 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
struct Client *target_p;
int hop;
unsigned int required_mask;
const char *missing;
int ret;
name = parv[1];
@ -222,18 +221,18 @@ mr_server(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
required_mask = serv_capindex.required();
if (!IsCapable(client_p, required_mask))
{
missing = serv_capindex.list(required_mask & ~client_p->localClient->caps);
const auto missing(serv_capindex.list(required_mask & ~client_p->localClient->caps));
sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) ? L_NETWIDE : L_ALL,
"Link %s dropped, required CAPABs [%s] are missing",
name, missing);
name, missing.c_str());
ilog(L_SERVER, "Link %s%s dropped, required CAPABs [%s] are missing",
EmptyString(client_p->name) ? name : "",
log_client_name(client_p, SHOW_IP), missing);
log_client_name(client_p, SHOW_IP), missing.c_str());
/* Do not use '[' in the below message because it would cause
* it to be considered potentially unsafe (might disclose IP
* addresses)
*/
sendto_one(client_p, "ERROR :Missing required CAPABs (%s)", missing);
sendto_one(client_p, "ERROR :Missing required CAPABs (%s)", missing.c_str());
exit_client(client_p, client_p, client_p, "Missing required CAPABs");
return;

View file

@ -44,6 +44,8 @@
#include <ircd/s_conf.h>
#include <ircd/hash.h>
using namespace ircd;
static const char cap_desc[] = "Provides the commands used for client capability negotiation";
typedef int (*bqcmp)(const void *, const void *);
@ -63,7 +65,7 @@ DECLARE_MODULE_AV2(cap, NULL, NULL, cap_clist, NULL, NULL, NULL, NULL, cap_desc)
#define HasCapabilityFlag(c, f) (c->ownerdata != NULL && (((struct ClientCapability *)c->ownerdata)->flags & (f)) == f)
static inline int
clicap_visible(struct Client *client_p, const std::shared_ptr<CapabilityEntry> cap)
clicap_visible(struct Client *client_p, const std::shared_ptr<capability::entry> cap)
{
struct ClientCapability *clicap;
@ -89,12 +91,11 @@ clicap_visible(struct Client *client_p, const std::shared_ptr<CapabilityEntry> c
* int pointer to whether we finish with success
* Ouputs: Cap entry if found, NULL otherwise.
*/
static std::shared_ptr<CapabilityEntry>
static std::shared_ptr<capability::entry>
clicap_find(const char *data, int *negate, int *finished)
{
static char buf[BUFSIZE];
static char *p;
std::shared_ptr<CapabilityEntry> cap;
char *s;
*negate = 0;
@ -131,15 +132,16 @@ clicap_find(const char *data, int *negate, int *finished)
if((s = strchr(p, ' ')))
*s++ = '\0';
if((cap = cli_capindex.find(p)) != NULL)
{
if(s)
p = s;
else
*finished = 1;
}
const auto it(cli_capindex.caps.find(p));
if (it == end(cli_capindex.caps))
return {};
return cap;
if (s)
p = s;
else
*finished = 1;
return it->second;
}
/* clicap_generate()
@ -170,10 +172,10 @@ clicap_generate(struct Client *source_p, const char *subcmd, int flags)
return;
}
for (auto it = cli_capindex.cap_dict.begin(); it != cli_capindex.cap_dict.end(); it++)
for (const auto &it : cli_capindex.caps)
{
size_t caplen = 0;
const auto entry = it->second;
const auto &entry(it.second);
const auto clicap(reinterpret_cast<ClientCapability *>(entry->ownerdata));
const char *data = NULL;
@ -217,7 +219,7 @@ clicap_generate(struct Client *source_p, const char *subcmd, int flags)
static void
cap_ack(struct Client *source_p, const char *arg)
{
std::shared_ptr<CapabilityEntry> cap;
std::shared_ptr<capability::entry> cap;
int capadd = 0, capdel = 0;
int finished = 0, negate;
@ -290,7 +292,7 @@ cap_req(struct Client *source_p, const char *arg)
{
char buf[BUFSIZE];
char pbuf[2][BUFSIZE];
std::shared_ptr<CapabilityEntry> cap;
std::shared_ptr<capability::entry> cap;
int buflen, plen;
int i = 0;
int capadd = 0, capdel = 0;

View file

@ -46,6 +46,8 @@
#include <ircd/whowas.h>
#include <ircd/sslproc.h>
using namespace ircd;
static const char stats_desc[] =
"Provides the STATS command to inspect various server/network information";
@ -819,7 +821,7 @@ stats_oper(struct Client *source_p)
}
static void
stats_capability_walk(std::string &line, void *data)
stats_capability_walk(const std::string &line, void *data)
{
struct Client *client_p = (Client *)data;
@ -829,7 +831,7 @@ stats_capability_walk(std::string &line, void *data)
static void
stats_capability(struct Client *client_p)
{
capability_stats(stats_capability_walk, client_p);
capability::stats(stats_capability_walk, client_p);
}
static void