updates.
[silc.git] / apps / silcd / server.c
index 05323399eda32a43a8612d13898fbf6f42f15bef..a9395e399db27012da1c771ea50dd1b3624c017f 100644 (file)
@@ -659,7 +659,11 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router)
       sconn->remote_host = strdup(ptr->host);
       sconn->remote_port = ptr->port;
       sconn->backup = ptr->backup_router;
-      
+      if (sconn->backup) {
+       sconn->backup_replace_ip = strdup(ptr->backup_replace_ip);
+       sconn->backup_replace_port = ptr->backup_replace_port;
+      }
+
       silc_schedule_task_add(server->schedule, fd, 
                             silc_server_connect_router,
                             (void *)sconn, 0, 1, SILC_TASK_TIMEOUT, 
@@ -872,8 +876,24 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
 
   SILC_LOG_INFO(("Connected to router %s", sock->hostname));
 
-  /* Add the connected router to local server list */
-  id_entry = silc_idlist_add_server(server->local_list, strdup(sock->hostname),
+  /* Check that we do not have this ID already */
+  id_entry = silc_idlist_find_server_by_id(server->local_list, 
+                                          ctx->dest_id, TRUE, NULL);
+  if (id_entry) {
+    silc_idcache_del_by_context(server->local_list->servers, id_entry);
+  } else {
+    id_entry = silc_idlist_find_server_by_id(server->global_list, 
+                                            ctx->dest_id, TRUE, NULL);
+    if (id_entry) 
+      silc_idcache_del_by_context(server->global_list->servers, id_entry);
+  }
+
+  SILC_LOG_DEBUG(("New server id(%s)",
+                 silc_id_render(ctx->dest_id, SILC_ID_SERVER)));
+
+  /* Add the connected router to global server list */
+  id_entry = silc_idlist_add_server(server->global_list, 
+                                   strdup(sock->hostname),
                                    SILC_ROUTER, ctx->dest_id, NULL, sock);
   if (!id_entry) {
     silc_free(ctx->dest_id);
@@ -924,7 +944,8 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
     }
   } else {
     /* Add this server to be our backup router */
-    silc_server_backup_add(server, id_entry, FALSE);
+    silc_server_backup_add(server, id_entry, sconn->backup_replace_ip,
+                          sconn->backup_replace_port, FALSE);
   }
 
   sock->protocol = NULL;
@@ -938,6 +959,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
   /* Free the temporary connection data context */
   if (sconn) {
     silc_free(sconn->remote_host);
+    silc_free(sconn->backup_replace_ip);
     silc_free(sconn);
   }
 
@@ -1315,11 +1337,18 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
         server. We mark ourselves as router for this server if we really
         are router. */
       new_server = 
-       silc_idlist_add_server(server->local_list, NULL,
-                              ctx->conn_type == SILC_SOCKET_TYPE_SERVER ?
-                              SILC_SERVER : SILC_ROUTER, NULL, 
-                              ctx->conn_type == SILC_SOCKET_TYPE_SERVER ?
-                              server->id_entry : NULL, sock);
+       silc_idlist_add_server((ctx->conn_type == SILC_SOCKET_TYPE_SERVER ?
+                               server->local_list : (conn->backup_router ?
+                                                     server->local_list :
+                                                     server->global_list)),
+                              NULL,
+                              (ctx->conn_type == SILC_SOCKET_TYPE_SERVER ?
+                               SILC_SERVER : SILC_ROUTER), 
+                              NULL, 
+                              (ctx->conn_type == SILC_SOCKET_TYPE_SERVER ?
+                               server->id_entry : (conn->backup_router ? 
+                                                   server->id_entry : NULL)),
+                              sock);
       if (!new_server) {
        SILC_LOG_ERROR(("Could not add new server to cache"));
        silc_free(sock->user_data);
@@ -1342,22 +1371,15 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
       /* If the incoming connection is router and marked as backup router
         then add it to be one of our backups */
       if (ctx->conn_type == SILC_SOCKET_TYPE_ROUTER && conn->backup_router) {
-       silc_server_backup_add(server, new_server, conn->backup_local);
+       silc_server_backup_add(server, new_server, conn->backup_replace_ip,
+                              conn->backup_replace_port, conn->backup_local);
 
        /* Change it back to SERVER type since that's what it really is. */
-       if (conn->backup_local) {
+       if (conn->backup_local)
          ctx->conn_type = SILC_SOCKET_TYPE_SERVER;
-         new_server->server_type = SILC_BACKUP_ROUTER;
-       }
-      }
 
-#if 0
-      /* If the incoming connection is normal server and marked as backup
-        server then it will use us as backup router. We'll disable the
-        connection until it is allowed to be used. */
-      if (ctx->conn_type == SILC_SOCKET_TYPE_SERVER && conn->backup_router)
-       SILC_SET_DISABLED(sock);
-#endif
+       new_server->server_type = SILC_BACKUP_ROUTER;
+      }
 
       /* Check whether this connection is to be our primary router connection
         if we do not already have the primary route. */
@@ -1606,8 +1628,10 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real)
 
   /* If entry is disabled ignore what we got. */
   if (ret != SILC_PACKET_RESUME_ROUTER &&
-      idata && idata->status & SILC_IDLIST_STATUS_DISABLED)
+      idata && idata->status & SILC_IDLIST_STATUS_DISABLED) {
+    SILC_LOG_DEBUG(("Connection is disabled"));
     goto out;
+  }
 
   if (ret == SILC_PACKET_NONE)
     goto out;
@@ -2314,11 +2338,12 @@ void silc_server_free_sock_user_data(SilcServer server,
       SilcServerEntry user_data = (SilcServerEntry)sock->user_data;
       SilcServerEntry backup_router = NULL;
 
+      if (user_data->id)
+       backup_router = silc_server_backup_get(server, user_data->id);
+
       /* If this was our primary router connection then we're lost to
         the outside world. */
       if (server->router == user_data) {
-       backup_router = silc_server_backup_get(server);
-
        /* Check whether we have a backup router connection */
        if (!backup_router || backup_router == user_data) {
          silc_schedule_task_add(server->schedule, 0, 
@@ -2339,6 +2364,7 @@ void silc_server_free_sock_user_data(SilcServer server,
          server->id_entry->router = backup_router;
          server->router = backup_router;
          server->router_connect = time(0);
+         server->backup_primary = TRUE;
          if (server->server_type == SILC_BACKUP_ROUTER) {
            server->server_type = SILC_ROUTER;
 
@@ -2353,6 +2379,15 @@ void silc_server_free_sock_user_data(SilcServer server,
          silc_server_backup_replaced_add(server, user_data->id, 
                                          backup_router);
        }
+      } else if (backup_router) {
+       SILC_LOG_INFO(("Enabling the use of backup router %s",
+                      backup_router->server_name));
+       SILC_LOG_DEBUG(("Enabling the use of backup router %s",
+                       backup_router->server_name));
+
+       /* Mark this connection as replaced */
+       silc_server_backup_replaced_add(server, user_data->id, 
+                                       backup_router);
       }
 
       if (!backup_router) {
@@ -2372,7 +2407,8 @@ void silc_server_free_sock_user_data(SilcServer server,
       silc_server_backup_del(server, user_data);
       silc_server_backup_replaced_del(server, user_data);
       silc_idlist_del_data(user_data);
-      silc_idlist_del_server(server->local_list, user_data);
+      if (!silc_idlist_del_server(server->local_list, user_data))
+       silc_idlist_del_server(server->global_list, user_data);
       server->stat.my_servers--;
       server->stat.servers--;
       if (server->server_type == SILC_ROUTER)
@@ -2381,26 +2417,15 @@ void silc_server_free_sock_user_data(SilcServer server,
       if (backup_router) {
        /* Announce all of our stuff that was created about 5 minutes ago.
           The backup router knows all the other stuff already. */
-       if (server->server_type == SILC_ROUTER)
-         silc_server_announce_servers(server, FALSE, 0,
-                                      server->router->connection);
-
-       /* Announce our clients and channels to the router */
-       silc_server_announce_clients(server, 0,
-                                    server->router->connection);
-       silc_server_announce_channels(server, 0,
-                                     server->router->connection);
-#if 0
        if (server->server_type == SILC_ROUTER)
          silc_server_announce_servers(server, FALSE, time(0) - 300,
-                                      server->router->connection);
+                                      backup_router->connection);
 
        /* Announce our clients and channels to the router */
        silc_server_announce_clients(server, time(0) - 300,
-                                    server->router->connection);
+                                    backup_router->connection);
        silc_server_announce_channels(server, time(0) - 300,
-                                     server->router->connection);
-#endif
+                                     backup_router->connection);
       }
       break;
     }
@@ -2462,9 +2487,9 @@ void silc_server_remove_from_channels(SilcServer server,
        silc_hash_table_count(channel->user_list) < 2) {
       if (channel->rekey)
        silc_schedule_task_del_by_context(server->schedule, channel->rekey);
-      if (!silc_idlist_del_channel(server->local_list, channel))
-       silc_idlist_del_channel(server->global_list, channel);
+      if (silc_idlist_del_channel(server->local_list, channel))
       server->stat.my_channels--;
+       silc_idlist_del_channel(server->global_list, channel);
       continue;
     }