updates.
[silc.git] / apps / silcd / server.c
index 83cb7fef3597f4c65267378347ee5a68078983d0..ef90e6dc1d731083a5b6ba1072f510afd2974168 100644 (file)
@@ -483,6 +483,8 @@ void silc_server_run(SilcServer server)
 {
   SILC_LOG_DEBUG(("Running server"));
 
+  SILC_LOG_INFO(("SILC Server started"));
+
   /* Start the scheduler, the heart of the SILC server. When this returns
      the program will be terminated. */
   silc_schedule();
@@ -1008,6 +1010,9 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection)
      later when outgoing data is available. */
   SILC_REGISTER_CONNECTION_FOR_IO(sock);
 
+  SILC_LOG_INFO(("Incoming connection from %s (%s)", newsocket->hostname,
+                newsocket->ip));
+
   port = server->sockets[fd]->port; /* Listenning port */
 
   /* Check whether this connection is denied to connect to us. */
@@ -1017,6 +1022,8 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection)
                                          port);
   if (deny) {
     /* The connection is denied */
+    SILC_LOG_INFO(("Connection %s (%s) is denied", 
+                   newsocket->hostname, newsocket->ip));
     silc_server_disconnect_remote(server, newsocket, deny->comment ?
                                  deny->comment :
                                  "Server closed connection: "
@@ -1054,9 +1061,6 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection)
 
   /* The connection is allowed */
 
-  SILC_LOG_INFO(("Incoming connection from %s (%s)", newsocket->hostname,
-                newsocket->ip));
-
   /* Allocate internal context for key exchange protocol. This is
      sent as context for the protocol. */
   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
@@ -2076,6 +2080,14 @@ void silc_server_close_connection(SilcServer server,
                  sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
                  "Router"), sock->sock));
 
+  /* If any protocol is active cancel its execution */
+  if (sock->protocol) {
+    silc_protocol_cancel(sock->protocol, server->timeout_queue);
+    sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
+    silc_protocol_execute_final(sock->protocol, server->timeout_queue);
+    sock->protocol = NULL;
+  }
+
   /* We won't listen for this connection anymore */
   silc_schedule_unset_listen_fd(sock->sock);
 
@@ -2402,7 +2414,8 @@ int silc_server_remove_clients_by_server(SilcServer server,
     SilcBuffer args;
 
     /* Send SERVER_SIGNOFF notify to our primary router */
-    if (!server->standalone && server->router) {
+    if (!server->standalone && server->router &&
+       server->router != entry) {
       args = silc_argument_payload_encode(1, argv, argv_lens,
                                          argv_types);
       silc_server_send_notify_args(server, 
@@ -3292,7 +3305,9 @@ void silc_server_announce_get_channels(SilcServer server,
                                       SilcIDList id_list,
                                       SilcBuffer *channels,
                                       SilcBuffer *channel_users,
-                                      SilcBuffer *channel_users_modes)
+                                      SilcBuffer **channel_users_modes,
+                                      uint32 *channel_users_modes_c,
+                                      SilcChannelID ***channel_ids)
 {
   SilcIDCacheList list;
   SilcIDCacheEntry id_cache;
@@ -3301,6 +3316,7 @@ void silc_server_announce_get_channels(SilcServer server,
   uint32 id_len;
   uint16 name_len;
   int len;
+  int i = *channel_users_modes_c;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -3330,15 +3346,24 @@ void silc_server_announce_get_channels(SilcServer server,
                           SILC_STR_END);
        silc_buffer_pull(*channels, len);
 
+       *channel_users_modes = silc_realloc(*channel_users_modes,
+                                           sizeof(**channel_users_modes) * 
+                                           (i + 1));
+       (*channel_users_modes)[i] = NULL;
+       *channel_ids = silc_realloc(*channel_ids, 
+                                   sizeof(**channel_ids) * (i + 1));
+       (*channel_ids)[i] = NULL;
        silc_server_announce_get_channel_users(server, channel,
                                               channel_users,
-                                              channel_users_modes);
-
-       silc_free(cid);
+                                              channel_users_modes[i]);
+       (*channel_ids)[i] = channel->id;
+       i++;
 
        if (!silc_idcache_list_next(list, &id_cache))
          break;
       }
+
+      *channel_users_modes_c += i;
     }
 
     silc_idcache_list_free(list);
@@ -3351,19 +3376,26 @@ void silc_server_announce_get_channels(SilcServer server,
 
 void silc_server_announce_channels(SilcServer server)
 {
-  SilcBuffer channels = NULL, channel_users = NULL, channel_users_modes = NULL;
+  SilcBuffer channels = NULL, channel_users = NULL;
+  SilcBuffer *channel_users_modes = NULL;
+  uint32 channel_users_modes_c = 0;
+  SilcChannelID **channel_ids = NULL;
 
   SILC_LOG_DEBUG(("Announcing channels and channel users"));
 
   /* Get channels and channel users in local list */
   silc_server_announce_get_channels(server, server->local_list,
                                    &channels, &channel_users,
-                                   &channel_users_modes);
+                                   &channel_users_modes,
+                                   &channel_users_modes_c,
+                                   &channel_ids);
 
   /* Get channels and channel users in global list */
   silc_server_announce_get_channels(server, server->global_list,
                                    &channels, &channel_users,
-                                   &channel_users_modes);
+                                   &channel_users_modes,
+                                   &channel_users_modes_c,
+                                   &channel_ids);
 
   if (channels) {
     silc_buffer_push(channels, channels->data - channels->head);
@@ -3393,19 +3425,24 @@ void silc_server_announce_channels(SilcServer server)
   }
 
   if (channel_users_modes) {
-    silc_buffer_push(channel_users_modes, 
-                    channel_users_modes->data - channel_users_modes->head);
-    SILC_LOG_HEXDUMP(("channel users modes"), channel_users_modes->data, 
-                    channel_users_modes->len);
-
-    /* Send the packet */
-    silc_server_packet_send(server, server->router->connection,
-                           SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
-                           channel_users_modes->data, 
-                           channel_users_modes->len,
-                           FALSE);
-
-    silc_buffer_free(channel_users_modes);
+    int i;
+
+    for (i = 0; i < channel_users_modes_c; i++) {
+      silc_buffer_push(channel_users_modes[i], 
+                      channel_users_modes[i]->data - 
+                      channel_users_modes[i]->head);
+      SILC_LOG_HEXDUMP(("channel users modes"), channel_users_modes[i]->data, 
+                      channel_users_modes[i]->len);
+      silc_server_packet_send_dest(server, server->router->connection,
+                                  SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
+                                  channel_ids[i], SILC_ID_CHANNEL,
+                                  channel_users_modes[i]->data, 
+                                  channel_users_modes[i]->len,
+                                  FALSE);
+      silc_buffer_free(channel_users_modes[i]);
+    }
+    silc_free(channel_users_modes);
+    silc_free(channel_ids);
   }
 }