Revert "LIST: use new sendq system to reimplement SAFELIST differently."

This reverts commit e835592cfc.
This commit is contained in:
William Pitcock 2016-01-20 22:26:55 -05:00
parent 704697b6b6
commit 999fab778c
3 changed files with 148 additions and 30 deletions

View File

@ -71,6 +71,7 @@ struct Server;
struct LocalUser;
struct AuthRequest;
struct PreClient;
struct ListClient;
struct scache_entry;
/*
@ -269,6 +270,8 @@ struct LocalUser
time_t ratelimit;
unsigned int join_who_credits;
struct ListClient *safelist_data;
char *mangledhost; /* non-NULL if host mangling module loaded and
applicable to this client */
@ -299,6 +302,14 @@ struct PreClient
struct rb_sockaddr_storage lip; /* address of our side of the connection */
};
struct ListClient
{
char *chname;
unsigned int users_min, users_max;
time_t created_min, created_max, topic_min, topic_max;
int operspy;
};
/*
* status macros.
*/

View File

@ -34,6 +34,7 @@ extern rb_dlink_list *hostTable;
extern struct Dictionary *nd_dict;
extern struct irc_radixtree *resv_tree;
extern struct irc_radixtree *channel_tree;
/* Magic value for FNV hash functions */
#define FNV1_32_INIT 0x811c9dc5UL

View File

@ -51,6 +51,9 @@
#include "inline/stringops.h"
#include "s_assert.h"
#include "logger.h"
#include "irc_radixtree.h"
static rb_dlink_list safelisting_clients = { NULL, NULL, 0 };
static int _modinit(void);
static void _moddeinit(void);
@ -58,16 +61,14 @@ static void _moddeinit(void);
static int m_list(struct Client *, struct Client *, int, const char **);
static int mo_list(struct Client *, struct Client *, int, const char **);
struct ListOptions
{
unsigned int users_min, users_max;
time_t created_min, created_max, topic_min, topic_max;
int operspy;
};
static void list_one_channel(struct Client *source_p, struct Channel *chptr, int visible);
static void safelist_one_channel(struct Client *source_p, struct Channel *chptr, struct ListOptions *params);
static void safelist_one_channel(struct Client *source_p, struct Channel *chptr, struct ListClient *params);
static void safelist_check_cliexit(hook_data_client_exit * hdata);
static void safelist_client_instantiate(struct Client *, struct ListClient *);
static void safelist_client_release(struct Client *);
static void safelist_iterate_client(struct Client *source_p);
static void safelist_iterate_clients(void *unused);
static void safelist_channel_named(struct Client *source_p, const char *name, int operspy);
struct Message list_msgtab = {
@ -77,10 +78,19 @@ struct Message list_msgtab = {
mapi_clist_av1 list_clist[] = { &list_msgtab, NULL };
DECLARE_MODULE_AV1(list, _modinit, _moddeinit, list_clist, NULL, NULL, "$Revision: 3372 $");
mapi_hfn_list_av1 list_hfnlist[] = {
{"client_exit", (hookfn) safelist_check_cliexit},
{NULL, NULL}
};
DECLARE_MODULE_AV1(list, _modinit, _moddeinit, list_clist, NULL, list_hfnlist, "$Revision: 3372 $");
static struct ev_entry *iterate_clients_ev = NULL;
static int _modinit(void)
{
iterate_clients_ev = rb_event_add("safelist_iterate_clients", safelist_iterate_clients, NULL, 3);
/* ELIST=[tokens]:
*
* M = mask search
@ -97,10 +107,23 @@ static int _modinit(void)
static void _moddeinit(void)
{
rb_event_delete(iterate_clients_ev);
delete_isupport("SAFELIST");
delete_isupport("ELIST");
}
static void safelist_check_cliexit(hook_data_client_exit * hdata)
{
/* Cancel the safelist request if we are disconnecting
* from the server. That way it doesn't core. :P --nenolod
*/
if (MyClient(hdata->target) && hdata->target->localClient->safelist_data != NULL)
{
safelist_client_release(hdata->target);
}
}
/* m_list()
* parv[1] = channel
*
@ -111,6 +134,13 @@ static int m_list(struct Client *client_p, struct Client *source_p, int parc, co
{
static time_t last_used = 0L;
if (source_p->localClient->safelist_data != NULL)
{
sendto_one_notice(source_p, ":/LIST aborted");
safelist_client_release(source_p);
return 0;
}
if (parc < 2 || !IsChannelName(parv[1]))
{
/* pace this due to the sheer traffic involved */
@ -132,16 +162,18 @@ static int m_list(struct Client *client_p, struct Client *source_p, int parc, co
*/
static int mo_list(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
struct ListOptions *params;
struct ListClient *params;
char *p;
char *args = NULL;
int i;
int operspy = 0;
int sendq_limit = get_sendq_hard(client_p);
rb_dlink_node *ptr;
sendq_limit /= 10;
sendq_limit *= 9;
if (source_p->localClient->safelist_data != NULL)
{
sendto_one_notice(source_p, ":/LIST aborted");
safelist_client_release(source_p);
return 0;
}
if (parc > 1)
{
@ -163,7 +195,7 @@ static int mo_list(struct Client *client_p, struct Client *source_p, int parc, c
}
/* Multiple channels, possibly with parameters. */
params = rb_malloc(sizeof(struct ListOptions));
params = rb_malloc(sizeof(struct ListClient));
params->users_min = ConfigChannel.displayed_usercount;
params->users_max = INT_MAX;
@ -253,20 +285,7 @@ static int mo_list(struct Client *client_p, struct Client *source_p, int parc, c
}
}
sendto_one(client_p, form_str(RPL_LISTSTART), me.name, client_p->name);
RB_DLINK_FOREACH(ptr, global_channel_list.head)
{
safelist_one_channel(client_p, ptr->data, params);
if (rb_linebuf_len(&client_p->localClient->buf_sendq) > sendq_limit)
{
sendto_one(source_p, form_str(ERR_TOOMANYMATCHES), me.name, source_p->name, "LIST");
break;
}
}
sendto_one(source_p, form_str(RPL_LISTEND), me.name, source_p->name);
safelist_client_instantiate(source_p, params);
return 0;
}
@ -313,6 +332,59 @@ static int safelist_sendq_exceeded(struct Client *client_p)
return NO;
}
/*
* safelist_client_instantiate()
*
* inputs - pointer to Client to be listed,
* pointer to ListClient for params
* outputs - none
* side effects - the safelist process begins for a
* client.
*
* Please do not ever call this on a non-local client.
* If you do, you will get SIGSEGV.
*/
static void safelist_client_instantiate(struct Client *client_p, struct ListClient *params)
{
s_assert(MyClient(client_p));
s_assert(params != NULL);
client_p->localClient->safelist_data = params;
sendto_one(client_p, form_str(RPL_LISTSTART), me.name, client_p->name);
/* pop the client onto the queue for processing */
rb_dlinkAddAlloc(client_p, &safelisting_clients);
/* give the user some initial data to work with */
safelist_iterate_client(client_p);
}
/*
* safelist_client_release()
*
* inputs - pointer to Client being listed on
* outputs - none
* side effects - the client is no longer being
* listed
*
* Please do not ever call this on a non-local client.
* If you do, you will get SIGSEGV.
*/
static void safelist_client_release(struct Client *client_p)
{
s_assert(MyClient(client_p));
rb_dlinkFindDestroy(client_p, &safelisting_clients);
rb_free(client_p->localClient->safelist_data->chname);
rb_free(client_p->localClient->safelist_data);
client_p->localClient->safelist_data = NULL;
sendto_one(client_p, form_str(RPL_LISTEND), me.name, client_p->name);
}
/*
* safelist_channel_named()
*
@ -363,7 +435,7 @@ static void safelist_channel_named(struct Client *source_p, const char *name, in
* side effects - a channel is listed if it meets the
* requirements
*/
static void safelist_one_channel(struct Client *source_p, struct Channel *chptr, struct ListOptions *params)
static void safelist_one_channel(struct Client *source_p, struct Channel *chptr, struct ListClient *params)
{
int visible;
@ -391,3 +463,37 @@ static void safelist_one_channel(struct Client *source_p, struct Channel *chptr,
list_one_channel(source_p, chptr, visible);
}
/*
* safelist_iterate_client()
*
* inputs - client pointer
* outputs - none
* side effects - the client's sendq is filled up again
*/
static void safelist_iterate_client(struct Client *source_p)
{
struct Channel *chptr;
struct irc_radixtree_iteration_state iter;
IRC_RADIXTREE_FOREACH_FROM(chptr, &iter, channel_tree, source_p->localClient->safelist_data->chname)
{
if (safelist_sendq_exceeded(source_p->from) == YES)
{
source_p->localClient->safelist_data->chname = rb_strdup(chptr->chname);
return;
}
safelist_one_channel(source_p, chptr, source_p->localClient->safelist_data);
}
safelist_client_release(source_p);
}
static void safelist_iterate_clients(void *unused)
{
rb_dlink_node *n, *n2;
RB_DLINK_FOREACH_SAFE(n, n2, safelisting_clients.head)
safelist_iterate_client((struct Client *)n->data);
}