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:
parent
afba2488ec
commit
de7cf7e009
9 changed files with 93 additions and 72 deletions
|
@ -167,6 +167,8 @@ struct Client
|
||||||
struct LocalUser
|
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
|
* The following fields are allocated only for local clients
|
||||||
* (directly connected to *this* server with a socket.
|
* (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 next_away; /* Don't allow next away before... */
|
||||||
time_t last;
|
time_t last;
|
||||||
uint32_t connid;
|
|
||||||
|
|
||||||
/* clients allowed to talk through +g */
|
/* clients allowed to talk through +g */
|
||||||
rb_dlink_list allow_list;
|
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 *ssl_ctl; /* which ssl daemon we're associate with */
|
||||||
struct _ssl_ctl *z_ctl; /* second ctl for ssl+zlib */
|
struct _ssl_ctl *z_ctl; /* second ctl for ssl+zlib */
|
||||||
uint32_t zconnid;
|
|
||||||
uint32_t localflags;
|
uint32_t localflags;
|
||||||
struct ZipStats *zipstats; /* zipstats */
|
struct ZipStats *zipstats; /* zipstats */
|
||||||
uint16_t cork_count; /* used for corking/uncorking connections */
|
uint16_t cork_count; /* used for corking/uncorking connections */
|
||||||
|
@ -605,4 +605,8 @@ extern char *generate_uid(void);
|
||||||
void allocate_away(struct Client *);
|
void allocate_away(struct Client *);
|
||||||
void free_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 */
|
#endif /* INCLUDED_client_h */
|
||||||
|
|
|
@ -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 struct ConfItem *hash_find_resv(const char *name);
|
||||||
extern void clear_resv_hash(void);
|
extern void clear_resv_hash(void);
|
||||||
|
|
||||||
void add_to_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(struct Client *client_p);
|
void del_from_cli_connid_hash(uint32_t id);
|
||||||
struct Client *find_cli_connid_hash(uint32_t connid);
|
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 */
|
#endif /* INCLUDED_hash_h */
|
||||||
|
|
|
@ -76,7 +76,7 @@ static rb_bh *pclient_heap = NULL;
|
||||||
static rb_bh *user_heap = NULL;
|
static rb_bh *user_heap = NULL;
|
||||||
static rb_bh *away_heap = NULL;
|
static rb_bh *away_heap = NULL;
|
||||||
static char current_uid[IDLEN];
|
static char current_uid[IDLEN];
|
||||||
static int32_t current_connid = 0;
|
static uint32_t current_connid = 0;
|
||||||
|
|
||||||
rb_dictionary *nd_dict = NULL;
|
rb_dictionary *nd_dict = NULL;
|
||||||
|
|
||||||
|
@ -129,6 +129,78 @@ init_client(void)
|
||||||
nd_dict = rb_dictionary_create("nickdelay", irccmp);
|
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.
|
* 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;
|
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);
|
client_p->preClient = rb_bh_alloc(pclient_heap);
|
||||||
|
|
||||||
/* as good a place as any... */
|
/* as good a place as any... */
|
||||||
|
@ -229,7 +290,7 @@ free_local_client(struct Client *client_p)
|
||||||
client_p->localClient->listener = 0;
|
client_p->localClient->listener = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
del_from_cli_connid_hash(client_p);
|
client_release_connids(client_p);
|
||||||
if(client_p->localClient->F != NULL)
|
if(client_p->localClient->F != NULL)
|
||||||
{
|
{
|
||||||
rb_close(client_p->localClient->F);
|
rb_close(client_p->localClient->F);
|
||||||
|
@ -1949,7 +2010,7 @@ close_connection(struct Client *client_p)
|
||||||
else
|
else
|
||||||
ServerStats.is_ni++;
|
ServerStats.is_ni++;
|
||||||
|
|
||||||
del_from_cli_connid_hash(client_p);
|
client_release_connids(client_p);
|
||||||
|
|
||||||
if(client_p->localClient->F != NULL)
|
if(client_p->localClient->F != NULL)
|
||||||
{
|
{
|
||||||
|
|
34
ircd/hash.c
34
ircd/hash.c
|
@ -40,7 +40,6 @@
|
||||||
#include "rb_radixtree.h"
|
#include "rb_radixtree.h"
|
||||||
|
|
||||||
rb_dictionary *client_connid_tree = NULL;
|
rb_dictionary *client_connid_tree = NULL;
|
||||||
rb_dictionary *client_zconnid_tree = NULL;
|
|
||||||
rb_radixtree *client_id_tree = NULL;
|
rb_radixtree *client_id_tree = NULL;
|
||||||
rb_radixtree *client_name_tree = NULL;
|
rb_radixtree *client_name_tree = NULL;
|
||||||
|
|
||||||
|
@ -60,7 +59,6 @@ void
|
||||||
init_hash(void)
|
init_hash(void)
|
||||||
{
|
{
|
||||||
client_connid_tree = rb_dictionary_create("client connid", rb_uint32cmp);
|
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_id_tree = rb_radixtree_create("client id", NULL);
|
||||||
client_name_tree = rb_radixtree_create("client name", irccasecanon);
|
client_name_tree = rb_radixtree_create("client name", irccasecanon);
|
||||||
|
|
||||||
|
@ -493,41 +491,19 @@ clear_resv_hash(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
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));
|
rb_dictionary_delete(client_connid_tree, RB_UINT_TO_POINTER(id));
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Client *
|
struct Client *
|
||||||
find_cli_connid_hash(uint32_t connid)
|
find_cli_connid_hash(uint32_t connid)
|
||||||
{
|
{
|
||||||
struct Client *target_p;
|
return rb_dictionary_retrieve(client_connid_tree, RB_UINT_TO_POINTER(connid));
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -481,7 +481,7 @@ add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, str
|
||||||
free_client(new_client);
|
free_client(new_client);
|
||||||
return;
|
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)
|
if(new_client->localClient->ssl_ctl == NULL)
|
||||||
{
|
{
|
||||||
free_client(new_client);
|
free_client(new_client);
|
||||||
|
|
|
@ -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->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)
|
if(!client_p->localClient->ssl_ctl)
|
||||||
{
|
{
|
||||||
serv_connect_callback(client_p->localClient->F, RB_ERROR, data);
|
serv_connect_callback(client_p->localClient->F, RB_ERROR, data);
|
||||||
|
|
|
@ -863,23 +863,11 @@ start_zlib_session(void *data)
|
||||||
return;
|
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[0] = server->localClient->F;
|
||||||
F[1] = xF1;
|
F[1] = xF1;
|
||||||
del_from_zconnid_hash(server);
|
|
||||||
server->localClient->F = xF2;
|
server->localClient->F = xF2;
|
||||||
/* need to redo as what we did before isn't valid now */
|
/* need to redo as what we did before isn't valid now */
|
||||||
uint32_to_buf(&buf[1], server->localClient->zconnid);
|
uint32_to_buf(&buf[1], connid_get(server));
|
||||||
add_to_zconnid_hash(server);
|
|
||||||
|
|
||||||
server->localClient->z_ctl = which_ssld();
|
server->localClient->z_ctl = which_ssld();
|
||||||
if(!server->localClient->z_ctl)
|
if(!server->localClient->z_ctl)
|
||||||
|
|
|
@ -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));
|
sendto_one_numeric(client_p, RPL_STARTTLS, form_str(RPL_STARTTLS));
|
||||||
send_queued(client_p);
|
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)
|
if (ctl != NULL)
|
||||||
{
|
{
|
||||||
client_p->localClient->F = F[0];
|
client_p->localClient->F = F[0];
|
||||||
|
|
|
@ -1067,11 +1067,6 @@ mod_process_cmd_recv(mod_ctl_t * ctl)
|
||||||
process_stats(ctl, ctl_buf);
|
process_stats(ctl, ctl_buf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'Y':
|
|
||||||
{
|
|
||||||
change_connid(ctl, ctl_buf);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
case 'Z':
|
case 'Z':
|
||||||
|
|
Loading…
Reference in a new issue