diff --git a/include/client.h b/include/client.h index f844aac7..b9a612bf 100644 --- a/include/client.h +++ b/include/client.h @@ -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 */ diff --git a/include/hash.h b/include/hash.h index c2d220db..aa0ef79e 100644 --- a/include/hash.h +++ b/include/hash.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 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 */ diff --git a/ircd/client.c b/ircd/client.c index f411848b..268f61b2 100644 --- a/ircd/client.c +++ b/ircd/client.c @@ -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) { diff --git a/ircd/hash.c b/ircd/hash.c index 172734d3..0d3fb128 100644 --- a/ircd/hash.c +++ b/ircd/hash.c @@ -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)); } diff --git a/ircd/listener.c b/ircd/listener.c index a3d08cba..aeff94e9 100644 --- a/ircd/listener.c +++ b/ircd/listener.c @@ -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); diff --git a/ircd/s_serv.c b/ircd/s_serv.c index 619ab51f..79a0a487 100644 --- a/ircd/s_serv.c +++ b/ircd/s_serv.c @@ -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); diff --git a/ircd/sslproc.c b/ircd/sslproc.c index 2edd091e..709504ac 100644 --- a/ircd/sslproc.c +++ b/ircd/sslproc.c @@ -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) diff --git a/modules/m_starttls.c b/modules/m_starttls.c index f49abb46..62b7feb6 100644 --- a/modules/m_starttls.c +++ b/modules/m_starttls.c @@ -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]; diff --git a/ssld/ssld.c b/ssld/ssld.c index 7a0dc20f..6eb942c2 100644 --- a/ssld/ssld.c +++ b/ssld/ssld.c @@ -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':