0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-12-26 15:33:54 +01:00

Upgrade channel membership lists.

This commit is contained in:
Jason Volk 2016-08-19 17:32:26 -07:00
parent 276cad4275
commit 5752be41b8
33 changed files with 447 additions and 394 deletions

View file

@ -52,7 +52,7 @@ m_findforwards(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *
/* Allow ircops to search for forwards to nonexistent channels */
if(!IsOper(source_p))
{
if((chptr = find_channel(parv[1])) == NULL || (msptr = find_channel_membership(chptr, source_p)) == NULL)
if((chptr = find_channel(parv[1])) == NULL || (msptr = get(chptr->members, *source_p, std::nothrow)) == NULL)
{
sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
form_str(ERR_NOTONCHANNEL), parv[1]);

View file

@ -84,7 +84,7 @@ mo_ojoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
if(*parv[1] == '@')
{
add_user_to_channel(chptr, source_p, chan::CHANOP);
add(*chptr, *source_p, chan::CHANOP);
sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
":%s SJOIN %ld %s + :@%s",
me.id, (long) chptr->channelts, chptr->name.c_str(), source_p->id);
@ -95,7 +95,7 @@ mo_ojoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
}
else if(*parv[1] == '+')
{
add_user_to_channel(chptr, source_p, chan::VOICE);
add(*chptr, *source_p, chan::VOICE);
sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
":%s SJOIN %ld %s + :+%s",
me.id, (long) chptr->channelts, chptr->name.c_str(), source_p->id);
@ -105,7 +105,7 @@ mo_ojoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
}
else
{
add_user_to_channel(chptr, source_p, chan::PEON);
add(*chptr, *source_p, chan::PEON);
sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
":%s JOIN %ld %s +",
source_p->id, (long) chptr->channelts, chptr->name.c_str());

View file

@ -97,7 +97,7 @@ mo_okick(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
return;
}
if((msptr = find_channel_membership(chptr, target_p)) == NULL)
if((msptr = get(chptr->members, *target_p, std::nothrow)) == NULL)
{
sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL), parv[1], parv[2]);
return;
@ -120,5 +120,6 @@ mo_okick(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
me.name, chptr->name.c_str(), who->name, comment);
sendto_server(&me, chptr, CAP_TS6, NOCAPS,
":%s KICK %s %s :%s", me.id, chptr->name.c_str(), who->id, comment);
remove_user_from_channel(msptr);
del(*chptr, *target_p);
}

View file

@ -76,7 +76,7 @@ mo_omode(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
}
/* Now know the channel exists */
msptr = find_channel_membership(chptr, source_p);
msptr = get(chptr->members, *source_p, std::nothrow);
wasonchannel = msptr != NULL;
if (is_chanop(msptr))
@ -133,8 +133,8 @@ mo_omode(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
msptr->flags |= chan::CHANOP;
else
{
add_user_to_channel(chptr, source_p, chan::CHANOP);
msptr = find_channel_membership(chptr, source_p);
add(*chptr, *source_p, chan::CHANOP);
msptr = get(chptr->members, *source_p, std::nothrow);
}
set_channel_mode(client_p, source_p, chptr, msptr,
parc - 2, parv + 2);
@ -144,7 +144,7 @@ mo_omode(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
if (wasonchannel)
msptr->flags &= ~chan::CHANOP;
else
remove_user_from_channel(msptr);
del(*chptr, get_client(*msptr));
}
#endif
}

View file

@ -57,9 +57,9 @@ mo_opme(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
return;
}
RB_DLINK_FOREACH(ptr, chptr->members.head)
for(auto &pit : chptr->members.global)
{
msptr = (chan::membership *)ptr->data;
msptr = &pit.second;
if(is_chanop(msptr))
{
@ -68,7 +68,7 @@ mo_opme(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
}
}
msptr = find_channel_membership(chptr, source_p);
msptr = get(chptr->members, *source_p, std::nothrow);
if(msptr == NULL)
return;

View file

@ -80,7 +80,7 @@ m_remove(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
if(!IsServer(source_p))
{
msptr = find_channel_membership(chptr, source_p);
msptr = get(chptr->members, *source_p, std::nothrow);
if((msptr == NULL) && MyConnect(source_p))
{
@ -139,7 +139,7 @@ m_remove(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
return;
}
msptr = find_channel_membership(chptr, who);
msptr = get(chptr->members, *who, std::nothrow);
if(msptr != NULL)
{
@ -190,7 +190,7 @@ m_remove(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
":%s KICK %s %s :%s",
use_id(source_p), chptr->name.c_str(), use_id(who), comment);
remove_user_from_channel(msptr);
del(*chptr, get_client(*msptr));
}
else if (MyClient(source_p))
sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,

View file

@ -140,7 +140,7 @@ m_displaymsg(struct MsgBuf *msgbuf_p, struct Client *source_p, const char *chann
return;
}
if(!(msptr = find_channel_membership(chptr, source_p)))
if(!(msptr = get(chptr->members, *source_p, std::nothrow)))
{
sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
form_str(ERR_NOTONCHANNEL), chptr->name.c_str());

View file

@ -43,7 +43,7 @@ h_scc_channel_join(void *vdata)
struct Client *source_p = data->client;
/* If they just joined a channel, and it only has one member, then they just created it. */
if(rb_dlink_list_length(&chptr->members) == 1 && is_chanop(find_channel_membership(chptr, source_p)))
if(size(chptr->members) == 1 && is_chanop(get(chptr->members, *source_p, std::nothrow)))
{
sendto_realops_snomask(snomask_modes['l'], L_NETWIDE, "%s is creating new channel %s",
source_p->name, chptr->name.c_str());

View file

@ -165,11 +165,10 @@ int chans_add(struct chan *const chan)
if(!rb_radixtree_add(chans, chan->name.c_str(), chan))
return 0;
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, chan->members.head)
for(const auto &pit : chan->members.global)
{
const auto msptr(reinterpret_cast<membership *>(ptr->data));
bloom_add_str(msptr->client->name);
const auto &client(pit.first);
bloom_add_str(client->name);
}
return 1;

View file

@ -34,6 +34,7 @@ namespace chan {
IRCD_EXCEPTION(ircd::error, error)
IRCD_EXCEPTION(error, not_found)
IRCD_EXCEPTION(error, invalid_list)
IRCD_EXCEPTION(error, invalid_argument)
enum status
{
@ -96,17 +97,15 @@ uint operator~(const modes &);
struct membership
{
rb_dlink_node channode;
rb_dlink_node locchannode;
rb_dlink_node usernode;
struct chan *chan;
Client *client;
unsigned int flags;
using global = std::map<client *, membership>;
using local = std::list<membership *>;
uint flags;
time_t bants;
global::iterator git;
local::iterator lit;
membership();
membership(const uint &flags = 0);
~membership() noexcept;
};
@ -119,6 +118,27 @@ bool is_chanop_voiced(const membership *const &);
bool can_send_banned(const membership &);
bool can_send_banned(const membership *const &);
const char *find_status(const membership *const &msptr, const int &combine);
const client &get_client(const membership &);
client &get_client(membership &);
struct members
{
membership::global global;
membership::local local;
members();
~members() noexcept;
};
bool empty(const members &);
size_t size(const members &);
bool local_empty(const members &);
size_t local_size(const members &);
bool exists(const members &, const client &);
const membership *get(const members &, const client &, std::nothrow_t);
const membership &get(const members &, const client &);
membership *get(members &, const client &, std::nothrow_t);
membership &get(members &, const client &);
bool has_prefix(const char *const &name);
bool has_prefix(const std::string &name);
@ -131,11 +151,8 @@ struct chan
struct modes mode;
std::string mode_lock;
struct topic topic;
rb_dlink_list members;
rb_dlink_list locmembers;
struct members members;
std::set<client *> invites;
list bans;
list excepts;
list invexs;
@ -160,6 +177,7 @@ struct chan
~chan() noexcept;
};
const auto &name(const chan &);
bool is_secret(const chan &);
bool is_secret(const chan *const &);
bool is_hidden(const chan &);
@ -206,9 +224,6 @@ void del_invite(chan &, client &);
void clear_invites(chan &);
bool flood_attack_channel(int p_or_n, client *source, chan *);
void add_user_to_channel(chan *, client *, int flags);
void remove_user_from_channel(membership *);
void remove_user_from_channels(client *);
void invalidate_bancache_user(client *);
void channel_member_names(chan *, client *, int show_eon);
const char *channel_modes(chan *, client *who);
@ -227,13 +242,17 @@ int match_extban(const char *banstr, client *, chan *, long mode_type);
int valid_extban(const char *banstr, client *, chan *, long mode_type);
const char * get_extban_string(void);
int get_channel_access(client *source, chan *, membership *, int dir, const char *modestr);
membership *find_channel_membership(chan *chptr, client *client_p);
void send_join(chan &, client &);
//extern std::map<std::string, std::unique_ptr<chan>> chans;
extern rb_dlink_list global_channel_list;
// Add and remove clients from channels
void add(chan &, client &, const int &flags = PEON);
void del(chan &, client &);
void del(client &); // remove from all channels
// Initialize subsystem
void init();
@ -276,8 +295,7 @@ is_public(const chan *const &c)
inline bool
is_member(const chan &c, const client &client)
{
//return client.user && get(c, client, std::nothrow) != nullptr;
return find_channel_membership(const_cast<struct chan *>(&c), const_cast<Client *>(&client)) != nullptr;
return exists(c.members, client);
}
inline bool
@ -322,6 +340,42 @@ valid_name(const std::string &name)
return !name.empty() && std::all_of(begin(name), end(name), rfc1459::is_chan);
}
inline const auto &
name(const chan &chan)
{
return chan.name;
}
inline size_t
local_size(const members &m)
{
return std::distance(begin(m.local), end(m.local));
}
inline bool
local_empty(const members &m)
{
return m.local.empty();
}
inline size_t
size(const members &m)
{
return m.global.size();
}
inline bool
empty(const members &m)
{
return m.global.empty();
}
inline bool
exists(const members &m, const client &c)
{
return m.global.count(const_cast<client *>(&c));
}
inline bool
is_chanop(const membership &m)
{
@ -358,6 +412,18 @@ is_chanop_voiced(const membership *const &m)
return m && is_chanop_voiced(*m);
}
inline client &
get_client(membership &m)
{
return *m.git->first;
}
inline const client &
get_client(const membership &m)
{
return *m.git->first;
}
inline bool
can_send_banned(const membership &m)
{

View file

@ -68,7 +68,7 @@ typedef int SSL_OPEN_CB(struct Client *, int status);
*/
struct User
{
rb_dlink_list channel; /* chain of channel pointer blocks */
std::map<chan::chan *, chan::membership *> channel;
std::set<chan::chan *> invited;
char *away; /* pointer to away message */
int refcnt; /* Number of times this block is referenced */

View file

@ -49,8 +49,7 @@ chan::chan::chan(const std::string &name)
,mode{}
,mode_lock{}
,topic{}
,members{0}
,locmembers{0}
,members{}
,join_count{0}
,join_delta{0}
,flood_noticed{0}
@ -74,13 +73,108 @@ noexcept
del_from_channel_hash(name.c_str(), this);
}
chan::membership::membership()
:channode{0}
,locchannode{0}
,usernode{0}
,chan{nullptr}
,client{nullptr}
,flags{0}
/* remove_user_from_channels()
*
* input - user to remove from all channels
* output -
* side effects - user is removed from all channels
*/
void
chan::del(client &client)
{
auto &client_chans(client.user->channel);
for(const auto &pit : client_chans)
{
auto &chan(*pit.first);
auto &member(*pit.second);
if (my(client))
chan.members.local.erase(member.lit);
chan.members.global.erase(member.git);
chan.invites.erase(&client);
if (empty(chan.members) && ~chan.mode & mode::PERMANENT)
delete &chan;
}
client_chans.clear();
client.user->invited.clear();
}
void
chan::del(chan &chan,
client &client)
{
// These are the relevant containers.
auto &global(chan.members.global);
auto &local(chan.members.local);
auto &client_chans(client.user->channel);
const auto it(client_chans.find(&chan));
if (it == end(client_chans))
return;
auto &member(*it->second);
if (my(client))
chan.members.local.erase(member.lit);
chan.members.global.erase(member.git); // The member is destroyed at this point.
client_chans.erase(it);
if (empty(chan.members) && ~chan.mode & mode::PERMANENT)
delete &chan;
}
void
chan::add(chan &chan,
client &client,
const int &flags)
{
if (!client.user)
{
s_assert(0);
return;
}
// These are the relevant containers.
auto &global(chan.members.global);
auto &local(chan.members.local);
auto &client_chans(client.user->channel);
// Add client to channel's global map
const auto iit(global.emplace(&client, flags));
if (!iit.second)
return;
// The global map hosts the membership structure.
auto &member(iit.first->second);
// Add iterator (pointer to the element) for constant time lookup/removal
member.git = iit.first;
// Add channel to client's channel map, pointing to the membership;
client_chans.emplace(&chan, &member);
// Add membership to a local list which can be iterated for local IO;
// iterator to this element is saved more crucially here to prevent linear removal
if (my(client))
member.lit = local.emplace(end(local), &member);
}
chan::members::members()
{
}
chan::members::~members()
noexcept
{
}
chan::membership::membership(const uint &flags)
:flags{flags}
,bants{0}
{
}
@ -144,46 +238,66 @@ chan::send_join(chan &chan,
client.user->away);
}
/* find_channel_membership()
*
* input - channel to find them in, client to find
* output - membership of client in channel, else NULL
* side effects -
*/
chan::membership *
chan::find_channel_membership(chan *chptr, client *client_p)
chan::membership &
chan::get(members &members,
const client &client)
{
struct membership *msptr;
rb_dlink_node *ptr;
if (!is_client(client))
throw invalid_argument();
if(!IsClient(client_p))
return NULL;
const auto key(const_cast<ircd::chan::client *>(&client)); //TODO: temp elaborated
const auto it(members.global.find(key));
if (it == end(members.global))
throw not_found();
/* Pick the most efficient list to use to be nice to things like
* CHANSERV which could be in a large number of channels
*/
if(rb_dlink_list_length(&chptr->members) < rb_dlink_list_length(&client_p->user->channel))
{
RB_DLINK_FOREACH(ptr, chptr->members.head)
{
msptr = (membership *)ptr->data;
return it->second;
}
if(msptr->client == client_p)
return msptr;
}
}
else
{
RB_DLINK_FOREACH(ptr, client_p->user->channel.head)
{
msptr = (membership *)ptr->data;
const chan::membership &
chan::get(const members &members,
const client &client)
{
if (!is_client(client))
throw invalid_argument();
if(msptr->chan == chptr)
return msptr;
}
}
const auto key(const_cast<ircd::chan::client *>(&client)); //TODO: temp elaborated
const auto it(members.global.find(key));
if (it == end(members.global))
throw not_found();
return NULL;
return it->second;
}
chan::membership *
chan::get(members &members,
const client &client,
std::nothrow_t)
{
if (!is_client(client))
return nullptr;
const auto key(const_cast<ircd::chan::client *>(&client)); //TODO: temp elaborated
const auto it(members.global.find(key));
if (it == end(members.global))
return nullptr;
return &it->second;
}
const chan::membership *
chan::get(const members &members,
const client &client,
std::nothrow_t)
{
if (!is_client(client))
return nullptr;
const auto key(const_cast<ircd::chan::client *>(&client)); //TODO: temp elaborated
const auto it(members.global.find(key));
if (it == end(members.global))
return nullptr;
return &it->second;
}
/* find_channel_status()
@ -215,102 +329,6 @@ chan::find_status(const membership *const &msptr,
return buffer;
}
/* add_user_to_channel()
*
* input - channel to add client to, client to add, channel flags
* output -
* side effects - user is added to channel
*/
void
chan::add_user_to_channel(chan *chptr, client *client_p, int flags)
{
membership *msptr;
s_assert(client_p->user != NULL);
if(client_p->user == NULL)
return;
msptr = new membership;
msptr->chan = chptr;
msptr->client = client_p;
msptr->flags = flags;
rb_dlinkAdd(msptr, &msptr->usernode, &client_p->user->channel);
rb_dlinkAdd(msptr, &msptr->channode, &chptr->members);
if(MyClient(client_p))
rb_dlinkAdd(msptr, &msptr->locchannode, &chptr->locmembers);
}
/* remove_user_from_channel()
*
* input - membership pointer to remove from channel
* output -
* side effects - membership (thus user) is removed from channel
*/
void
chan::remove_user_from_channel(membership *msptr)
{
client *client_p;
chan *chptr;
s_assert(msptr != NULL);
if(msptr == NULL)
return;
client_p = msptr->client;
chptr = msptr->chan;
rb_dlinkDelete(&msptr->usernode, &client_p->user->channel);
rb_dlinkDelete(&msptr->channode, &chptr->members);
if(client_p->servptr == &me)
rb_dlinkDelete(&msptr->locchannode, &chptr->locmembers);
if(!(chptr->mode.mode & mode::PERMANENT) && rb_dlink_list_length(&chptr->members) <= 0)
delete chptr;
delete msptr;
return;
}
/* remove_user_from_channels()
*
* input - user to remove from all channels
* output -
* side effects - user is removed from all channels
*/
void
chan::remove_user_from_channels(client *client_p)
{
chan *chptr;
membership *msptr;
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
if(client_p == NULL)
return;
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->user->channel.head)
{
msptr = (membership *)ptr->data;
chptr = msptr->chan;
rb_dlinkDelete(&msptr->channode, &chptr->members);
if(client_p->servptr == &me)
rb_dlinkDelete(&msptr->locchannode, &chptr->locmembers);
if(!(chptr->mode.mode & mode::PERMANENT) && rb_dlink_list_length(&chptr->members) <= 0)
delete chptr;
delete msptr;
}
client_p->user->channel.head = client_p->user->channel.tail = NULL;
client_p->user->channel.length = 0;
}
/* invalidate_bancache_user()
*
* input - user to invalidate ban cache for
@ -319,19 +337,17 @@ chan::remove_user_from_channels(client *client_p)
* to be used after a nick change
*/
void
chan::invalidate_bancache_user(client *client_p)
chan::invalidate_bancache_user(client *client)
{
membership *msptr;
rb_dlink_node *ptr;
if(client_p == NULL)
if(!client)
return;
RB_DLINK_FOREACH(ptr, client_p->user->channel.head)
for(const auto &pair : client->user->channel)
{
msptr = (membership *)ptr->data;
msptr->bants = 0;
msptr->flags &= ~BANNED;
auto &chan(*pair.first);
auto &member(*pair.second);
member.bants = 0;
member.flags &= ~BANNED;
}
}
@ -358,7 +374,6 @@ channel_pub_or_secret(chan::chan *const &chptr)
void
chan::channel_member_names(chan *chptr, client *client_p, int show_eon)
{
membership *msptr;
client *target_p;
rb_dlink_node *ptr;
char lbuf[BUFSIZE];
@ -376,10 +391,10 @@ chan::channel_member_names(chan *chptr, client *client_p, int show_eon)
t = lbuf + cur_len;
RB_DLINK_FOREACH(ptr, chptr->members.head)
for(const auto &pair : chptr->members.global)
{
msptr = (membership *)ptr->data;
target_p = msptr->client;
auto *const target_p(pair.first);
const auto &member(pair.second);
if(IsInvisible(target_p) && !is_member(chptr, client_p))
continue;
@ -395,7 +410,7 @@ chan::channel_member_names(chan *chptr, client *client_p, int show_eon)
t = lbuf + mlen;
}
tlen = sprintf(t, "%s%s!%s@%s ", find_status(msptr, stack),
tlen = sprintf(t, "%s%s!%s@%s ", find_status(&member, stack),
target_p->name, target_p->username, target_p->host);
}
else
@ -409,7 +424,7 @@ chan::channel_member_names(chan *chptr, client *client_p, int show_eon)
t = lbuf + mlen;
}
tlen = sprintf(t, "%s%s ", find_status(msptr, stack),
tlen = sprintf(t, "%s%s ", find_status(&member, stack),
target_p->name);
}
@ -733,8 +748,7 @@ chan::can_join(client *source_p, chan *chptr, const char *key, const char **forw
}
}
if(chptr->mode.limit &&
rb_dlink_list_length(&chptr->members) >= (unsigned long) chptr->mode.limit)
if(chptr->mode.limit && size(chptr->members) >= ulong(chptr->mode.limit))
i = ERR_CHANNELISFULL;
if(chptr->mode.mode & mode::REGONLY && EmptyString(source_p->user->suser))
i = ERR_NEEDREGGEDNICK;
@ -783,7 +797,7 @@ chan::can_send(chan *chptr, client *source_p, membership *msptr)
if(msptr == NULL)
{
msptr = find_channel_membership(chptr, source_p);
msptr = get(chptr->members, *source_p, std::nothrow);
if(msptr == NULL)
{
@ -828,7 +842,7 @@ chan::can_send(chan *chptr, client *source_p, membership *msptr)
moduledata.approved = CAN_SEND_OPV;
moduledata.client = source_p;
moduledata.chptr = msptr->chan;
moduledata.chptr = chptr;
moduledata.msptr = msptr;
moduledata.target = NULL;
moduledata.dir = moduledata.approved == CAN_SEND_NO? MODE_ADD : MODE_QUERY;
@ -913,10 +927,11 @@ chan::find_bannickchange_channel(client *client_p)
sprintf(src_host, "%s!%s@%s", client_p->name, client_p->username, client_p->host);
sprintf(src_iphost, "%s!%s@%s", client_p->name, client_p->username, client_p->sockhost);
RB_DLINK_FOREACH(ptr, client_p->user->channel.head)
for(const auto &pit : client_p->user->channel)
{
msptr = (membership *)ptr->data;
chptr = msptr->chan;
auto &chptr(pit.first);
auto &msptr(pit.second);
if (is_chanop_voiced(msptr))
continue;
/* cached can_send */
@ -1270,10 +1285,11 @@ chan::resv_chan_forcepart(const char *name, const char *reason, int temp_time)
chptr = find_channel(name);
if(chptr != NULL)
{
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
// Iterate a copy of the local list while all of this is going on
auto local(chptr->members.local);
for(auto &msptr : local)
{
msptr = (membership *)ptr->data;
target_p = msptr->client;
const auto target_p(msptr->git->first);
if(IsExemptResv(target_p))
continue;
@ -1285,7 +1301,7 @@ chan::resv_chan_forcepart(const char *name, const char *reason, int temp_time)
target_p->name, target_p->username,
target_p->host, chptr->name.c_str(), target_p->name);
remove_user_from_channel(msptr);
del(*chptr, *target_p);
/* notify opers & user they were removed from the channel */
sendto_realops_snomask(SNO_GENERAL, L_ALL,

View file

@ -409,8 +409,7 @@ pretty_mask(const char *idmask)
* side effects - numeric sent if not allowed
*/
static bool
check_forward(struct Client *source_p, chan::chan *chptr,
const char *forward)
check_forward(Client *source_p, chan::chan *chptr, const char *forward)
{
chan::chan *targptr = NULL;
chan::membership *msptr;
@ -436,11 +435,13 @@ check_forward(struct Client *source_p, chan::chan *chptr,
}
if(MyClient(source_p) && !(targptr->mode.mode & mode::FREETARGET))
{
if((msptr = find_channel_membership(targptr, source_p)) == NULL ||
chan::get_channel_access(source_p, targptr, msptr, MODE_QUERY, NULL) < chan::CHANOP)
auto *const msptr(get(targptr->members, *source_p, std::nothrow));
if(!msptr || get_channel_access(source_p, targptr, msptr, MODE_QUERY, NULL) < chan::CHANOP)
{
sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
me.name, source_p->name, targptr->name.c_str());
me.name,
source_p->name,
targptr->name.c_str());
return false;
}
}
@ -954,7 +955,7 @@ mode::functor::op(client *source_p, chan *chptr,
return;
}
mstptr = find_channel_membership(chptr, targ_p);
mstptr = get(chptr->members, *targ_p, std::nothrow);
if(mstptr == NULL)
{
@ -1030,7 +1031,7 @@ mode::functor::voice(client *source_p, chan *chptr,
return;
}
mstptr = find_channel_membership(chptr, targ_p);
mstptr = get(chptr->members, *targ_p, std::nothrow);
if(mstptr == NULL)
{

View file

@ -1265,10 +1265,10 @@ exit_generic_client(struct Client *client_p, struct Client *source_p, struct Cli
source_p->name,
source_p->username, source_p->host, comment);
chan::remove_user_from_channels(source_p);
chan::del(*source_p);
/* Should not be in any channels now */
s_assert(source_p->user->channel.head == NULL);
s_assert(source_p->user->channel.empty());
// Clean up invitefield
for (auto &chan : source_p->user->invited)
@ -1839,10 +1839,10 @@ free_user(struct User *user, struct Client *client_p)
/*
* sanity check
*/
if(user->refcnt < 0 || !user->invited.empty() || user->channel.head)
if(user->refcnt < 0 || !user->invited.empty() || !user->channel.empty())
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"* %p user (%s!%s@%s) %p %lu %p %lu %d *",
"* %p user (%s!%s@%s) %p %lu %lu %d *",
client_p,
client_p ? client_p->
name : "<noname>",
@ -1850,12 +1850,11 @@ free_user(struct User *user, struct Client *client_p)
client_p->host,
user,
user->invited.size(),
user->channel.head,
rb_dlink_list_length(&user->channel),
user->channel.size(),
user->refcnt);
s_assert(!user->refcnt);
s_assert(user->invited.empty());
s_assert(!user->channel.head);
s_assert(user->channel.empty());
}
rb_bh_free(user_heap, user);

View file

@ -646,11 +646,12 @@ burst_TS6(struct Client *client_p)
t = buf + mlen;
RB_DLINK_FOREACH(uptr, chptr->members.head)
for (auto &pair : chptr->members.global)
{
msptr = (chan::membership *)uptr->data;
msptr = &pair.second;
auto *const client(pair.first);
tlen = strlen(use_id(msptr->client)) + 1;
tlen = strlen(use_id(client)) + 1;
if(is_chanop(msptr))
tlen++;
if(is_voiced(msptr))
@ -664,13 +665,13 @@ burst_TS6(struct Client *client_p)
t = buf + mlen;
}
sprintf(t, "%s%s ", chan::find_status(msptr, 1), use_id(msptr->client));
sprintf(t, "%s%s ", chan::find_status(msptr, 1), use_id(client));
cur_len += tlen;
t += tlen;
}
if (rb_dlink_list_length(&chptr->members) > 0)
if (!empty(chptr->members))
{
/* remove trailing space */
*(t-1) = '\0';

View file

@ -1473,11 +1473,10 @@ change_nick_user_host(struct Client *target_p, const char *nick, const char *use
{
rb_dlink_node *ptr;
chan::chan *chptr;
chan::membership *mscptr;
int changed = irccmp(target_p->name, nick);
int changed_case = strcmp(target_p->name, nick);
int do_qjm = irccmp(target_p->username, user) || irccmp(target_p->host, host);
char mode[10], modeval[NICKLEN * 2 + 2], reason[256], *mptr;
char mode[10], modeval[NICKLEN * 2 + 2], reason[256];
va_list ap;
modeval[0] = '\0';
@ -1499,20 +1498,20 @@ change_nick_user_host(struct Client *target_p, const char *nick, const char *use
target_p->name, target_p->username, target_p->host,
reason);
RB_DLINK_FOREACH(ptr, target_p->user->channel.head)
for(const auto &pit : target_p->user->channel)
{
mscptr = (chan::membership *)ptr->data;
chptr = mscptr->chan;
mptr = mode;
auto &chan(*pit.first);
auto &member(*pit.second);
char *mptr(mode);
if(is_chanop(mscptr))
if(is_chanop(member))
{
*mptr++ = 'o';
strcat(modeval, nick);
strcat(modeval, " ");
}
if(is_voiced(mscptr))
if(is_voiced(member))
{
*mptr++ = 'v';
strcat(modeval, nick);
@ -1520,16 +1519,16 @@ change_nick_user_host(struct Client *target_p, const char *nick, const char *use
*mptr = '\0';
sendto_channel_local_with_capability_butone(target_p, chan::ALL_MEMBERS, NOCAPS, CLICAP_EXTENDED_JOIN | CLICAP_CHGHOST, chptr,
":%s!%s@%s JOIN %s", nick, user, host, chptr->name.c_str());
sendto_channel_local_with_capability_butone(target_p, chan::ALL_MEMBERS, CLICAP_EXTENDED_JOIN, CLICAP_CHGHOST, chptr,
":%s!%s@%s JOIN %s %s :%s", nick, user, host, chptr->name.c_str(),
sendto_channel_local_with_capability_butone(target_p, chan::ALL_MEMBERS, NOCAPS, CLICAP_EXTENDED_JOIN | CLICAP_CHGHOST, &chan,
":%s!%s@%s JOIN %s", nick, user, host, chan.name.c_str());
sendto_channel_local_with_capability_butone(target_p, chan::ALL_MEMBERS, CLICAP_EXTENDED_JOIN, CLICAP_CHGHOST, &chan,
":%s!%s@%s JOIN %s %s :%s", nick, user, host, chan.name.c_str(),
EmptyString(target_p->user->suser) ? "*" : target_p->user->suser,
target_p->info);
if(*mode)
sendto_channel_local_with_capability_butone(target_p, chan::ALL_MEMBERS, NOCAPS, CLICAP_CHGHOST, chptr,
":%s MODE %s +%s %s", target_p->servptr->name, chptr->name.c_str(), mode, modeval);
sendto_channel_local_with_capability_butone(target_p, chan::ALL_MEMBERS, NOCAPS, CLICAP_CHGHOST, &chan,
":%s MODE %s +%s %s", target_p->servptr->name, chan.name.c_str(), mode, modeval);
*modeval = '\0';
}

View file

@ -485,8 +485,6 @@ sendto_channel_flags(struct Client *one, int type, struct Client *source_p,
va_list args;
buf_head_t rb_linebuf_local;
buf_head_t rb_linebuf_id;
struct Client *target_p;
chan::membership *msptr;
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
int current_capmask = 0;
@ -506,10 +504,10 @@ sendto_channel_flags(struct Client *one, int type, struct Client *source_p,
linebuf_put_msgbuf(&msgbuf, &rb_linebuf_local, NOCAPS, "%s", buf);
rb_linebuf_putmsg(&rb_linebuf_id, NULL, NULL, ":%s %s", use_id(source_p), buf);
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->members.head)
for(const auto &pair : chptr->members.global)
{
msptr = (chan::membership *)ptr->data;
target_p = msptr->client;
auto *const target_p(pair.first);
const auto &member(pair.second);
if(!MyClient(source_p) && (IsIOError(target_p->from) || target_p->from == one))
continue;
@ -517,7 +515,7 @@ sendto_channel_flags(struct Client *one, int type, struct Client *source_p,
if(MyClient(source_p) && !IsCapable(source_p, CLICAP_ECHO_MESSAGE) && target_p == one)
continue;
if(type && ((msptr->flags & type) == 0))
if(type && ((member.flags & type) == 0))
continue;
if(IsDeaf(target_p))
@ -572,8 +570,6 @@ sendto_channel_opmod(struct Client *one, struct Client *source_p,
buf_head_t rb_linebuf_local;
buf_head_t rb_linebuf_old;
buf_head_t rb_linebuf_new;
struct Client *target_p;
chan::membership *msptr;
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
@ -606,10 +602,10 @@ sendto_channel_opmod(struct Client *one, struct Client *source_p,
":%s %s =%s :%s",
use_id(source_p), command, chptr->name.c_str(), text);
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->members.head)
for(const auto &pair : chptr->members.global)
{
msptr = (chan::membership *)ptr->data;
target_p = msptr->client;
auto *const target_p(pair.first);
const auto &member(pair.second);
if(!MyClient(source_p) && (IsIOError(target_p->from) || target_p->from == one))
continue;
@ -617,7 +613,7 @@ sendto_channel_opmod(struct Client *one, struct Client *source_p,
if(MyClient(source_p) && !IsCapable(source_p, CLICAP_ECHO_MESSAGE) && target_p == one)
continue;
if((msptr->flags & chan::CHANOP) == 0)
if((member.flags & chan::CHANOP) == 0)
continue;
if(IsDeaf(target_p))
@ -660,10 +656,6 @@ sendto_channel_local(int type, chan::chan *chptr, const char *pattern, ...)
{
va_list args;
buf_head_t linebuf;
chan::membership *msptr;
struct Client *target_p;
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
rb_linebuf_newbuf(&linebuf);
@ -671,10 +663,10 @@ sendto_channel_local(int type, chan::chan *chptr, const char *pattern, ...)
rb_linebuf_putmsg(&linebuf, pattern, &args, NULL);
va_end(args);
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
for (const auto &pair : chptr->members.global)
{
msptr = (chan::membership *)ptr->data;
target_p = msptr->client;
auto *const target_p(pair.first);
const auto &member(pair.second);
if(IsIOError(target_p))
continue;
@ -684,7 +676,7 @@ sendto_channel_local(int type, chan::chan *chptr, const char *pattern, ...)
if (!IsOper(target_p))
continue;
}
else if(type && ((msptr->flags & type) == 0))
else if(type && ((member.flags & type) == 0))
continue;
_send_linebuf(target_p, &linebuf);
@ -703,18 +695,13 @@ _sendto_channel_local_with_capability_butone(struct Client *one, int type, int c
const char *pattern, va_list * args)
{
buf_head_t linebuf;
chan::membership *msptr;
struct Client *target_p;
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
rb_linebuf_newbuf(&linebuf);
rb_linebuf_putmsg(&linebuf, pattern, args, NULL);
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
for(const auto &member : chptr->members.local)
{
msptr = (chan::membership *)ptr->data;
target_p = msptr->client;
const auto target_p(member->git->first);
if (target_p == one)
continue;
@ -724,7 +711,7 @@ _sendto_channel_local_with_capability_butone(struct Client *one, int type, int c
!NotCapable(target_p, negcaps))
continue;
if(type && ((msptr->flags & type) == 0))
if(type && ((member->flags & type) == 0))
continue;
_send_linebuf(target_p, &linebuf);
@ -780,8 +767,6 @@ sendto_channel_local_butone(struct Client *one, int type, chan::chan *chptr, con
{
va_list args;
buf_head_t linebuf;
chan::membership *msptr;
struct Client *target_p;
struct MsgBuf msgbuf;
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
@ -794,10 +779,9 @@ sendto_channel_local_butone(struct Client *one, int type, chan::chan *chptr, con
rb_linebuf_putmsg(&linebuf, pattern, &args, NULL);
va_end(args);
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
for(const auto &member : chptr->members.local)
{
msptr = (chan::membership *)ptr->data;
target_p = msptr->client;
const auto target_p(member->git->first);
if(target_p == one)
continue;
@ -805,7 +789,7 @@ sendto_channel_local_butone(struct Client *one, int type, chan::chan *chptr, con
if(IsIOError(target_p))
continue;
if(type && ((msptr->flags & type) == 0))
if(type && ((member->flags & type) == 0))
continue;
/* attach the present linebuf to the target */
@ -848,15 +832,14 @@ sendto_common_channels_local(struct Client *user, int cap, int negcap, const cha
++current_serial;
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, user->user->channel.head)
for(const auto &pit : user->user->channel)
{
mscptr = (chan::membership *)ptr->data;
chptr = mscptr->chan;
auto &chptr(pit.first);
auto &mscptr(pit.second);
RB_DLINK_FOREACH_SAFE(uptr, next_uptr, chptr->locmembers.head)
for(const auto &msptr : chptr->members.local)
{
msptr = (chan::membership *)uptr->data;
target_p = msptr->client;
const auto target_p(msptr->git->first);
if(IsIOError(target_p) ||
target_p->serial == current_serial ||
@ -915,15 +898,14 @@ sendto_common_channels_local_butone(struct Client *user, int cap, int negcap, co
/* Skip them -- jilles */
user->serial = current_serial;
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, user->user->channel.head)
for(const auto &pit : user->user->channel)
{
mscptr = (membership *)ptr->data;
chptr = mscptr->chan;
auto &chptr(pit.first);
auto &mscptr(pit.second);
RB_DLINK_FOREACH_SAFE(uptr, next_uptr, chptr->locmembers.head)
for(const auto &msptr : chptr->members.local)
{
msptr = (membership *)uptr->data;
target_p = msptr->client;
const auto target_p(msptr->git->first);
if(IsIOError(target_p) ||
target_p->serial == current_serial ||

View file

@ -27,18 +27,18 @@ namespace ircd {
static int add_hashed_target(struct Client *source_p, uint32_t hashv);
chan::chan *
find_allowing_channel(struct Client *source_p, struct Client *target_p)
find_allowing_channel(struct Client *source, struct Client *target)
{
rb_dlink_node *ptr;
chan::membership *msptr;
RB_DLINK_FOREACH(ptr, source_p->user->channel.head)
for(const auto &pit : source->user->channel)
{
msptr = (chan::membership *)ptr->data;
if (is_chanop_voiced(msptr) && is_member(msptr->chan, target_p))
return msptr->chan;
auto &chan(*pit.first);
auto &member(*pit.second);
if (is_chanop_voiced(member) && is_member(chan, *target))
return &chan;
}
return NULL;
return nullptr;
}
int

View file

@ -48,7 +48,7 @@ chm_noctcp_process(hook_data_privmsg_channel *data)
data->approved = ERR_CANNOTSENDTOCHAN;
return;
}
else if (rb_dlink_list_length(&data->chptr->locmembers) > (unsigned)(GlobalSetOptions.floodcount / 2))
else if (local_size(data->chptr->members) > (unsigned)(GlobalSetOptions.floodcount / 2))
data->source_p->large_ctcp_sent = rb_current_time();
}

View file

@ -221,7 +221,7 @@ m_join(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
/* JOIN 0 simply parts all channels the user is in */
if(*name == '0' && !atoi(name))
{
if(source_p->user->channel.head == NULL)
if(source_p->user->channel.empty())
continue;
do_join_0(&me, source_p);
@ -265,10 +265,10 @@ m_join(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
flags = chan::CHANOP;
}
if((rb_dlink_list_length(&source_p->user->channel) >=
if(((source_p->user->channel.size()) >=
(unsigned long) ConfigChannel.max_chans_per_user) &&
(!IsExtendChans(source_p) ||
(rb_dlink_list_length(&source_p->user->channel) >=
(source_p->user->channel.size() >=
(unsigned long) ConfigChannel.max_chans_per_user_large)))
{
sendto_one(source_p, form_str(ERR_TOOMANYCHANNELS),
@ -309,7 +309,7 @@ m_join(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
chan::check_spambot_warning(source_p, name);
/* add the user to the channel */
add_user_to_channel(chptr, source_p, flags);
add(*chptr, *source_p, flags);
if (chptr->mode.join_num &&
rb_current_time() - chptr->join_delta >= chptr->mode.join_time)
{
@ -482,7 +482,7 @@ ms_join(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
if(!is_member(chptr, source_p))
{
add_user_to_channel(chptr, source_p, chan::PEON);
add(*chptr, *source_p, chan::PEON);
if (chptr->mode.join_num &&
rb_current_time() - chptr->join_delta >= chptr->mode.join_time)
{
@ -637,12 +637,11 @@ ms_sjoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
{
chan::membership *msptr;
struct Client *who;
int l = rb_dlink_list_length(&chptr->members);
int l = size(chptr->members);
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
for(const auto &msptr : chptr->members.local)
{
msptr = (chan::membership *)ptr->data;
who = msptr->client;
who = &get_client(*msptr);
sendto_one(who, ":%s KICK %s %s :Net Rider",
me.name, chptr->name.c_str(), who->name);
@ -650,7 +649,7 @@ ms_sjoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
":%s KICK %s %s :Net Rider",
me.id, chptr->name.c_str(),
who->id);
remove_user_from_channel(msptr);
del(*chptr, *who);
if (--l == 0)
break;
}
@ -822,7 +821,7 @@ ms_sjoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
if(!is_member(chptr, target_p))
{
add_user_to_channel(chptr, target_p, fl);
add(*chptr, *target_p, fl);
send_join(*chptr, *target_p);
joins++;
}
@ -953,18 +952,19 @@ do_join_0(struct Client *client_p, struct Client *source_p)
sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s JOIN 0", use_id(source_p));
while((ptr = source_p->user->channel.head))
for(const auto &pit : source_p->user->channel)
{
if(MyConnect(source_p) &&
!IsOper(source_p) && !IsExemptSpambot(source_p))
chan::check_spambot_warning(source_p, NULL);
msptr = (chan::membership *)ptr->data;
chptr = msptr->chan;
auto &msptr(pit.second);
auto &chptr(pit.first);
sendto_channel_local(chan::ALL_MEMBERS, chptr, ":%s!%s@%s PART %s",
source_p->name,
source_p->username, source_p->host, chptr->name.c_str());
remove_user_from_channel(msptr);
del(*chptr, get_client(*msptr));
}
}
@ -1162,7 +1162,6 @@ set_final_mode(chan::modes *mode, chan::modes *oldmode)
static void
remove_our_modes(chan::chan *chptr, struct Client *source_p)
{
chan::membership *msptr;
rb_dlink_node *ptr;
char lmodebuf[chan::mode::BUFLEN];
char *lpara[chan::mode::MAXPARAMS];
@ -1175,14 +1174,15 @@ remove_our_modes(chan::chan *chptr, struct Client *source_p)
for(i = 0; i < chan::mode::MAXPARAMS; i++)
lpara[i] = NULL;
RB_DLINK_FOREACH(ptr, chptr->members.head)
for(auto &pit : chptr->members.global)
{
msptr = (chan::membership *)ptr->data;
auto &client(pit.first);
auto &msptr(pit.second);
if(is_chanop(msptr))
{
msptr->flags &= ~chan::CHANOP;
lpara[count++] = msptr->client->name;
msptr.flags &= ~chan::CHANOP;
lpara[count++] = client->name;
*mbuf++ = 'o';
/* +ov, might not fit so check. */
@ -1206,15 +1206,15 @@ remove_our_modes(chan::chan *chptr, struct Client *source_p)
lpara[i] = NULL;
}
msptr->flags &= ~chan::VOICE;
lpara[count++] = msptr->client->name;
msptr.flags &= ~chan::VOICE;
lpara[count++] = client->name;
*mbuf++ = 'v';
}
}
else if(is_voiced(msptr))
{
msptr->flags &= ~chan::VOICE;
lpara[count++] = msptr->client->name;
msptr.flags &= ~chan::VOICE;
lpara[count++] = client->name;
*mbuf++ = 'v';
}
else

View file

@ -75,7 +75,7 @@ m_kick(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
if(!IsServer(source_p))
{
msptr = find_channel_membership(chptr, source_p);
msptr = get(chptr->members, *source_p, std::nothrow);
if((msptr == NULL) && MyConnect(source_p))
{
@ -114,7 +114,7 @@ m_kick(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
return;
}
msptr = find_channel_membership(chptr, who);
msptr = get(chptr->members, *who, std::nothrow);
if(msptr != NULL)
{
@ -168,7 +168,8 @@ m_kick(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
":%s KICK %s %s :%s",
use_id(source_p), chptr->name.c_str(), use_id(who), comment);
remove_user_from_channel(msptr);
del(*chptr, *who);
}
else if (MyClient(source_p))
sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,

View file

@ -336,7 +336,7 @@ build_target_list(enum message_type msgtype, struct Client *client_p,
{
chan::membership *msptr;
msptr = find_channel_membership(chptr, source_p);
msptr = get(chptr->members, *source_p, std::nothrow);
if(!IsServer(source_p) && !IsService(source_p) && !is_chanop_voiced(msptr))
{

View file

@ -120,7 +120,7 @@ m_mode(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
}
else
{
msptr = find_channel_membership(chptr, source_p);
msptr = get(chptr->members, *source_p, std::nothrow);
/* Finish the flood grace period... */
if(MyClient(source_p) && !IsFloodDone(source_p))
@ -182,7 +182,7 @@ ms_tmode(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
}
else
{
msptr = find_channel_membership(chptr, source_p);
msptr = get(chptr->members, *source_p, std::nothrow);
set_channel_mode(client_p, source_p, chptr, msptr, parc - 3, parv + 3);
}

View file

@ -95,7 +95,7 @@ part_one_client(struct Client *client_p, struct Client *source_p, char *name, co
return;
}
msptr = find_channel_membership(chptr, source_p);
msptr = get(chptr->members, *source_p, std::nothrow);
if(msptr == NULL)
{
sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), name);
@ -145,7 +145,7 @@ part_one_client(struct Client *client_p, struct Client *source_p, char *name, co
chptr->name.c_str());
}
remove_user_from_channel(msptr);
del(*chptr, *source_p);
}
/*

View file

@ -212,7 +212,6 @@ m_chantrace(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sou
{
struct Client *target_p;
chan::chan *chptr;
chan::membership *msptr;
const char *sockhost;
const char *name;
rb_dlink_node *ptr;
@ -251,10 +250,10 @@ m_chantrace(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sou
return;
}
RB_DLINK_FOREACH(ptr, chptr->members.head)
for(const auto &pit : chptr->members.global)
{
msptr = (chan::membership *)ptr->data;
target_p = msptr->client;
auto &target_p(pit.first);
auto &member(pit.second);
if(EmptyString(target_p->sockhost))
sockhost = empty_sockhost;

View file

@ -112,7 +112,7 @@ m_invite(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
return;
}
msptr = find_channel_membership(chptr, source_p);
msptr = get(chptr->members, *source_p, std::nothrow);
if(MyClient(source_p) && (msptr == NULL))
{
sendto_one_numeric(source_p, ERR_NOTONCHANNEL,

View file

@ -98,7 +98,7 @@ m_knock(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
if(!((chptr->mode.mode & chan::mode::INVITEONLY) || (*chptr->mode.key) ||
(chptr->mode.limit &&
rb_dlink_list_length(&chptr->members) >= (unsigned long)chptr->mode.limit)))
size(chptr->members) >= (unsigned long)chptr->mode.limit)))
{
sendto_one_numeric(source_p, ERR_CHANOPEN,
form_str(ERR_CHANOPEN), name);

View file

@ -291,7 +291,7 @@ static void list_one_channel(struct Client *source_p, chan::chan *chptr,
strip_colour(topic);
sendto_one(source_p, form_str(RPL_LIST), me.name, source_p->name,
visible ? "" : "!",
chptr->name.c_str(), rb_dlink_list_length(&chptr->members),
chptr->name.c_str(), size(chptr->members),
topic);
}
@ -422,8 +422,7 @@ static void safelist_one_channel(struct Client *source_p, chan::chan *chptr, str
if (!visible && !params->operspy)
return;
if ((unsigned int)chptr->members.length < params->users_min
|| (unsigned int)chptr->members.length > params->users_max)
if (size(chptr->members) < params->users_min || size(chptr->members) > params->users_max)
return;
if (params->topic_min && chptr->topic.time < params->topic_min)

View file

@ -113,7 +113,6 @@ names_global(struct Client *source_p)
rb_dlink_node *lp, *ptr;
struct Client *target_p;
chan::chan *chptr = NULL;
chan::membership *msptr;
char buf[BUFSIZE];
char *t;
@ -143,10 +142,9 @@ names_global(struct Client *source_p)
* both were missed out above. if the target is on a
* common channel with source, its already been shown.
*/
RB_DLINK_FOREACH(lp, target_p->user->channel.head)
for(const auto &pit : target_p->user->channel)
{
msptr = (chan::membership *)lp->data;
chptr = msptr->chan;
auto &chptr(pit.first);
if(is_public(chptr) || is_member(chptr, source_p) || is_secret(chptr))
{

View file

@ -1336,7 +1336,7 @@ stats_memory (struct Client *source_p)
{
users_counted++;
users_invited_count += target_p->user->invited.size();
user_channels += rb_dlink_list_length(&target_p->user->channel);
user_channels += target_p->user->channel.size();
if(target_p->user->away)
{
aways_counted++;
@ -1352,7 +1352,7 @@ stats_memory (struct Client *source_p)
channel_count++;
channel_memory += (strlen(chptr->name.c_str()) + sizeof(chan::chan));
channel_users += rb_dlink_list_length(&chptr->members);
channel_users += size(chptr->members);
channel_invites += chptr->invites.size();
channel_bans += size(*chptr, chan::mode::BAN);

View file

@ -85,7 +85,7 @@ m_topic(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
/* setting topic */
if(parc > 2)
{
msptr = find_channel_membership(chptr, source_p);
msptr = get(chptr->members, *source_p, std::nothrow);
if(msptr == NULL)
{

View file

@ -54,7 +54,7 @@ static void do_who_on_channel(struct Client *source_p, chan::chan *chptr,
struct who_format *fmt);
static void who_global(struct Client *source_p, const char *mask, int server_oper, int operspy, struct who_format *fmt);
static void do_who(struct Client *source_p,
struct Client *target_p, chan::membership *msptr,
struct Client *target_p, chan::chan *, chan::membership *msptr,
struct who_format *fmt);
struct Message who_msgtab = {
@ -144,10 +144,10 @@ m_who(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p,
if(source_p->user == NULL)
return;
if((lp = source_p->user->channel.head) != NULL)
if (!source_p->user->channel.empty())
{
msptr = (chan::membership *)lp->data;
do_who_on_channel(source_p, msptr->chan, server_oper, true, &fmt);
auto *const chan(begin(source_p->user->channel)->first);
do_who_on_channel(source_p, chan, server_oper, true, &fmt);
}
sendto_one(source_p, form_str(RPL_ENDOFWHO),
@ -176,7 +176,7 @@ m_who(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p,
if(chptr != NULL)
{
if (!IsOper(source_p) && !ratelimit_client_who(source_p, rb_dlink_list_length(&chptr->members)/50))
if (!IsOper(source_p) && !ratelimit_client_who(source_p, size(chptr->members)/50))
{
sendto_one(source_p, form_str(RPL_LOAD2HI),
me.name, source_p->name, "WHO");
@ -207,27 +207,27 @@ m_who(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p,
int isinvis = 0;
isinvis = IsInvisible(target_p);
RB_DLINK_FOREACH(lp, target_p->user->channel.head)
for(const auto &pit : target_p->user->channel)
{
msptr = (chan::membership *)lp->data;
chptr = msptr->chan;
member = is_member(chptr, source_p);
chptr = pit.first;
msptr = get(chptr->members, *source_p, std::nothrow);
if(isinvis && !member)
{
msptr = nullptr;
continue;
}
if(member || (!isinvis && is_public(chptr)))
break;
msptr = nullptr;
}
/* if we stopped midlist, lp->data is the membership for
/* if we stopped midlist, msptr is the membership for
* target_p of chptr
*/
if(lp != NULL)
do_who(source_p, target_p, (chan::membership *)lp->data, &fmt);
else
do_who(source_p, target_p, NULL, &fmt);
do_who(source_p, target_p, chptr, msptr, &fmt);
sendto_one(source_p, form_str(RPL_ENDOFWHO),
me.name, source_p->name, mask);
@ -286,32 +286,28 @@ who_common_channel(struct Client *source_p, chan::chan *chptr,
const char *mask, int server_oper, int *maxmatches,
struct who_format *fmt)
{
chan::membership *msptr;
struct Client *target_p;
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, chptr->members.head)
for(const auto &pit : chptr->members.global)
{
msptr = (chan::membership *)ptr->data;
target_p = msptr->client;
const auto &target(pit.first);
const auto &member(pit.second);
if(!IsInvisible(target_p) || IsMarked(target_p))
if(!IsInvisible(target) || IsMarked(target))
continue;
if(server_oper && !IsOper(target_p))
if(server_oper && !IsOper(target))
continue;
SetMark(target_p);
SetMark(target);
if(*maxmatches > 0)
{
if((mask == NULL) ||
match(mask, target_p->name) || match(mask, target_p->username) ||
match(mask, target_p->host) || match(mask, target_p->servptr->name) ||
(IsOper(source_p) && match(mask, target_p->orighost)) ||
match(mask, target_p->info))
match(mask, target->name) || match(mask, target->username) ||
match(mask, target->host) || match(mask, target->servptr->name) ||
(IsOper(source_p) && match(mask, target->orighost)) ||
match(mask, target->info))
{
do_who(source_p, target_p, NULL, fmt);
do_who(source_p, target, chptr, nullptr, fmt);
--(*maxmatches);
}
}
@ -345,10 +341,10 @@ who_global(struct Client *source_p, const char *mask, int server_oper, int opers
*/
if(!operspy)
{
RB_DLINK_FOREACH(lp, source_p->user->channel.head)
for(const auto &pit : source_p->user->channel)
{
msptr = (chan::membership *)lp->data;
who_common_channel(source_p, msptr->chan, mask, server_oper, &maxmatches, fmt);
auto &chan(pit.first);
who_common_channel(source_p, chan, mask, server_oper, &maxmatches, fmt);
}
}
else if (!ConfigFileEntry.operspy_dont_care_user_info)
@ -382,7 +378,7 @@ who_global(struct Client *source_p, const char *mask, int server_oper, int opers
(IsOper(source_p) && match(mask, target_p->orighost)) ||
match(mask, target_p->info))
{
do_who(source_p, target_p, NULL, fmt);
do_who(source_p, target_p, nullptr, nullptr, fmt);
--maxmatches;
}
}
@ -408,22 +404,18 @@ who_global(struct Client *source_p, const char *mask, int server_oper, int opers
*/
static void
do_who_on_channel(struct Client *source_p, chan::chan *chptr,
int server_oper, int member, struct who_format *fmt)
int server_oper, int source_member, struct who_format *fmt)
{
struct Client *target_p;
chan::membership *msptr;
rb_dlink_node *ptr;
RB_DLINK_FOREACH(ptr, chptr->members.head)
for(auto &pit : chptr->members.global)
{
msptr = (chan::membership *)ptr->data;
target_p = msptr->client;
const auto &target(pit.first);
auto &member(pit.second);
if(server_oper && !IsOper(target_p))
if(server_oper && !IsOper(target))
continue;
if(member || !IsInvisible(target_p))
do_who(source_p, target_p, msptr, fmt);
if(source_member || !IsInvisible(target))
do_who(source_p, target, chptr, &member, fmt);
}
}
@ -464,7 +456,7 @@ append_format(char *buf, size_t bufsize, size_t *pos, const char *fmt, ...)
*/
static void
do_who(struct Client *source_p, struct Client *target_p, chan::membership *msptr, struct who_format *fmt)
do_who(struct Client *source_p, struct Client *target_p, chan::chan *chan, chan::membership *msptr, struct who_format *fmt)
{
char status[16];
char str[510 + 1]; /* linebuf.c will add \r\n */
@ -476,7 +468,7 @@ do_who(struct Client *source_p, struct Client *target_p, chan::membership *msptr
if (fmt->fields == 0)
sendto_one(source_p, form_str(RPL_WHOREPLY), me.name,
source_p->name, msptr ? msptr->chan->name.c_str() : "*",
source_p->name, msptr ? chan->name.c_str() : "*",
target_p->username, target_p->host,
target_p->servptr->name, target_p->name, status,
ConfigServerHide.flatten_links && !IsOper(source_p) && !IsExemptShide(source_p) ? 0 : target_p->hopcount,
@ -490,7 +482,7 @@ do_who(struct Client *source_p, struct Client *target_p, chan::membership *msptr
if (fmt->fields & FIELD_QUERYTYPE)
append_format(str, sizeof str, &pos, " %s", fmt->querytype);
if (fmt->fields & FIELD_CHANNEL)
append_format(str, sizeof str, &pos, " %s", msptr? msptr->chan->name.c_str() : "*");
append_format(str, sizeof str, &pos, " %s", msptr? name(*chan).c_str() : "*");
if (fmt->fields & FIELD_USER)
append_format(str, sizeof str, &pos, " %s", target_p->username);
if (fmt->fields & FIELD_IP)

View file

@ -252,10 +252,10 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy)
if (!IsService(target_p))
{
RB_DLINK_FOREACH(ptr, target_p->user->channel.head)
for(const auto &pit : target_p->user->channel)
{
msptr = (chan::membership *)ptr->data;
chptr = msptr->chan;
auto &chptr(pit.first);
auto &msptr(pit.second);
hdata.chptr = chptr;