From: Skywing Date: Sat, 13 Dec 2008 21:27:48 +0000 (-0500) Subject: Don't decrement my_clients when killing or expiring a detached client. X-Git-Tag: silc.toolkit.1.1.9~4^2 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=6e596af78adee828595e00a0988625453f9ecbc9 Don't decrement my_clients when killing or expiring a detached client. This prevents my_clients from getting out of sync when a detached client is forcibly removed, fixing a regression. --- diff --git a/apps/silcd/command.c b/apps/silcd/command.c index f68edccd..9c1fc4e2 100644 --- a/apps/silcd/command.c +++ b/apps/silcd/command.c @@ -4082,6 +4082,9 @@ SILC_TASK_CALLBACK(silc_server_command_detach_cb) client->connection = NULL; silc_server_close_connection(server, sock); + /* Mark the client as locally detached. */ + client->local_detached = TRUE; + /* * Decrement the user count; we'll increment it if the user resumes on our * server. diff --git a/apps/silcd/idlist.h b/apps/silcd/idlist.h index 7b9c2ad1..0112db07 100644 --- a/apps/silcd/idlist.h +++ b/apps/silcd/idlist.h @@ -310,6 +310,13 @@ typedef struct SilcChannelClientEntryStruct { this command identifier and handle the process after the resolving is over. + SilcClientEntry resuming_client + + unsigned locally_detached : 1 + + Set to indicate that the client is locally owned but detached for + purposes of tracking user counts. + */ struct SilcClientEntryStruct { /* Generic data structure. DO NOT add anything before this! */ @@ -348,6 +355,10 @@ struct SilcClientEntryStruct { /* we need this so nobody can resume more than once at the same time - * server crashes, really odd behaviour, ... */ SilcClientEntry resuming_client; + + /* Client is locally owned but detached and not counted in the user + * count for local clients (server->stat.my_clients). */ + unsigned local_detached : 1; }; /* diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index ac815610..e776863e 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -1500,7 +1500,8 @@ static void silc_server_notify_process(SilcServer server, SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR); if (SILC_IS_LOCAL(client)) { - server->stat.my_clients--; + if (!client->local_detached) + server->stat.my_clients--; silc_schedule_task_del_by_context(server->schedule, client); silc_idlist_del_data(client); client->mode = 0; @@ -3740,6 +3741,7 @@ void silc_server_resume_client(SilcServer server, server user count as-is (incremented by the current client entry) as we decremented the count already during detach, thus we'd be undoing that operation. */ + detached_client->local_detached = FALSE; SILC_VERIFY(server->stat.clients > 0); server->stat.clients--; if (server->stat.cell_clients) @@ -4025,8 +4027,12 @@ void silc_server_resume_client(SilcServer server, detached_client, &id_cache)) silc_idcache_move(server->local_list->clients, server->global_list->clients, id_cache); - } + } + /* We don't own this client anymore, if we ever did, as we were just + * told that someone else resumed it. Thus, it is most definitely no + * a detached client.*/ + detached_client->local_detached = FALSE; /* Change the owner of the client */ detached_client->router = server_entry; diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 3d0623ac..ab1d7374 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -3142,7 +3142,10 @@ void silc_server_free_client_data(SilcServer server, } /* Update statistics */ - server->stat.my_clients--; + + /* Local detached clients aren't counted. */ + if (!client->local_detached) + server->stat.my_clients--; SILC_VERIFY(server->stat.clients > 0); server->stat.clients--; if (server->stat.cell_clients) diff --git a/apps/silcd/server_util.c b/apps/silcd/server_util.c index 9bcc47b2..b7b50617 100644 --- a/apps/silcd/server_util.c +++ b/apps/silcd/server_util.c @@ -1577,7 +1577,8 @@ void silc_server_kill_client(SilcServer server, } if (SILC_IS_LOCAL(remote_client)) { - server->stat.my_clients--; + if (!remote_client->local_detached) + server->stat.my_clients--; silc_schedule_task_del_by_context(server->schedule, remote_client); }