New silcconfig library and server parser. Merged silc-newconfig-final.patch.
[silc.git] / apps / silcd / server_backup.c
index 3a16e54afa9205a82d98a49fe78d0675c6ed6876..6b3d876a8e74999f6cf0c7be9696d10614773128 100644 (file)
@@ -90,8 +90,8 @@ void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server,
       server->backup->servers[i].local = local;
       memset(server->backup->servers[i].ip.data, 0,
             sizeof(server->backup->servers[i].ip.data));
-      silc_net_addr2bin_ne(ip, server->backup->servers[i].ip.data,
-                          sizeof(server->backup->servers[i].ip.data));
+      silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
+                       sizeof(server->backup->servers[i].ip.data));
       //server->backup->servers[i].port = port;
       return;
     }
@@ -105,8 +105,8 @@ void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server,
   server->backup->servers[i].local = local;
   memset(server->backup->servers[i].ip.data, 0,
         sizeof(server->backup->servers[i].ip.data));
-  silc_net_addr2bin_ne(ip, server->backup->servers[i].ip.data,
-                      sizeof(server->backup->servers[i].ip.data));
+  silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
+                   sizeof(server->backup->servers[i].ip.data));
   //server->backup->servers[i].port = server_id->port;
   server->backup->servers_count++;
 }
@@ -293,7 +293,7 @@ void silc_server_backup_broadcast(SilcServer server,
 
     silc_packet_send_prepare(sock, 0, 0, buffer->len); 
     silc_buffer_put(sock->outbuf, buffer->data, buffer->len);
-    silc_packet_encrypt(idata->send_key, idata->hmac_send, 
+    silc_packet_encrypt(idata->send_key, idata->hmac_send, idata->psn_send++, 
                        sock->outbuf, sock->outbuf->len);
 
     SILC_LOG_HEXDUMP(("Broadcasted packet, len %d", sock->outbuf->len),
@@ -401,7 +401,8 @@ void silc_server_backup_resume_router(SilcServer server,
                                      SilcPacketContext *packet)
 {
   uint8 type, session;
-  int ret;
+  SilcServerBackupProtocolContext ctx;
+  int i, ret;
 
   if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
       sock->type == SILC_SOCKET_TYPE_UNKNOWN)
@@ -409,7 +410,6 @@ void silc_server_backup_resume_router(SilcServer server,
 
   SILC_LOG_DEBUG(("Start"));
 
-    SILC_LOG_DEBUG(("********************************"));
   ret = silc_buffer_unformat(packet->buffer,
                             SILC_STR_UI_CHAR(&type),
                             SILC_STR_UI_CHAR(&session),
@@ -417,14 +417,34 @@ void silc_server_backup_resume_router(SilcServer server,
   if (ret < 0)
     return;
   
-    SILC_LOG_DEBUG(("********************************"));
+  /* Activate the protocol for this socket if necessary */
+  if ((type == SILC_SERVER_BACKUP_RESUMED || 
+      type == SILC_SERVER_BACKUP_RESUMED_GLOBAL) &&
+      sock->type == SILC_SOCKET_TYPE_ROUTER && !sock->protocol && 
+      ((SilcIDListData)sock->user_data)->status & 
+      SILC_IDLIST_STATUS_DISABLED) {
+    SilcServerEntry backup_router;
+
+    if (silc_server_backup_replaced_get(server, 
+                                       ((SilcServerEntry)sock->
+                                        user_data)->id, 
+                                       &backup_router)) {
+      SilcSocketConnection bsock = 
+       (SilcSocketConnection)backup_router->connection;
+      if (bsock->protocol && bsock->protocol->protocol &&
+         bsock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
+       sock->protocol = bsock->protocol;
+       ctx = sock->protocol->context;
+       ctx->sock = sock;
+      }
+    }
+  }
+
   /* If the backup resuming protocol is active then process the packet
      in the protocol. */
   if (sock->protocol && sock->protocol->protocol &&
       sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP) {
-    SilcServerBackupProtocolContext ctx = sock->protocol->context;
-    int i;
-
+    ctx = sock->protocol->context;
     ctx->type = type;
 
     SILC_LOG_DEBUG(("********************************"));
@@ -448,7 +468,6 @@ void silc_server_backup_resume_router(SilcServer server,
     return;
   }
 
-    SILC_LOG_DEBUG(("********************************"));
   /* We don't have protocol active. If we are router and the packet is 
      coming from our primary router then lets check whether it means we've
      been replaced by an backup router in my cell. This is usually received
@@ -463,14 +482,13 @@ void silc_server_backup_resume_router(SilcServer server,
     SilcIDListData idata = (SilcIDListData)sock->user_data;
 
     SILC_LOG_INFO(("We are replaced by an backup router in this cell, will "
-                  "wait untill backup resuming protocol is executed"));
+                  "wait until backup resuming protocol is executed"));
 
     SILC_LOG_DEBUG(("We are replaced by an backup router in this cell"));
     idata->status |= SILC_IDLIST_STATUS_DISABLED;
     return;
   }
 
-    SILC_LOG_DEBUG(("********************************"));
   if (type == SILC_SERVER_BACKUP_START ||
       type == SILC_SERVER_BACKUP_START_GLOBAL) {
     /* We have received a start for resuming protocol. */
@@ -492,7 +510,6 @@ void silc_server_backup_resume_router(SilcServer server,
                        silc_server_protocol_backup_done);
     silc_protocol_execute(sock->protocol, server->schedule, 0, 0);
   }
-    SILC_LOG_DEBUG(("EEEEEEEEEEEEEEEEEEEEEEEEe"));
 }
 
 /* Timeout task callback to connect to remote router */
@@ -507,7 +524,7 @@ SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
                  sconn->remote_port));
 
   /* Connect to remote host */
-  sock = silc_net_create_connection(server->config->listen_port->local_ip,
+  sock = silc_net_create_connection(server->config->server_info->server_ip,
                                    sconn->remote_port,
                                    sconn->remote_host);
   if (sock < 0) {
@@ -633,6 +650,34 @@ static void silc_server_backup_connect_primary(SilcServer server,
   backup_router->protocol = NULL;
 }
 
+SILC_TASK_CALLBACK(silc_server_backup_send_resumed)
+{
+  SilcProtocol protocol = (SilcProtocol)context;
+  SilcServerBackupProtocolContext ctx = protocol->context;
+  SilcServer server = ctx->server;
+  SilcBuffer packet;
+  int i;
+
+  for (i = 0; i < ctx->sessions_count; i++)
+    if (ctx->sessions[i].server_entry == ctx->sock->user_data)
+      ctx->session = ctx->sessions[i].session;
+  
+  /* We've received all the CONNECTED packets and now we'll send the
+     ENDING packet to the new primary router. */
+  packet = silc_buffer_alloc(2);
+  silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
+  silc_buffer_format(packet,
+                    SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_ENDING),
+                    SILC_STR_UI_CHAR(ctx->session),
+                    SILC_STR_END);
+  silc_server_packet_send(server, ctx->sock, 
+                         SILC_PACKET_RESUME_ROUTER, 0, 
+                         packet->data, packet->len, FALSE);
+  silc_buffer_free(packet);
+  
+  protocol->state = SILC_PROTOCOL_STATE_END;
+}
+
 /* Resume protocol with RESUME_ROUTER packet: 
 
    SILC_PACKET_RESUME_ROUTER:
@@ -724,8 +769,55 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
        if (silc_idcache_list_first(list, &id_cache)) {
          while (id_cache) {
            server_entry = (SilcServerEntry)id_cache->context;
-           if ((server_entry == server->id_entry) || 
-               !server_entry->connection) {
+           if (!server_entry || (server_entry == server->id_entry) || 
+               !server_entry->connection || !server_entry->data.send_key ||
+               (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
+             if (!silc_idcache_list_next(list, &id_cache))
+               break;
+             else
+               continue;
+           }
+
+           ctx->sessions = silc_realloc(ctx->sessions,
+                                        sizeof(*ctx->sessions) *
+                                        (ctx->sessions_count + 1));
+           ctx->sessions[ctx->sessions_count].session = ctx->sessions_count;
+           ctx->sessions[ctx->sessions_count].connected = FALSE;
+           ctx->sessions[ctx->sessions_count].server_entry = server_entry;
+
+           SILC_LOG_DEBUG(("********************************"));
+           SILC_LOG_DEBUG(("START (local) for session %d", 
+                           ctx->sessions_count));
+
+           /* This connection is performing this protocol too now */
+           ((SilcSocketConnection)server_entry->connection)->protocol =
+             protocol;
+
+           if (server_entry->server_type == SILC_ROUTER)
+             packet->data[0] = SILC_SERVER_BACKUP_START;
+           else
+             packet->data[0] = SILC_SERVER_BACKUP_START_GLOBAL;
+           packet->data[1] = ctx->sessions_count;
+           silc_server_packet_send(server, server_entry->connection,
+                                   SILC_PACKET_RESUME_ROUTER, 0, 
+                                   packet->data, packet->len, FALSE);
+           ctx->sessions_count++;
+
+           if (!silc_idcache_list_next(list, &id_cache))
+             break;
+         }
+       }
+
+       silc_idcache_list_free(list);
+      }
+
+      if (silc_idcache_get_all(server->global_list->servers, &list)) {
+       if (silc_idcache_list_first(list, &id_cache)) {
+         while (id_cache) {
+           server_entry = (SilcServerEntry)id_cache->context;
+           if (!server_entry || (server_entry == server->id_entry) || 
+               !server_entry->connection || !server_entry->data.send_key ||
+               (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)) {
              if (!silc_idcache_list_next(list, &id_cache))
                break;
              else
@@ -740,7 +832,8 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
            ctx->sessions[ctx->sessions_count].server_entry = server_entry;
 
            SILC_LOG_DEBUG(("********************************"));
-           SILC_LOG_DEBUG(("START for session %d", ctx->sessions_count));
+           SILC_LOG_DEBUG(("START (global) for session %d", 
+                           ctx->sessions_count));
 
            /* This connection is performing this protocol too now */
            ((SilcSocketConnection)server_entry->connection)->protocol =
@@ -766,16 +859,15 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
 
       silc_buffer_free(packet);
 
-      /* If we are router then announce our possible servers. */
-      if (server->server_type == SILC_ROUTER)
-       silc_server_announce_servers(server, FALSE, 0, ctx->sock);
+      /* Announce all of our information */
+      silc_server_announce_servers(server, TRUE, 0, ctx->sock);
       silc_server_announce_clients(server, 0, ctx->sock);
       silc_server_announce_channels(server, 0, ctx->sock);
 
       protocol->state++;
     } else {
       /* Responder of the protocol. */
-      SilcServerConfigSectionServerConnection *primary;
+      SilcServerConfigSectionRouter *primary;
 
       /* We should have received START or START_GLOBAL packet */
       if (ctx->type != SILC_SERVER_BACKUP_START &&
@@ -858,24 +950,12 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
       SILC_LOG_DEBUG(("********************************"));
       SILC_LOG_DEBUG(("Sending ENDING packet to primary"));
 
-      for (i = 0; i < ctx->sessions_count; i++)
-       if (ctx->sessions[i].server_entry == ctx->sock->user_data)
-         ctx->session = ctx->sessions[i].session;
-
-      /* We've received all the CONNECTED packets and now we'll send the
-        ENDING packet to the new primary router. */
-      packet = silc_buffer_alloc(2);
-      silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
-      silc_buffer_format(packet,
-                        SILC_STR_UI_CHAR(SILC_SERVER_BACKUP_ENDING),
-                        SILC_STR_UI_CHAR(ctx->session),
-                        SILC_STR_END);
-      silc_server_packet_send(server, ctx->sock, 
-                             SILC_PACKET_RESUME_ROUTER, 0, 
-                             packet->data, packet->len, FALSE);
-      silc_buffer_free(packet);
-
-      protocol->state = SILC_PROTOCOL_STATE_END;
+      /* Send with a timeout */
+      silc_schedule_task_add(server->schedule, 0, 
+                            silc_server_backup_send_resumed,
+                            protocol, 1, 0, SILC_TASK_TIMEOUT,
+                            SILC_TASK_PRI_NORMAL);
+      return;
     } else {
       /* Responder */
 
@@ -901,10 +981,15 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
        break;
       }
 
-      /* Switch announced informations to our entry instead of using the
+      /* Switch announced informations to our primary router of using the
         backup router. */
+      silc_server_update_servers_by_server(server, ctx->sock->user_data, 
+                                          server->router);
       silc_server_update_clients_by_server(server, ctx->sock->user_data,
-                                          server->id_entry, TRUE, FALSE);
+                                          server->router, TRUE, FALSE);
+      if (server->server_type == SILC_SERVER)
+       silc_server_update_channels_by_server(server, ctx->sock->user_data, 
+                                             server->router);
 
       packet = silc_buffer_alloc(2);
       silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
@@ -914,8 +999,8 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
        if (silc_idcache_list_first(list, &id_cache)) {
          while (id_cache) {
            server_entry = (SilcServerEntry)id_cache->context;
-           if ((server_entry == server->id_entry) || 
-               !server_entry->connection) {
+           if (!server_entry || (server_entry == server->id_entry) || 
+               !server_entry->connection || !server_entry->data.send_key) {
              if (!silc_idcache_list_next(list, &id_cache))
                break;
              else
@@ -923,7 +1008,44 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
            }
 
            SILC_LOG_DEBUG(("********************************"));
-           SILC_LOG_DEBUG(("RESUMED packet"));
+           SILC_LOG_DEBUG(("RESUMED packet (local)"));
+
+           server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
+
+           /* This connection is performing this protocol too now */
+           ((SilcSocketConnection)server_entry->connection)->protocol =
+             protocol;
+
+           if (server_entry->server_type == SILC_ROUTER)
+             packet->data[0] = SILC_SERVER_BACKUP_RESUMED;
+           else
+             packet->data[0] = SILC_SERVER_BACKUP_RESUMED_GLOBAL;
+           silc_server_packet_send(server, server_entry->connection,
+                                   SILC_PACKET_RESUME_ROUTER, 0, 
+                                   packet->data, packet->len, FALSE);
+
+           if (!silc_idcache_list_next(list, &id_cache))
+             break;
+         }
+       }
+
+       silc_idcache_list_free(list);
+      }
+
+      if (silc_idcache_get_all(server->global_list->servers, &list)) {
+       if (silc_idcache_list_first(list, &id_cache)) {
+         while (id_cache) {
+           server_entry = (SilcServerEntry)id_cache->context;
+           if (!server_entry || (server_entry == server->id_entry) || 
+               !server_entry->connection || !server_entry->data.send_key) {
+             if (!silc_idcache_list_next(list, &id_cache))
+               break;
+             else
+               continue;
+           }
+
+           SILC_LOG_DEBUG(("********************************"));
+           SILC_LOG_DEBUG(("RESUMED packet (global)"));
 
            server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
 
@@ -949,6 +1071,8 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
 
       silc_buffer_free(packet);
 
+      SILC_LOG_INFO(("We are now the primary router of our cell again"));
+
       /* For us this is the end of this protocol. */
       if (protocol->final_callback)
        silc_protocol_execute_final(protocol, server->schedule);
@@ -960,8 +1084,7 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
   case SILC_PROTOCOL_STATE_END:
     {
       SilcIDListData idata;
-      SilcServerEntry primary;
-      SilcServerEntry backup_router;
+      SilcServerEntry router, backup_router;
 
       /* We should have been received RESUMED packet from our primary
         router. */
@@ -978,45 +1101,48 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
       if (server->backup_router)
        server->server_type = SILC_BACKUP_ROUTER;
 
-      primary = (SilcServerEntry)ctx->sock->user_data;
-      if (silc_server_backup_replaced_get(server, primary->id, 
+      router = (SilcServerEntry)ctx->sock->user_data;
+      if (silc_server_backup_replaced_get(server, router->id, 
                                          &backup_router)) {
 
        if (backup_router == server->router) {
-         server->id_entry->router = ctx->sock->user_data;
-         server->router = ctx->sock->user_data;
+         server->id_entry->router = router;
+         server->router = router;
          SILC_LOG_INFO(("Switching back to primary router %s",
                         server->router->server_name));
-         SILC_LOG_DEBUG(("********************************"));
          SILC_LOG_DEBUG(("Switching back to primary router %s",
                          server->router->server_name));
          idata = (SilcIDListData)server->router;
          idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
-
-         /* Update the client entries of the backup router to the new 
-            primary router. */
-         silc_server_update_clients_by_server(server, backup_router,
-                                              primary, TRUE, FALSE);
-         silc_server_backup_replaced_del(server, backup_router);
-         silc_server_backup_add(server, backup_router, 
-                                ((SilcSocketConnection)primary->
-                                 connection)->ip,
-                                ((SilcSocketConnection)primary->
-                                 connection)->port,
-                                backup_router->server_type != SILC_ROUTER ?
-                                TRUE : FALSE);
+       } else {
+         SILC_LOG_INFO(("Resuming the use of router %s",
+                        router->server_name));
+         SILC_LOG_DEBUG(("Resuming the use of router %s",
+                         router->server_name));
+         idata = (SilcIDListData)router;
+         idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
        }
 
-       /* Announce all of our information to the new primary router. */
+       /* Update the client entries of the backup router to the new 
+          router */
+       silc_server_update_servers_by_server(server, backup_router, router);
+       silc_server_update_clients_by_server(server, backup_router,
+                                            router, TRUE, FALSE);
+       if (server->server_type == SILC_SERVER)
+         silc_server_update_channels_by_server(server, backup_router, router);
+       silc_server_backup_replaced_del(server, backup_router);
+       silc_server_backup_add(server, backup_router, 
+                              ctx->sock->ip, ctx->sock->port,
+                              backup_router->server_type != SILC_ROUTER ?
+                              TRUE : FALSE);
+
+       /* Announce all of our information to the router. */
        if (server->server_type == SILC_ROUTER)
-         silc_server_announce_servers(server, FALSE, 0,
-                                      server->router->connection);
-       
+         silc_server_announce_servers(server, FALSE, 0, 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);
+       silc_server_announce_clients(server, 0, router->connection);
+       silc_server_announce_channels(server, 0, router->connection);
       }
 
       /* Protocol has ended, call the final callback */
@@ -1065,15 +1191,39 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
     SILC_LOG_ERROR(("Error occurred during backup router resuming protcool"));
   }
 
+  /* Remove this protocol from all server entries that has it */
   if (silc_idcache_get_all(server->local_list->servers, &list)) {
     if (silc_idcache_list_first(list, &id_cache)) {
       while (id_cache) {
        server_entry = (SilcServerEntry)id_cache->context;
        sock = (SilcSocketConnection)server_entry->connection;
 
-       if (sock->protocol && sock->protocol->protocol &&
-           sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_BACKUP)
+       if (sock->protocol == protocol) {
          sock->protocol = NULL;
+
+         if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
+           server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
+       }
+       
+       if (!silc_idcache_list_next(list, &id_cache))
+         break;
+      }
+    }
+    silc_idcache_list_free(list);
+  }
+
+  if (silc_idcache_get_all(server->global_list->servers, &list)) {
+    if (silc_idcache_list_first(list, &id_cache)) {
+      while (id_cache) {
+       server_entry = (SilcServerEntry)id_cache->context;
+       sock = (SilcSocketConnection)server_entry->connection;
+
+       if (sock->protocol == protocol) {
+         sock->protocol = NULL;
+
+         if (server_entry->data.status & SILC_IDLIST_STATUS_DISABLED)
+           server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
+       }
        
        if (!silc_idcache_list_next(list, &id_cache))
          break;