updates.
[silc.git] / apps / silcd / server_util.c
index b86abec99395c8b45fca87da86db8975b2567214..a29c2fd3757685017be70b928ae0368b528ea117 100644 (file)
@@ -64,8 +64,8 @@ static void silc_server_remove_clients_channels(SilcServer server,
 
       if (silc_idlist_del_channel(server->local_list, channel))
        server->stat.my_channels--;
-      else if (silc_idlist_del_channel(server->global_list, channel))
-       server->stat.my_channels--;
+      else 
+        silc_idlist_del_channel(server->global_list, channel);
       continue;
     }
 
@@ -97,7 +97,7 @@ static void silc_server_remove_clients_channels(SilcServer server,
        SilcChannelClientEntry chl2;
        SilcHashTableList htl2;
 
-       channel->id = NULL;
+       channel->disabled = TRUE;
 
        silc_hash_table_list(channel->user_list, &htl2);
        while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) {
@@ -111,8 +111,8 @@ static void silc_server_remove_clients_channels(SilcServer server,
       /* Remove the channel entry */
       if (silc_idlist_del_channel(server->local_list, channel))
        server->stat.my_channels--;
-      else if (silc_idlist_del_channel(server->global_list, channel))
-       server->stat.my_channels--;
+      else 
+        silc_idlist_del_channel(server->global_list, channel);
       continue;
     }
 
@@ -182,7 +182,7 @@ bool silc_server_remove_clients_by_server(SilcServer server,
        }
 
        if (client->router != entry) {
-         if (server_signoff && client->connection) {
+         if (server_signoff) {
            clients = silc_realloc(clients, 
                                   sizeof(*clients) * (clients_c + 1));
            clients[clients_c] = client;
@@ -212,7 +212,11 @@ bool silc_server_remove_clients_by_server(SilcServer server,
 
        /* Remove the client entry */
        silc_server_remove_clients_channels(server, NULL, client, channels);
-       silc_idlist_del_client(server->local_list, client);
+       client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+       id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
+       server->stat.clients--;
+       if (server->server_type == SILC_ROUTER)
+         server->stat.cell_clients--;
 
        if (!silc_idcache_list_next(list, &id_cache))
          break;
@@ -264,7 +268,11 @@ bool silc_server_remove_clients_by_server(SilcServer server,
 
        /* Remove the client entry */
        silc_server_remove_clients_channels(server, NULL, client, channels);
-       silc_idlist_del_client(server->global_list, client);
+       client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+       id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
+       server->stat.clients--;
+       if (server->server_type == SILC_ROUTER)
+         server->stat.cell_clients--;
 
        if (!silc_idcache_list_next(list, &id_cache))
          break;
@@ -275,7 +283,7 @@ bool silc_server_remove_clients_by_server(SilcServer server,
 
   /* Send the SERVER_SIGNOFF notify */
   if (server_signoff) {
-    SilcBuffer args;
+    SilcBuffer args, not;
 
     /* Send SERVER_SIGNOFF notify to our primary router */
     if (!server->standalone && server->router &&
@@ -291,17 +299,19 @@ bool silc_server_remove_clients_by_server(SilcServer server,
       silc_buffer_free(args);
     }
 
+    /* Send to local clients. We also send the list of client ID's that
+       is to be removed for those servers that would like to use that list. */
     args = silc_argument_payload_encode(argc, argv, argv_lens,
                                        argv_types);
-    /* Send to local clients */
-    for (i = 0; i < clients_c; i++) {
-      silc_server_send_notify_args(server, clients[i]->connection,
-                                  FALSE, SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
-                                  argc, args);
-    }
+    not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF, 
+                                         argc, args);
+    silc_server_packet_send_clients(server, clients, clients_c,
+                                   SILC_PACKET_NOTIFY, 0, FALSE,
+                                   not->data, not->len, FALSE);
 
     silc_free(clients);
     silc_buffer_free(args);
+    silc_buffer_free(not);
     for (i = 0; i < argc; i++)
       silc_free(argv[i]);
     silc_free(argv);
@@ -353,7 +363,6 @@ silc_server_update_clients_by_real_server(SilcServer server,
        SILC_LOG_DEBUG(("Found (local) %s",
                        silc_id_render(server_entry->id, SILC_ID_SERVER)));
 
-#if 0
        if (!server_entry->data.send_key && server_entry->router) {
          SILC_LOG_DEBUG(("Server not locally connected, use its router"));
          /* If the client is not marked as local then move it to local list
@@ -367,7 +376,6 @@ silc_server_update_clients_by_real_server(SilcServer server,
          }
          server_entry = server_entry->router;
        } else {
-#endif
          /* If the client is not marked as local then move it to local list
             since the server is local. */
          if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
@@ -377,9 +385,7 @@ silc_server_update_clients_by_real_server(SilcServer server,
                             client_cache->expire);
            silc_idcache_del_by_context(server->global_list->clients, client);
          }
-#if 0
        }
-#endif
 
        silc_idcache_list_free(list);
        return server_entry;
@@ -404,7 +410,6 @@ silc_server_update_clients_by_real_server(SilcServer server,
        SILC_LOG_DEBUG(("Found (global) %s",
                        silc_id_render(server_entry->id, SILC_ID_SERVER)));
 
-#if 0
        if (!server_entry->data.send_key && server_entry->router) {
          SILC_LOG_DEBUG(("Server not locally connected, use its router"));
          /* If the client is marked as local then move it to global list
@@ -418,7 +423,6 @@ silc_server_update_clients_by_real_server(SilcServer server,
          }
          server_entry = server_entry->router;
        } else {
-#endif
          /* If the client is marked as local then move it to global list
             since the server is global. */
          if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
@@ -428,9 +432,7 @@ silc_server_update_clients_by_real_server(SilcServer server,
                             client_cache->expire);
            silc_idcache_del_by_context(server->local_list->clients, client);
          }
-#if 0
        }
-#endif
 
        silc_idcache_list_free(list);
        return server_entry;
@@ -480,8 +482,6 @@ void silc_server_update_clients_by_server(SilcServer server,
     if (silc_idcache_list_first(list, &id_cache)) {
       while (id_cache) {
        client = (SilcClientEntry)id_cache->context;
-       
-
        if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
          if (!silc_idcache_list_next(list, &id_cache))
            break;
@@ -529,7 +529,6 @@ void silc_server_update_clients_by_server(SilcServer server,
     if (silc_idcache_list_first(list, &id_cache)) {
       while (id_cache) {
        client = (SilcClientEntry)id_cache->context;
-
        if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
          if (!silc_idcache_list_next(list, &id_cache))
            break;
@@ -623,6 +622,57 @@ void silc_server_update_servers_by_server(SilcServer server,
   }
 }
 
+/* Removes channels that are from `from. */
+
+void silc_server_remove_channels_by_server(SilcServer server, 
+                                          SilcServerEntry from)
+{
+  SilcIDCacheList list = NULL;
+  SilcIDCacheEntry id_cache = NULL;
+  SilcChannelEntry channel = NULL;
+
+  SILC_LOG_DEBUG(("Start"));
+
+  if (silc_idcache_get_all(server->global_list->channels, &list)) {
+    if (silc_idcache_list_first(list, &id_cache)) {
+      while (id_cache) {
+       channel = (SilcChannelEntry)id_cache->context;
+       if (channel->router == from)
+         silc_idlist_del_channel(server->global_list, channel);
+       if (!silc_idcache_list_next(list, &id_cache))
+         break;
+      }
+    }
+    silc_idcache_list_free(list);
+  }
+}
+
+/* Updates channels that are from `from' to be originated from `to'.  */
+
+void silc_server_update_channels_by_server(SilcServer server, 
+                                          SilcServerEntry from,
+                                          SilcServerEntry to)
+{
+  SilcIDCacheList list = NULL;
+  SilcIDCacheEntry id_cache = NULL;
+  SilcChannelEntry channel = NULL;
+
+  SILC_LOG_DEBUG(("Start"));
+
+  if (silc_idcache_get_all(server->global_list->channels, &list)) {
+    if (silc_idcache_list_first(list, &id_cache)) {
+      while (id_cache) {
+       channel = (SilcChannelEntry)id_cache->context;
+       if (channel->router == from)
+         channel->router = to;
+       if (!silc_idcache_list_next(list, &id_cache))
+         break;
+      }
+    }
+    silc_idcache_list_free(list);
+  }
+}
+
 /* Checks whether given channel has global users.  If it does this returns
    TRUE and FALSE if there is only locally connected clients on the channel. */