ircd: client: substantially rework the connid registry system

now connid's are allocated on demand and clients may have as many connid's as necessary.
this allows us to build chains of helpers while ensuring the ircd properly tracks and GCs the resources.
This commit is contained in:
William Pitcock 2016-03-25 19:49:01 -05:00
parent afba2488ec
commit de7cf7e009
9 changed files with 93 additions and 72 deletions

View File

@ -166,7 +166,9 @@ struct Client
struct LocalUser
{
rb_dlink_node tnode; /* This is the node for the local list type the client is on*/
rb_dlink_node tnode; /* This is the node for the local list type the client is on */
rb_dlink_list connids; /* This is the list of connids to free */
/*
* The following fields are allocated only for local clients
* (directly connected to *this* server with a socket.
@ -233,7 +235,6 @@ struct LocalUser
time_t next_away; /* Don't allow next away before... */
time_t last;
uint32_t connid;
/* clients allowed to talk through +g */
rb_dlink_list allow_list;
@ -272,7 +273,6 @@ struct LocalUser
struct _ssl_ctl *ssl_ctl; /* which ssl daemon we're associate with */
struct _ssl_ctl *z_ctl; /* second ctl for ssl+zlib */
uint32_t zconnid;
uint32_t localflags;
struct ZipStats *zipstats; /* zipstats */
uint16_t cork_count; /* used for corking/uncorking connections */
@ -605,4 +605,8 @@ extern char *generate_uid(void);
void allocate_away(struct Client *);
void free_away(struct Client *);
uint32_t connid_get(struct Client *client_p);
void connid_put(uint32_t id);
void client_release_connids(struct Client *client_p);
#endif /* INCLUDED_client_h */

View File

@ -95,11 +95,8 @@ extern void del_from_resv_hash(const char *name, struct ConfItem *aconf);
extern struct ConfItem *hash_find_resv(const char *name);
extern void clear_resv_hash(void);
void add_to_cli_connid_hash(struct Client *client_p);
void del_from_cli_connid_hash(struct Client *client_p);
void add_to_cli_connid_hash(struct Client *client_p, uint32_t id);
void del_from_cli_connid_hash(uint32_t id);
struct Client *find_cli_connid_hash(uint32_t connid);
void add_to_zconnid_hash(struct Client *client_p);
void del_from_zconnid_hash(struct Client *client_p);
#endif /* INCLUDED_hash_h */

View File

@ -76,7 +76,7 @@ static rb_bh *pclient_heap = NULL;
static rb_bh *user_heap = NULL;
static rb_bh *away_heap = NULL;
static char current_uid[IDLEN];
static int32_t current_connid = 0;
static uint32_t current_connid = 0;
rb_dictionary *nd_dict = NULL;
@ -129,6 +129,78 @@ init_client(void)
nd_dict = rb_dictionary_create("nickdelay", irccmp);
}
/*
* connid_get - allocate a connid
*
* inputs - none
* outputs - a connid token which is used to represent a logical circuit
* side effects - current_connid is incremented, possibly multiple times.
* the association of the connid to it's client is committed.
*/
uint32_t
connid_get(struct Client *client_p)
{
s_assert(MyClient(client_p));
if (!MyClient(client_p))
return 0;
/* find a connid that is available */
while (find_cli_connid_hash(++current_connid) != NULL)
{
/* handle wraparound, current_connid must NEVER be 0 */
if (current_connid == 0)
++current_connid;
}
add_to_cli_connid_hash(client_p, current_connid);
rb_dlinkAddAlloc(RB_UINT_TO_POINTER(current_connid), &client_p->localClient->connids);
return current_connid;
}
/*
* connid_put - free a connid
*
* inputs - connid to free
* outputs - nothing
* side effects - connid bookkeeping structures are freed
*/
void
connid_put(uint32_t id)
{
struct Client *client_p;
s_assert(id != 0);
if (id == 0)
return;
client_p = find_cli_connid_hash(id);
if (client_p == NULL)
return;
del_from_cli_connid_hash(id);
rb_dlinkFindDestroy(RB_UINT_TO_POINTER(id), &client_p->localClient->connids);
}
/*
* client_release_connids - release any connids still attached to a client
*
* inputs - client to garbage collect
* outputs - none
* side effects - client's connids are garbage collected
*/
void
client_release_connids(struct Client *client_p)
{
rb_dlink_node *ptr, *ptr2;
s_assert(MyClient(client_p));
if (!MyClient(client_p))
return;
RB_DLINK_FOREACH_SAFE(ptr, ptr2, client_p->localClient->connids.head)
connid_put(RB_POINTER_TO_UINT(ptr->data));
}
/*
* make_client - create a new Client struct and set it to initial state.
@ -160,17 +232,6 @@ make_client(struct Client *from)
client_p->localClient->F = NULL;
if(current_connid+1 == 0)
current_connid++;
client_p->localClient->connid = ++current_connid;
if(current_connid+1 == 0)
current_connid++;
client_p->localClient->zconnid = ++current_connid;
add_to_cli_connid_hash(client_p);
client_p->preClient = rb_bh_alloc(pclient_heap);
/* as good a place as any... */
@ -229,7 +290,7 @@ free_local_client(struct Client *client_p)
client_p->localClient->listener = 0;
}
del_from_cli_connid_hash(client_p);
client_release_connids(client_p);
if(client_p->localClient->F != NULL)
{
rb_close(client_p->localClient->F);
@ -1949,7 +2010,7 @@ close_connection(struct Client *client_p)
else
ServerStats.is_ni++;
del_from_cli_connid_hash(client_p);
client_release_connids(client_p);
if(client_p->localClient->F != NULL)
{

View File

@ -40,7 +40,6 @@
#include "rb_radixtree.h"
rb_dictionary *client_connid_tree = NULL;
rb_dictionary *client_zconnid_tree = NULL;
rb_radixtree *client_id_tree = NULL;
rb_radixtree *client_name_tree = NULL;
@ -60,7 +59,6 @@ void
init_hash(void)
{
client_connid_tree = rb_dictionary_create("client connid", rb_uint32cmp);
client_zconnid_tree = rb_dictionary_create("client zconnid", rb_uint32cmp);
client_id_tree = rb_radixtree_create("client id", NULL);
client_name_tree = rb_radixtree_create("client name", irccasecanon);
@ -493,41 +491,19 @@ clear_resv_hash(void)
}
void
add_to_zconnid_hash(struct Client *client_p)
add_to_cli_connid_hash(struct Client *client_p, uint32_t id)
{
rb_dictionary_add(client_zconnid_tree, RB_UINT_TO_POINTER(client_p->localClient->zconnid), client_p);
rb_dictionary_add(client_connid_tree, RB_UINT_TO_POINTER(id), client_p);
}
void
del_from_zconnid_hash(struct Client *client_p)
del_from_cli_connid_hash(uint32_t id)
{
rb_dictionary_delete(client_zconnid_tree, RB_UINT_TO_POINTER(client_p->localClient->zconnid));
}
void
add_to_cli_connid_hash(struct Client *client_p)
{
rb_dictionary_add(client_connid_tree, RB_UINT_TO_POINTER(client_p->localClient->connid), client_p);
}
void
del_from_cli_connid_hash(struct Client *client_p)
{
rb_dictionary_delete(client_connid_tree, RB_UINT_TO_POINTER(client_p->localClient->connid));
rb_dictionary_delete(client_connid_tree, RB_UINT_TO_POINTER(id));
}
struct Client *
find_cli_connid_hash(uint32_t connid)
{
struct Client *target_p;
target_p = rb_dictionary_retrieve(client_connid_tree, RB_UINT_TO_POINTER(connid));
if (target_p != NULL)
return target_p;
target_p = rb_dictionary_retrieve(client_zconnid_tree, RB_UINT_TO_POINTER(connid));
if (target_p != NULL)
return target_p;
return NULL;
return rb_dictionary_retrieve(client_connid_tree, RB_UINT_TO_POINTER(connid));
}

View File

@ -481,7 +481,7 @@ add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, str
free_client(new_client);
return;
}
new_client->localClient->ssl_ctl = start_ssld_accept(F, xF[1], new_client->localClient->connid); /* this will close F for us */
new_client->localClient->ssl_ctl = start_ssld_accept(F, xF[1], connid_get(new_client)); /* this will close F for us */
if(new_client->localClient->ssl_ctl == NULL)
{
free_client(new_client);

View File

@ -1157,7 +1157,7 @@ serv_connect_ssl_callback(rb_fde_t *F, int status, void *data)
}
client_p->localClient->F = xF[0];
client_p->localClient->ssl_ctl = start_ssld_connect(F, xF[1], rb_get_fd(xF[0]));
client_p->localClient->ssl_ctl = start_ssld_connect(F, xF[1], connid_get(client_p));
if(!client_p->localClient->ssl_ctl)
{
serv_connect_callback(client_p->localClient->F, RB_ERROR, data);

View File

@ -863,23 +863,11 @@ start_zlib_session(void *data)
return;
}
if(IsSSL(server))
{
/* tell ssld the new connid for the ssl part*/
buf2[0] = 'Y';
uint32_to_buf(&buf2[1], rb_get_fd(server->localClient->F));
uint32_to_buf(&buf2[5], rb_get_fd(xF2));
ssl_cmd_write_queue(server->localClient->ssl_ctl, NULL, 0, buf2, sizeof(buf2));
}
F[0] = server->localClient->F;
F[1] = xF1;
del_from_zconnid_hash(server);
server->localClient->F = xF2;
/* need to redo as what we did before isn't valid now */
uint32_to_buf(&buf[1], server->localClient->zconnid);
add_to_zconnid_hash(server);
uint32_to_buf(&buf[1], connid_get(server));
server->localClient->z_ctl = which_ssld();
if(!server->localClient->z_ctl)

View File

@ -95,7 +95,7 @@ mr_starttls(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sou
sendto_one_numeric(client_p, RPL_STARTTLS, form_str(RPL_STARTTLS));
send_queued(client_p);
ctl = start_ssld_accept(client_p->localClient->F, F[1], client_p->localClient->connid);
ctl = start_ssld_accept(client_p->localClient->F, F[1], connid_get(client_p));
if (ctl != NULL)
{
client_p->localClient->F = F[0];

View File

@ -1067,11 +1067,6 @@ mod_process_cmd_recv(mod_ctl_t * ctl)
process_stats(ctl, ctl_buf);
break;
}
case 'Y':
{
change_connid(ctl, ctl_buf);
break;
}
#ifdef HAVE_LIBZ
case 'Z':