Don't decrement my_clients when killing or expiring a detached client.
authorSkywing <skywing@valhallalegends.com>
Sat, 13 Dec 2008 21:27:48 +0000 (16:27 -0500)
committerSkywing <skywing@valhallalegends.com>
Sat, 13 Dec 2008 21:29:01 +0000 (16:29 -0500)
This prevents my_clients from getting out of sync when a detached
client is forcibly removed, fixing a regression.

apps/silcd/command.c
apps/silcd/idlist.h
apps/silcd/packet_receive.c
apps/silcd/server.c
apps/silcd/server_util.c

index f68edccdc589984e4c364c4e4220df0ad1636201..9c1fc4e2504604bbfce5b0bdb4229e0ed31de60c 100644 (file)
@@ -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.
index 7b9c2ad139647bd385ee5e09369d5d4e7b130666..0112db075ff24489265bbfa1da0b75e82d9a8ae8 100644 (file)
@@ -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;
 };
 
 /*
index ac8156106e02c5616018027769623d1ff4fe015b..e776863e6be5a949af821ba2fa2f3a24328f6f28 100644 (file)
@@ -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;
 
index 3d0623aca8c3aa2071299e4f0cd6b5f895f09158..ab1d737457b504aa9628839b6574a043c9a1ad3c 100644 (file)
@@ -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)
index 9bcc47b20377b5c8c5acd8a0152dce1ca08d1656..b7b50617d82e6e53657b99612f9cba0d24d4affb 100644 (file)
@@ -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);
     }