updates.
authorPekka Riikonen <priikone@silcnet.org>
Tue, 20 Mar 2001 22:18:12 +0000 (22:18 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 20 Mar 2001 22:18:12 +0000 (22:18 +0000)
18 files changed:
CHANGES
TODO
apps/silc/client_ops.c
apps/silc/local_command.c
apps/silcd/command.c
apps/silcd/command_reply.c
apps/silcd/command_reply.h
apps/silcd/idlist.c
apps/silcd/idlist.h
apps/silcd/packet_receive.c
apps/silcd/server.c
apps/silcd/testi2.conf
doc/draft-riikonen-silc-spec-01.nroff
lib/silcclient/client.c
lib/silcclient/client_prvmsg.c
lib/silcclient/command_reply.c
lib/silccore/idcache.c
lib/silccore/idcache.h

diff --git a/CHANGES b/CHANGES
index 76b0bca50ad8c131fadedc8acf8d1bf4582e4d1f..af5bc741dee4b2787660665cf4e6d1d8b361115c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,33 @@
+Tue Mar 20 21:05:57 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * The client entry's data.registered must be TRUE even with
+         global client entry on global client list.  The data.registered
+         is used to check whether the client is anymore in the network,
+         for example with WHOWAS command so it must be valid.
+
+       * Fixed the WHOWAS command in the server.  It now actually works
+         in router environment.  Added function into silcd/command_reply.c
+         silc_server_command_reply_whowas_save.
+
+       * Added silc_idlist_purge function to the silcd/idlist.c
+         to peridiocally purge the ID Cache.
+
+       * Fixed INFO command in the server.  It works now in router
+         environment.  Added <server name> argument to the INFO command
+         reply.  Updated the protocol specs.
+
+       * Fixed minor bug in silc_idcache_purge to not purge if the
+         expire value is zero.
+
+       * Fixed various bugs in WHOIS and IDENTIFY command handling as
+         they were buggy because of the WHOWAS information.
+
+       * Fixed local command MSG to handle the async resolving of 
+         the remote client properly.  It used to fail the first MSG.
+         Affected file silc/local_command.c.
+
+       * Added `data_len' field to SilcIDCache context.
+
 Tue Mar 20 16:29:00 EET 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Update TODO.  Todo in commands in the server.
diff --git a/TODO b/TODO
index be0898e9de3f0e11f699470ae27edd5324ecfc8b..482f0055fa4b403dc6607b0071b9dedaf9423b32 100644 (file)
--- a/TODO
+++ b/TODO
@@ -105,8 +105,6 @@ TODO In SILC Server
        o LIST is not implemented
        o RESTART is not implemented
        o INVITE is probably not working correctly
-       o INFO works only with local server.  It must work with any
-         server in the network, implement the sending to other servers.
        o PING works only with local server.  It must work with any
          server in the network, implement the sending to other servers.
        o MOTD works only with local server.  It must work with any
@@ -116,6 +114,12 @@ TODO In SILC Server
          Some of the modes may still not be implemented or is implemented
          the wrong way.  Also, setting ban and invite lists does not
          work at all and requires some thinking how to do them.
+       o In servers all command reply funtions should still call the
+         pending command reply even if the reply was error.  In client
+         it is not called but in server, I think, it must be called.
+         When implementing this check that all commands handle the
+         situation correctly when it is called as pending command
+         (it should most likely the that cmd->pending == TRUE/FALSE).
 
  o Packet processing can be made faster. All packet function in the
    packet_receive.c has same prototypes.  Instead of calling those from
index 2c3ac83d07cbc639a619e697b009cdfc0b5482f1..0a9eb74d8435126b3a32fa59ab9a720f845e5007 100644 (file)
@@ -413,7 +413,8 @@ void silc_command_reply(SilcClient client, SilcClientConnection conn,
        unsigned int idle, mode;
        SilcBuffer channels;
 
-       if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
+       if (status == SILC_STATUS_ERR_NO_SUCH_NICK ||
+           status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
          char *tmp;
          tmp = silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
                                           3, NULL);
@@ -503,7 +504,8 @@ void silc_command_reply(SilcClient client, SilcClientConnection conn,
        char buf[1024], *nickname, *username, *realname;
        int len;
 
-       if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
+       if (status == SILC_STATUS_ERR_NO_SUCH_NICK ||
+           status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
          char *tmp;
          tmp = silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
                                           3, NULL);
index 065da9385f4d58df097ff8680d74eff50df2cdef..0329366511ba39307c57521ec904127113e653b4 100644 (file)
@@ -128,8 +128,8 @@ SILC_CLIENT_LCMD_FUNC(msg)
   if (!client_entry) {
     /* Client entry not found, it was requested thus mark this to be
        pending command. */
-    silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, 0, NULL,
-                               silc_client_local_command_msg, context);
+    silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, conn->cmd_ident, 
+                               NULL, silc_client_local_command_msg, context);
     return;
   }
 
index 146c96a7efbcd1731217d5f3b16dbc15fedc5c62..7fac79e7df278489113a555cb6e0244953bb7da6 100644 (file)
@@ -487,6 +487,9 @@ silc_server_command_whois_check(SilcServerCommandContext cmd,
   for (i = 0; i < clients_count; i++) {
     entry = clients[i];
 
+    if (entry->data.registered == FALSE)
+      continue;
+
     if (!entry->nickname || !entry->username || !entry->userinfo) {
       SilcBuffer tmpbuf;
       unsigned short old_ident;
@@ -544,12 +547,14 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
   for (i = 0; i < clients_count; i++) {
     entry = clients[i];
 
-    if (entry->connection && entry->data.registered == FALSE) {
-      if (clients_count == 1)
+    if (entry->data.registered == FALSE) {
+      if (clients_count == 1) {
+       SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
        silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
-                                            SILC_STATUS_ERR_NO_SUCH_NICK,
-                                            3, entry->nickname, 
-                                            strlen(entry->nickname));
+                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
+                                            2, idp->data, idp->len);
+       silc_buffer_free(idp);
+      }
       continue;
     }
 
@@ -700,13 +705,13 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
       }
     }
   } else {
-    clients = silc_idlist_get_clients_by_nickname(server->local_list, 
-                                                 nick, server_name,
-                                                 &clients_count);
+    clients = silc_idlist_get_clients_by_hash(server->local_list, 
+                                             nick, server->md5hash,
+                                             &clients_count);
     if (!clients)
-      clients = silc_idlist_get_clients_by_hash(server->local_list, 
-                                               nick, server->md5hash,
-                                               &clients_count);
+      clients = silc_idlist_get_clients_by_nickname(server->local_list, 
+                                                   nick, server_name,
+                                                   &clients_count);
   }
   
   /* Check global list as well */
@@ -723,13 +728,13 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
        }
       }
     } else {
-      clients = silc_idlist_get_clients_by_nickname(server->global_list, 
-                                                   nick, server_name,
-                                                   &clients_count);
+      clients = silc_idlist_get_clients_by_hash(server->global_list, 
+                                               nick, server->md5hash,
+                                               &clients_count);
       if (!clients)
-       clients = silc_idlist_get_clients_by_hash(server->global_list, 
-                                                 nick, server->md5hash,
-                                                 &clients_count);
+       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
+                                                     nick, server_name,
+                                                     &clients_count);
     }
   }
   
@@ -810,13 +815,13 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
       }
     }
   } else {
-    clients = silc_idlist_get_clients_by_nickname(server->local_list, 
-                                                 nick, server_name,
-                                                 &clients_count);
+    clients = silc_idlist_get_clients_by_hash(server->local_list, 
+                                             nick, server->md5hash,
+                                             &clients_count);
     if (!clients)
-      clients = silc_idlist_get_clients_by_hash(server->local_list, 
-                                               nick, server->md5hash,
-                                               &clients_count);
+      clients = silc_idlist_get_clients_by_nickname(server->local_list, 
+                                                   nick, server_name,
+                                                   &clients_count);
   }
   
   /* If we are router we will check our global list as well. */
@@ -833,13 +838,13 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
        }
       }
     } else {
-      clients = silc_idlist_get_clients_by_nickname(server->global_list, 
-                                                   nick, server_name,
-                                                   &clients_count);
+      clients = silc_idlist_get_clients_by_hash(server->global_list, 
+                                               nick, server->md5hash,
+                                               &clients_count);
       if (!clients)
-       clients = silc_idlist_get_clients_by_hash(server->global_list, 
-                                                 nick, server->md5hash,
-                                                 &clients_count);
+       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
+                                                     nick, server_name,
+                                                     &clients_count);
     }
   }
 
@@ -950,6 +955,52 @@ silc_server_command_whowas_parse(SilcServerCommandContext cmd,
   return TRUE;
 }
 
+static char
+silc_server_command_whowas_check(SilcServerCommandContext cmd,
+                                SilcClientEntry *clients,
+                                unsigned int clients_count)
+{
+  SilcServer server = cmd->server;
+  int i;
+  SilcClientEntry entry;
+
+  for (i = 0; i < clients_count; i++) {
+    entry = clients[i];
+
+    if (!entry->nickname || !entry->username) {
+      SilcBuffer tmpbuf;
+      unsigned short old_ident;
+
+      if (!entry->router)
+       continue;
+      
+      old_ident = silc_command_get_ident(cmd->payload);
+      silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
+      tmpbuf = silc_command_payload_encode_payload(cmd->payload);
+
+      /* Send WHOWAS command */
+      silc_server_packet_send(server, entry->router->connection,
+                             SILC_PACKET_COMMAND, cmd->packet->flags,
+                             tmpbuf->data, tmpbuf->len, TRUE);
+      
+      /* Reprocess this packet after received reply */
+      silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
+                                 silc_command_get_ident(cmd->payload),
+                                 silc_server_command_destructor,
+                                 silc_server_command_whowas, 
+                                 silc_server_command_dup(cmd));
+      cmd->pending = TRUE;
+      
+      silc_command_set_ident(cmd->payload, old_ident);
+
+      silc_buffer_free(tmpbuf);
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
 static void
 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
                                      SilcClientEntry *clients,
@@ -963,6 +1014,7 @@ silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
   SilcCommandStatus status;
   unsigned short ident = silc_command_get_ident(cmd->payload);
   char found = FALSE;
+  char nh[256], uh[256];
 
   status = SILC_STATUS_OK;
   if (clients_count > 1)
@@ -999,27 +1051,25 @@ silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
     tmp = silc_argument_get_first_arg(cmd->args, NULL);
     
-    {
-      char nh[256], uh[256];
-
-      memset(uh, 0, sizeof(uh));
-      memset(nh, 0, sizeof(nh));
+    memset(uh, 0, sizeof(uh));
+    memset(nh, 0, sizeof(nh));
 
-      strncat(nh, entry->nickname, strlen(entry->nickname));
-      if (!strchr(entry->nickname, '@')) {
-       strncat(nh, "@", 1);
-       len = entry->router ? strlen(entry->router->server_name) :
-         strlen(server->server_name);
-       strncat(nh, entry->router ? entry->router->server_name :
-               server->server_name, len);
-      }
+    strncat(nh, entry->nickname, strlen(entry->nickname));
+    if (!strchr(entry->nickname, '@')) {
+      strncat(nh, "@", 1);
+      len = entry->router ? strlen(entry->router->server_name) :
+       strlen(server->server_name);
+      strncat(nh, entry->router ? entry->router->server_name :
+             server->server_name, len);
+    }
       
-      strncat(uh, entry->username, strlen(entry->username));
-      if (!strchr(entry->username, '@')) {
-       strncat(uh, "@", 1);
-       strcat(uh, "*private*");
-      }
+    strncat(uh, entry->username, strlen(entry->username));
+    if (!strchr(entry->username, '@')) {
+      strncat(uh, "@", 1);
+      strcat(uh, "*private*");
+    }
       
+    if (entry->userinfo)
       packet = 
        silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
                                             status, ident, 4, 
@@ -1028,8 +1078,14 @@ silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
                                             4, uh, strlen(uh),
                                             5, entry->userinfo, 
                                             strlen(entry->userinfo));
-    }
-    
+    else
+      packet = 
+       silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
+                                            status, ident, 3, 
+                                            2, idp->data, idp->len,
+                                            3, nh, strlen(nh),
+                                            4, uh, strlen(uh));
+
     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
                            0, packet->data, packet->len, FALSE);
     
@@ -1076,7 +1132,7 @@ silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
     silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
                                silc_command_get_ident(cmd->payload),
                                silc_server_command_destructor,
-                               silc_server_command_whois,
+                               silc_server_command_whowas,
                                silc_server_command_dup(cmd));
     cmd->pending = TRUE;
 
@@ -1114,11 +1170,8 @@ silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
                                                &clients_count);
   }
   
-  if (!clients) {
-    /* Such client(s) really does not exist in the SILC network. */
-    silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
-                                        SILC_STATUS_ERR_NO_SUCH_NICK,
-                                        3, nick, strlen(nick));
+  if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
+    ret = -1;
     goto out;
   }
 
@@ -1234,6 +1287,9 @@ silc_server_command_identify_check(SilcServerCommandContext cmd,
   for (i = 0; i < clients_count; i++) {
     entry = clients[i];
 
+    if (entry->data.registered == FALSE)
+      continue;
+
     if (!entry->nickname) {
       SilcBuffer tmpbuf;
       unsigned short old_ident;
@@ -1293,12 +1349,14 @@ silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
   for (i = 0; i < clients_count; i++) {
     entry = clients[i];
 
-    if (entry->connection && entry->data.registered == FALSE) {
-      if (clients_count == 1)
+    if (entry->data.registered == FALSE) {
+      if (clients_count == 1) {
+       SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
        silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
-                                            SILC_STATUS_ERR_NO_SUCH_NICK,
-                                            3, entry->nickname, 
-                                            strlen(entry->nickname));
+                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
+                                            2, idp->data, idp->len);
+       silc_buffer_free(idp);
+      }
       continue;
     }
 
@@ -1709,7 +1767,8 @@ SILC_SERVER_CMD_FUNC(nick)
 
   /* Update client cache */
   silc_idcache_add(server->local_list->clients, client->nickname, 
-                  SILC_ID_CLIENT, client->id, (void *)client, TRUE, FALSE);
+                  strlen(client->nickname), SILC_ID_CLIENT, client->id, 
+                  (void *)client, TRUE, FALSE);
 
   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
 
@@ -2164,7 +2223,9 @@ SILC_SERVER_CMD_FUNC(info)
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
   SilcBuffer packet, idp;
-  char info_string[256], *dest_server;
+  char *dest_server, *server_info = NULL, *server_name;
+  unsigned short ident = silc_command_get_ident(cmd->payload);
+  SilcServerEntry entry = NULL;
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
 
@@ -2178,6 +2239,8 @@ SILC_SERVER_CMD_FUNC(info)
 
   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
     /* Send our reply */
+    char info_string[256];
+
     memset(info_string, 0, sizeof(info_string));
     snprintf(info_string, sizeof(info_string), 
             "location: %s server: %s admin: %s <%s>",
@@ -2186,30 +2249,93 @@ SILC_SERVER_CMD_FUNC(info)
             server->config->admin_info->admin_name,
             server->config->admin_info->admin_email);
 
-    idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
-
-    packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
-                                                 SILC_STATUS_OK, 0, 2,
-                                                 2, idp->data, idp->len,
-                                                 3, info_string, 
-                                                 strlen(info_string));
-    silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
-                           packet->data, packet->len, FALSE);
-    
-    silc_buffer_free(packet);
-    silc_buffer_free(idp);
+    server_info = info_string;
+    entry = server->id_entry;
   } else {
-    /* Send this command to the requested server */
+    /* Check whether we have this server cached */
+    entry = silc_idlist_find_server_by_name(server->global_list,
+                                           dest_server, NULL);
+    if (!entry) {
+      entry = silc_idlist_find_server_by_name(server->local_list,
+                                             dest_server, NULL);
+    }
 
-    if (server->server_type == SILC_SERVER && !server->standalone) {
+    if (server->server_type == SILC_ROUTER && entry && !entry->server_info) {
+      /* Send to the server */
+      SilcBuffer tmpbuf;
+      unsigned short old_ident;
 
+      old_ident = silc_command_get_ident(cmd->payload);
+      silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
+      tmpbuf = silc_command_payload_encode_payload(cmd->payload);
+
+      silc_server_packet_send(server, entry->connection,
+                             SILC_PACKET_COMMAND, cmd->packet->flags,
+                             tmpbuf->data, tmpbuf->len, TRUE);
+
+      /* Reprocess this packet after received reply from router */
+      silc_server_command_pending(server, SILC_COMMAND_INFO, 
+                                 silc_command_get_ident(cmd->payload),
+                                 silc_server_command_destructor,
+                                 silc_server_command_info,
+                                 silc_server_command_dup(cmd));
+      cmd->pending = TRUE;
+      silc_command_set_ident(cmd->payload, old_ident);
+      silc_buffer_free(tmpbuf);
+      return;
     }
 
-    if (server->server_type == SILC_ROUTER) {
+    if (!entry && !cmd->pending && !server->standalone) {
+      /* Send to the primary router */
+      SilcBuffer tmpbuf;
+      unsigned short old_ident;
 
+      old_ident = silc_command_get_ident(cmd->payload);
+      silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
+      tmpbuf = silc_command_payload_encode_payload(cmd->payload);
+
+      silc_server_packet_send(server, server->router->connection,
+                             SILC_PACKET_COMMAND, cmd->packet->flags,
+                             tmpbuf->data, tmpbuf->len, TRUE);
+
+      /* Reprocess this packet after received reply from router */
+      silc_server_command_pending(server, SILC_COMMAND_INFO, 
+                                 silc_command_get_ident(cmd->payload),
+                                 silc_server_command_destructor,
+                                 silc_server_command_info,
+                                 silc_server_command_dup(cmd));
+      cmd->pending = TRUE;
+      silc_command_set_ident(cmd->payload, old_ident);
+      silc_buffer_free(tmpbuf);
+      return;
     }
   }
-  
+
+  if (!entry) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
+                                         SILC_STATUS_ERR_NO_SUCH_SERVER);
+    goto out;
+  }
+
+  idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
+  if (!server_info)
+    server_info = entry->server_info;
+  server_name = dest_server;
+
+  /* Send the reply */
+  packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
+                                               SILC_STATUS_OK, ident, 3,
+                                               2, idp->data, idp->len,
+                                               3, server_name, 
+                                               strlen(server_name),
+                                               4, server_info, 
+                                               strlen(server_info));
+  silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
+                         packet->data, packet->len, FALSE);
+    
+  silc_buffer_free(packet);
+  silc_buffer_free(idp);
+
  out:
   silc_server_command_free(cmd);
 }
index 45d0c4604aebce157c205072a97a93c56d430b24..6dac16d1e42fcd9631905543a695b16748883915 100644 (file)
@@ -50,9 +50,11 @@ do {                                                                   \
    they are never sent by server. More maybe added later if need appears. */
 SilcServerCommandReply silc_command_reply_list[] =
 {
-  SILC_SERVER_CMD_REPLY(join, JOIN),
   SILC_SERVER_CMD_REPLY(whois, WHOIS),
+  SILC_SERVER_CMD_REPLY(whowas, WHOWAS),
   SILC_SERVER_CMD_REPLY(identify, IDENTIFY),
+  SILC_SERVER_CMD_REPLY(info, INFO),
+  SILC_SERVER_CMD_REPLY(join, JOIN),
   SILC_SERVER_CMD_REPLY(users, USERS),
 
   { NULL, 0 },
@@ -192,6 +194,7 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
     if (!client)
       return FALSE;
 
+    client->data.registered = TRUE;
     client->mode = mode;
   } else {
     /* We have the client already, update the data */
@@ -221,6 +224,7 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
 
     if (cache) {
       cache->data = nick;
+      cache->data_len = strlen(nick);
       silc_idcache_sort_by_data(global ? server->global_list->clients : 
                                server->local_list->clients);
     }
@@ -255,6 +259,127 @@ SILC_SERVER_CMD_REPLY_FUNC(whois)
   silc_server_command_reply_free(cmd);
 }
 
+/* Caches the received WHOWAS information for a short period of time. */
+
+static char
+silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
+{
+  SilcServer server = cmd->server;
+  int len, id_len;
+  unsigned char *id_data;
+  char *nickname, *username, *realname;
+  SilcClientID *client_id;
+  SilcClientEntry client;
+  SilcIDCacheEntry cache = NULL;
+  char *nick;
+  int global = FALSE;
+
+  id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
+  nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
+  username = silc_argument_get_arg_type(cmd->args, 4, &len);
+  if (!id_data || !nickname || !username)
+    return FALSE;
+
+  realname = silc_argument_get_arg_type(cmd->args, 5, &len);
+
+  client_id = silc_id_payload_parse_id(id_data, id_len);
+  if (!client_id)
+    return FALSE;
+
+  /* Check if we have this client cached already. */
+
+  client = silc_idlist_find_client_by_id(server->local_list, client_id,
+                                        &cache);
+  if (!client) {
+    client = silc_idlist_find_client_by_id(server->global_list, 
+                                          client_id, &cache);
+    global = TRUE;
+  }
+
+  if (!client) {
+    /* If router did not find such Client ID in its lists then this must
+       be bogus client or some router in the net is buggy. */
+    if (server->server_type == SILC_ROUTER)
+      return FALSE;
+
+    /* Take hostname out of nick string if it includes it. */
+    if (strchr(nickname, '@')) {
+      int len = strcspn(nickname, "@");
+      nick = silc_calloc(len + 1, sizeof(char));
+      memcpy(nick, nickname, len);
+    } else {
+      nick = strdup(nickname);
+    }
+
+    /* We don't have that client anywhere, add it. The client is added
+       to global list since server didn't have it in the lists so it must be 
+       global. */
+    client = silc_idlist_add_client(server->global_list, nick,
+                                   strdup(username), 
+                                   strdup(realname), 
+                                   silc_id_dup(client_id, SILC_ID_CLIENT), 
+                                   cmd->sock->user_data, NULL);
+    if (!client)
+      return FALSE;
+
+    client->data.registered = FALSE;
+    client = silc_idlist_find_client_by_id(server->global_list, 
+                                          client_id, &cache);
+    cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
+  } else {
+    /* We have the client already, update the data */
+
+    /* Take hostname out of nick string if it includes it. */
+    if (strchr(nickname, '@')) {
+      int len = strcspn(nickname, "@");
+      nick = silc_calloc(len + 1, sizeof(char));
+      memcpy(nick, nickname, len);
+    } else {
+      nick = strdup(nickname);
+    }
+
+    if (client->nickname)
+      silc_free(client->nickname);
+    if (client->username)
+      silc_free(client->username);
+    
+    client->nickname = nick;
+    client->username = strdup(username);
+
+    if (cache) {
+      cache->data = nick;
+      cache->data_len = strlen(nick);
+      silc_idcache_sort_by_data(global ? server->global_list->clients : 
+                               server->local_list->clients);
+    }
+  }
+
+  silc_free(client_id);
+
+  return TRUE;
+}
+
+/* Received reply for WHOWAS command. Cache the client information only for
+   a short period of time. */
+
+SILC_SERVER_CMD_REPLY_FUNC(whowas)
+{
+  SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
+  SilcCommandStatus status;
+
+  COMMAND_CHECK_STATUS_LIST;
+
+  if (!silc_server_command_reply_whowas_save(cmd))
+    goto out;
+
+  /* Execute any pending commands */
+  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOWAS);
+
+ out:
+  SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOWAS);
+  silc_server_command_reply_free(cmd);
+}
+
 /* Caches the received IDENTIFY information. */
 
 static char
@@ -310,9 +435,10 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
     /* We don't have that client anywhere, add it. The client is added
        to global list since server didn't have it in the lists so it must be 
        global. */
-    silc_idlist_add_client(server->global_list, nick,
-                          username ? strdup(username) : NULL, NULL,
-                          client_id, cmd->sock->user_data, NULL);
+    client = silc_idlist_add_client(server->global_list, nick,
+                                   username ? strdup(username) : NULL, NULL,
+                                   client_id, cmd->sock->user_data, NULL);
+    client->data.registered = TRUE;
   } else {
     /* We have the client already, update the data */
 
@@ -342,6 +468,7 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
 
     if (nickname && cache) {
       cache->data = nick;
+      cache->data_len = strlen(nick);
       silc_idcache_sort_by_data(global ? server->global_list->clients : 
                                server->local_list->clients);
     }
@@ -375,6 +502,64 @@ SILC_SERVER_CMD_REPLY_FUNC(identify)
   silc_server_command_reply_free(cmd);
 }
 
+/* Received reply fro INFO command. Cache the server and its information */
+
+SILC_SERVER_CMD_REPLY_FUNC(info)
+{
+  SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
+  SilcServer server = cmd->server;
+  SilcCommandStatus status;
+  SilcServerEntry entry;
+  SilcServerID *server_id;
+  unsigned int tmp_len;
+  unsigned char *tmp, *name;
+
+  COMMAND_CHECK_STATUS;
+
+  /* Get Server ID */
+  tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+  if (!tmp)
+    goto out;
+  server_id = silc_id_payload_parse_id(tmp, tmp_len);
+  if (!server_id)
+    goto out;
+
+  /* Get the info string */
+  name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
+  if (tmp_len > 256)
+    goto out;
+
+  entry = silc_idlist_find_server_by_id(server->local_list, server_id, NULL);
+  if (!entry) {
+    entry = silc_idlist_find_server_by_id(server->global_list, server_id, 
+                                         NULL);
+    if (!entry) {
+      /* Add the server to global list */
+      server_id = silc_id_dup(server_id, SILC_ID_SERVER);
+      entry = silc_idlist_add_server(server->global_list, name, 0,
+                                    server_id, NULL, NULL);
+      if (!entry) {
+       silc_free(server_id);
+       goto out;
+      }
+    }
+  }
+
+  /* Get the info string */
+  tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
+  if (tmp_len > 256)
+    tmp = NULL;
+
+  entry->server_info = tmp ? strdup(tmp) : NULL;
+
+  /* Execute any pending commands */
+  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
+
+ out:
+  SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_INFO);
+  silc_server_command_reply_free(cmd);
+}
+
 /* Received reply for forwarded JOIN command. Router has created or joined
    the client to the channel. We save some channel information locally
    for future use. */
index 23c1fe6b0a7c350b5ca13147ea76ae5b91df1ac3..0726f108224dd8d074f87b99f1eb66500dedb14d 100644 (file)
@@ -61,9 +61,11 @@ void silc_server_command_reply_free(SilcServerCommandReplyContext cmd);
 void silc_server_command_reply_process(SilcServer server,
                                       SilcSocketConnection sock,
                                       SilcBuffer buffer);
-SILC_SERVER_CMD_REPLY_FUNC(join);
 SILC_SERVER_CMD_REPLY_FUNC(whois);
+SILC_SERVER_CMD_REPLY_FUNC(whowas);
 SILC_SERVER_CMD_REPLY_FUNC(identify);
+SILC_SERVER_CMD_REPLY_FUNC(info);
+SILC_SERVER_CMD_REPLY_FUNC(join);
 SILC_SERVER_CMD_REPLY_FUNC(users);
 
 #endif
index aca1c2812721eecdc43ee94ab6abcb2ee48b16e6..6d0b9030b97e512f721cf46963cd516f3df19c3d 100644 (file)
@@ -68,6 +68,21 @@ void silc_idlist_del_data(void *entry)
     silc_pkcs_public_key_free(idata->public_key);
 }
 
+/* Purges ID cache */
+
+SILC_TASK_CALLBACK_GLOBAL(silc_idlist_purge)
+{
+  SilcIDListPurge i = (SilcIDListPurge)context;
+
+  SILC_LOG_DEBUG(("Start"));
+
+  silc_idcache_purge(i->cache);
+  silc_task_register(i->timeout_queue, 0, 
+                    silc_idlist_purge,
+                    (void *)i, 600, 0,
+                    SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+}
+
 /******************************************************************************
 
                           Server entry functions
@@ -96,8 +111,10 @@ silc_idlist_add_server(SilcIDList id_list,
   server->router = router;
   server->connection = connection;
 
-  if (!silc_idcache_add(id_list->servers, server->server_name, SILC_ID_SERVER,
-                       (void *)server->id, (void *)server, TRUE, FALSE)) {
+  if (!silc_idcache_add(id_list->servers, server->server_name, 
+                       server->server_name ? strlen(server->server_name) : 0,
+                       SILC_ID_SERVER, (void *)server->id, 
+                       (void *)server, TRUE, FALSE)) {
     silc_free(server);
     return NULL;
   }
@@ -151,6 +168,8 @@ silc_idlist_find_server_by_name(SilcIDList id_list, char *name,
   if (ret_entry)
     *ret_entry = id_cache;
 
+  SILC_LOG_DEBUG(("Found"));
+
   return server;
 }
 
@@ -225,6 +244,8 @@ silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
   server->id = new_id;
   id_cache->id = (void *)new_id;
 
+  SILC_LOG_DEBUG(("Found"));
+
   return server;
 }
 
@@ -283,8 +304,10 @@ silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname,
   silc_list_init(client->channels, struct SilcChannelClientEntryStruct, 
                 client_list);
 
-  if (!silc_idcache_add(id_list->clients, nickname, SILC_ID_CLIENT,
-                       (void *)client->id, (void *)client, TRUE, FALSE)) {
+  if (!silc_idcache_add(id_list->clients, nickname, 
+                       nickname ? strlen(nickname) : 0,
+                       SILC_ID_CLIENT, (void *)client->id, 
+                       (void *)client, TRUE, FALSE)) {
     silc_free(client);
     return NULL;
   }
@@ -335,6 +358,8 @@ silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
   SilcClientEntry *clients;
   int i;
 
+  SILC_LOG_DEBUG(("Start"));
+
   if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
     return NULL;
 
@@ -369,6 +394,8 @@ silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
   unsigned char hash[32];
   int i;
 
+  SILC_LOG_DEBUG(("Start"));
+
   silc_hash_make(md5hash, nickname, strlen(nickname), hash);
 
   if (!silc_idcache_find_by_data(id_list->clients, hash, &list))
@@ -608,8 +635,9 @@ silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
                 channel_list);
 
   if (!silc_idcache_add(id_list->channels, channel->channel_name, 
-                       SILC_ID_CHANNEL, (void *)channel->id, 
-                       (void *)channel, TRUE, FALSE)) {
+                       channel->channel_name ? strlen(channel->channel_name) :
+                       0, SILC_ID_CHANNEL, 
+                       (void *)channel->id, (void *)channel, TRUE, FALSE)) {
     silc_free(channel);
     return NULL;
   }
index bcd3c3f143095549fc6693c2fc5a7202a14e33b5..59d6282d5ce798f6b249e55c4923b09808da34d2 100644 (file)
@@ -26,6 +26,13 @@ typedef struct SilcServerEntryStruct *SilcServerEntry;
 typedef struct SilcClientEntryStruct *SilcClientEntry;
 typedef struct SilcChannelEntryStruct *SilcChannelEntry;
 
+/* Context for holding cache information to periodically purge
+   the cache. */
+typedef struct {
+  SilcIDCache cache;
+  void *timeout_queue;
+} *SilcIDListPurge;
+
 /*
    Generic ID list data structure.
 
@@ -126,6 +133,7 @@ struct SilcServerEntryStruct {
   char *server_name;
   int server_type;
   SilcServerID *id;
+  char *server_info;
 
   /* Pointer to the router */
   SilcServerEntry router;
@@ -460,6 +468,7 @@ typedef struct {
 /* Prototypes */
 void silc_idlist_add_data(void *entry, SilcIDListData idata);
 void silc_idlist_del_data(void *entry);
+SILC_TASK_CALLBACK_GLOBAL(silc_idlist_purge);
 SilcServerEntry 
 silc_idlist_add_server(SilcIDList id_list, 
                       char *server_name, int server_type,
index e01f55f64ff58bbb8fdca196ee189299cce74124..98fb540b183b323e25e99694e0472c6087d6aac9 100644 (file)
@@ -42,6 +42,7 @@ void silc_server_notify(SilcServer server,
   SilcChannelEntry channel;
   SilcClientEntry client;
   SilcChannelClientEntry chl;
+  SilcIDCacheEntry cache;
   unsigned int mode;
   unsigned char *tmp;
   unsigned int tmp_len;
@@ -154,6 +155,8 @@ void silc_server_notify(SilcServer server,
          silc_free(client_id);
          goto out;
        }
+
+       client->data.registered = TRUE;
       }
     }
 
@@ -251,10 +254,10 @@ void silc_server_notify(SilcServer server,
 
     /* Get client entry */
     client = silc_idlist_find_client_by_id(server->global_list, 
-                                          client_id, NULL);
+                                          client_id, &cache);
     if (!client) {
       client = silc_idlist_find_client_by_id(server->local_list, 
-                                            client_id, NULL);
+                                            client_id, &cache);
       if (!client) {
        silc_free(client_id);
        goto out;
@@ -270,9 +273,14 @@ void silc_server_notify(SilcServer server,
     /* Remove the client from all channels */
     silc_server_remove_from_channels(server, NULL, client, TRUE, tmp, TRUE);
 
+    client->data.registered = FALSE;
+    cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
+
+#if 0
     /* Remove the client entry */
     if (!silc_idlist_del_client(server->global_list, client))
       silc_idlist_del_client(server->local_list, client);
+#endif
     break;
 
   case SILC_NOTIFY_TYPE_TOPIC_SET:
@@ -1142,7 +1150,7 @@ SilcServerEntry silc_server_new_server(SilcServer server,
   SilcServerID *server_id;
   SilcIDListData idata;
   unsigned char *server_name, *id_string;
-  unsigned short id_len;
+  unsigned short id_len, name_len;
   int ret;
 
   SILC_LOG_DEBUG(("Creating new server"));
@@ -1165,7 +1173,8 @@ SilcServerEntry silc_server_new_server(SilcServer server,
   /* Parse the incoming packet */
   ret = silc_buffer_unformat(buffer,
                             SILC_STR_UI16_NSTRING_ALLOC(&id_string, &id_len),
-                            SILC_STR_UI16_STRING_ALLOC(&server_name),
+                            SILC_STR_UI16_NSTRING_ALLOC(&server_name, 
+                                                        &name_len),
                             SILC_STR_END);
   if (ret == -1) {
     if (id_string)
@@ -1181,6 +1190,9 @@ SilcServerEntry silc_server_new_server(SilcServer server,
     return NULL;
   }
 
+  if (name_len > 256)
+    server_name[255] = '\0';
+
   /* Get Server ID */
   server_id = silc_id_str2id(id_string, id_len, SILC_ID_SERVER);
   if (!server_id) {
@@ -1289,13 +1301,14 @@ static void silc_server_new_id_real(SilcServer server,
         list. The client is put to global list and we will take the hash
         value of the Client ID and save it to the ID Cache system for fast
         searching in the future. */
-      hash = silc_calloc(sizeof(((SilcClientID *)id)->hash), 
+      hash = silc_calloc(sizeof(((SilcClientID *)id)->hash),
                         sizeof(unsigned char));
       memcpy(hash, ((SilcClientID *)id)->hash, 
             sizeof(((SilcClientID *)id)->hash));
       entry = silc_idlist_add_client(id_list, hash, NULL, NULL, id, 
                                     router, NULL);
       entry->nickname = NULL;
+      entry->data.registered = TRUE;
 
       if (sock->type == SILC_SOCKET_TYPE_SERVER)
        server->stat.cell_clients++;
index 87ceee969f2f9c2fc469e7e4ab93f195d0d15692..999c24b60a6f6f8a893396354a5cc39280321e0b 100644 (file)
@@ -113,6 +113,7 @@ int silc_server_init(SilcServer server)
   int *sock = NULL, sock_count = 0, i;
   SilcServerID *id;
   SilcServerEntry id_entry;
+  SilcIDListPurge purge;
 
   SILC_LOG_DEBUG(("Initializing server"));
   assert(server);
@@ -335,6 +336,27 @@ int silc_server_init(SilcServer server)
   if (server->config->servers)
     server->server_type = SILC_ROUTER;
 
+  /* Register the ID Cache purge task. This periodically purges the ID cache
+     and removes the expired cache entries. */
+
+  /* Clients local list */
+  purge = silc_calloc(1, sizeof(*purge));
+  purge->cache = server->local_list->clients;
+  purge->timeout_queue = server->timeout_queue;
+  silc_task_register(purge->timeout_queue, 0, 
+                    silc_idlist_purge,
+                    (void *)purge, 600, 0,
+                    SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+
+  /* Clients global list */
+  purge = silc_calloc(1, sizeof(*purge));
+  purge->cache = server->global_list->clients;
+  purge->timeout_queue = server->timeout_queue;
+  silc_task_register(purge->timeout_queue, 0, 
+                    silc_idlist_purge,
+                    (void *)purge, 300, 0,
+                    SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+
   SILC_LOG_DEBUG(("Server initialized"));
 
   /* We are done here, return succesfully */
@@ -3087,6 +3109,8 @@ void silc_server_save_users_on_channel(SilcServer server,
        silc_free(client_id);
        continue;
       }
+
+      client->data.registered = TRUE;
     }
 
     silc_free(client_id);
@@ -3215,6 +3239,8 @@ SilcBuffer silc_server_get_client_channel_list(SilcServer server,
     silc_free(cid);
   }
 
-  silc_buffer_push(buffer, buffer->data - buffer->head);
+  if (buffer)
+    silc_buffer_push(buffer, buffer->data - buffer->head);
+
   return buffer;
 }
index 9948361e405f855127b7d7c2bf085ffa4dbb1fa3..7140f1186bdf256c2edb5f0cf63a43123dbb537a 100644 (file)
@@ -1,17 +1,23 @@
 [Cipher]
-rc6:../lib/silcsim/modules/rc6.sim.so:16:16
-twofish:../lib/silcsim/modules/twofish.sim.so:16:16
-mars:../lib/silcsim/modules/mars.sim.so:16:16
+aes-256-cbc:../lib/silcsim/modules/aes.sim.so:32:16
+aes-192-cbc:../lib/silcsim/modules/aes.sim.so:24:16
+aes-128-cbc:../lib/silcsim/modules/aes.sim.so:16:16
+twofish-256-cbc:../lib/silcsim/modules/twofish.sim.so:32:16
+twofish-192-cbc:../lib/silcsim/modules/twofish.sim.so:24:16
+twofish-128-cbc:../lib/silcsim/modules/twofish.sim.so:16:16
+mars-256-cbc:../lib/silcsim/modules/mars.sim.so:32:16
+mars-192-cbc:../lib/silcsim/modules/mars.sim.so:24:16
+mars-128-cbc:../lib/silcsim/modules/mars.sim.so:16:16
 none:../lib/silcsim/modules/none.sim.so:0:0
 
-[Hash] 
+[Hash]
 md5::64:16
 sha1::64:20
 
 [hmac]
 hmac-sha1-96:sha1:12
 hmac-md5-96:md5:12
-hmac-sha1:sha1:20
+hmac-sha1:sha1:20   
 hmac-md5:md5:16
 
 #[PKCS]
@@ -25,10 +31,10 @@ nobody:nobody
 Mun huone:Mun servo:Pekka Riikonen:priikone@poseidon.pspt.fi
 
 [ServerInfo]
-lassi.kuo.fi.ssh.com:10.2.1.7:Kuopio, Finland:1334
+silc:212.146.42.253:Kuopio, Finland:1334
 
 [ListenPort]
-10.2.1.7:10.2.1.7:1334
+212.146.42.253:212.146.42.253:1334
 
 [Logging]
 infologfile:silcd2.log:10000
@@ -47,13 +53,13 @@ errorlogfile:silcd2.log:10000
 :::1336:1
 
 [AdminConnection]
-*:silc:silc:passwd:testi
+*:priikone:*:passwd:testi
 
 [ServerConnection]
-10.2.1.7:passwd:priikone:1333:1:1
+212.146.42.253:passwd:priikone:1336:1:1
 
 [RouterConnection]
-10.2.1.7:passwd:priikone:1335:1:1:0
+212.146.42.253:passwd:priikone:1335:1:1:0
 
 [DenyConnection]
 [RedirectClient]
index 5a4799bd01aa9be309ef25de50f4208a99b9a7c8..8c238d8c5f79f3a32a52cc490c1f1bf1285cae9e 100644 (file)
@@ -2362,9 +2362,9 @@ List of all defined commands in SILC follows.
 
         Reply messages to the command:
 
-        Max Arguments:  3
+        Max Arguments:  4
             Arguments:  (1) <Status Payload>  (2) <Server ID>
-                        (3) <string>
+                        (3) <server name>     (4) <string>
 
         This command replies with the Server ID of the server and a
         string which tells the information about the server.
index ed9bc13a9b200fd09be5387dcd4afa53ac0312a3..ae08c2ffc0dacbb8d0847391033ae9b05a99b14e 100644 (file)
@@ -1128,8 +1128,9 @@ void silc_client_receive_new_id(SilcClient client,
   conn->local_entry->id = conn->local_id;
   
   /* Put it to the ID cache */
-  silc_idcache_add(conn->client_cache, conn->nickname, SILC_ID_CLIENT,
-                  conn->local_id, (void *)conn->local_entry, TRUE, FALSE);
+  silc_idcache_add(conn->client_cache, conn->nickname, strlen(conn->nickname),
+                  SILC_ID_CLIENT, conn->local_id, (void *)conn->local_entry,
+                  TRUE, FALSE);
 
   /* Notify application of successful connection. We do it here now that
      we've received the Client ID and are allowed to send traffic. */
@@ -1161,8 +1162,9 @@ SilcChannelEntry silc_client_new_channel_id(SilcClient client,
   conn->current_channel = channel;
 
   /* Put it to the ID cache */
-  silc_idcache_add(conn->channel_cache, channel_name, SILC_ID_CHANNEL,
-                  (void *)channel->id, (void *)channel, TRUE, FALSE);
+  silc_idcache_add(conn->channel_cache, channel_name, strlen(channel_name),
+                  SILC_ID_CHANNEL, (void *)channel->id, (void *)channel, 
+                  TRUE, FALSE);
 
   return channel;
 }
index 3fe00aaf30aa5653dbd9ac2b794ee1fe176bfa9c..c9d198c4b046577cf8bf0d421f74a7187ab2fba2 100644 (file)
@@ -177,8 +177,8 @@ void silc_client_private_message(SilcClient client,
       
       /* Save the client to cache */
       silc_idcache_add(conn->client_cache, remote_client->nickname,
-                      SILC_ID_CLIENT, remote_client->id, remote_client
-                      TRUE, TRUE);
+                      strlen(remote_client->nickname), SILC_ID_CLIENT
+                      remote_client->id, remote_client, TRUE, TRUE);
     } else {
       remote_client = (SilcClientEntry)id_cache->context;
     }
index ec64040bd95ac268a35c96aca57cf4f08439a2c9..91579710086e88fe3a8c73adc2838afe94a3b267 100644 (file)
@@ -264,6 +264,7 @@ silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd,
     
     /* Add client to cache */
     silc_idcache_add(conn->client_cache, client_entry->nickname,
+                    strlen(client_entry->nickname),
                     SILC_ID_CLIENT, client_id, (void *)client_entry, 
                     TRUE, FALSE);
   } else {
@@ -287,6 +288,7 @@ silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd,
       client_entry->realname = strdup(realname);
 
     id_cache->data = client_entry->nickname;
+    id_cache->data_len = strlen(client_entry->nickname);
     silc_idcache_sort_by_data(conn->client_cache);
 
     silc_free(client_id);
@@ -462,6 +464,7 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd,
     
     /* Add client to cache */
     silc_idcache_add(conn->client_cache, client_entry->nickname,
+                    strlen(client_entry->nickname),
                     SILC_ID_CLIENT, client_id, (void *)client_entry, 
                     TRUE, FALSE);
   } else {
@@ -482,6 +485,7 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd,
       client_entry->username = strdup(username);
     
     id_cache->data = client_entry->nickname;
+    id_cache->data_len = strlen(client_entry->nickname);
     silc_idcache_sort_by_data(conn->client_cache);
     
     silc_free(client_id);
@@ -749,11 +753,16 @@ SILC_CLIENT_CMD_REPLY_FUNC(info)
 
   /* XXX save server id */
 
-  /* Get server info */
+  /* Get server name */
   tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
   if (!tmp)
     goto out;
 
+  /* Get server info */
+  tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
+  if (!tmp)
+    goto out;
+
   client->ops->say(cmd->client, conn, "Info: %s", tmp);
 
   /* Notify application */
@@ -970,7 +979,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
       /* No, we don't have it, add entry for it. */
       client_entry = silc_calloc(1, sizeof(*client_entry));
       client_entry->id = silc_id_dup(client_id, SILC_ID_CLIENT);
-      silc_idcache_add(conn->client_cache, NULL, SILC_ID_CLIENT, 
+      silc_idcache_add(conn->client_cache, NULL, 0, SILC_ID_CLIENT, 
                       client_entry->id, (void *)client_entry, FALSE, FALSE);
     } else {
       /* Yes, we have it already */
index 6c836514941aeac007b2efe154c57babeb862083..5d8d793c145afe72d416880ac9cdf12694cdd217 100644 (file)
@@ -200,7 +200,7 @@ int silc_idcache_find_by_data(SilcIDCache cache, unsigned char *data,
       break;
 
     if (cache->cache[i].data && 
-       !memcmp(cache->cache[i].data, data, strlen(cache->cache[i].data)))
+       !memcmp(cache->cache[i].data, data, cache->cache[i].data_len))
       silc_idcache_list_add(list, &(cache->cache[i]));
   }
 
@@ -236,7 +236,7 @@ int silc_idcache_find_by_data_one(SilcIDCache cache, unsigned char *data,
 
   for (i = i; i < cache->cache_count; i++)
     if (cache->cache[i].data && 
-       !memcmp(cache->cache[i].data, data, strlen(cache->cache[i].data))) {
+       !memcmp(cache->cache[i].data, data, cache->cache[i].data_len)) {
       if (ret)
        *ret = &(cache->cache[i]);
       return TRUE;
@@ -391,8 +391,8 @@ int silc_idcache_find_by_context(SilcIDCache cache, void *context,
    however, it is not mandatory. */
 
 int silc_idcache_add(SilcIDCache cache, unsigned char *data, 
-                    SilcIdType id_type, void *id, void *context, int sort,
-                    int expire)
+                    unsigned int data_len, SilcIdType id_type, void *id, 
+                    void *context, int sort, int expire)
 {
   int i;
   unsigned int count;
@@ -420,6 +420,7 @@ int silc_idcache_add(SilcIDCache cache, unsigned char *data,
   for (i = 0; i < count; i++) {
     if (c[i].data == NULL && c[i].id == NULL) {
       c[i].data = data;
+      c[i].data_len = data_len;
       c[i].type = id_type;
       c[i].id = id;
       c[i].expire = (expire ? (curtime + SILC_ID_CACHE_EXPIRE) : 0);
@@ -435,6 +436,7 @@ int silc_idcache_add(SilcIDCache cache, unsigned char *data,
       c[i].id = NULL;
     }
     c[count].data = data;
+    c[count].data_len = data_len;
     c[count].type = id_type;
     c[count].id = id;
     c[count].expire = (expire ? (curtime + SILC_ID_CACHE_EXPIRE) : 0);
@@ -521,7 +523,7 @@ int silc_idcache_purge(SilcIDCache cache)
   c = cache->cache;
 
   for (i = 0; i < cache->cache_count; i++) {
-    if (c[i].data && c[i].expire < curtime) {
+    if (c[i].data && c[i].expire && c[i].expire < curtime) {
 
       /* Call the destructor */
       if (cache->destructor)
index 492ecfb7cd041ea75950d7b3fe07f29729c621f3..84682bb0016938951d0670480eddd0594c716ce0 100644 (file)
@@ -30,6 +30,7 @@
    allocate any of these fields nor free them.
 
    unsigned char *data
+   unsigned int data_len;
 
       The data that is usually used to find the data from the cache.
       For example for Client ID's this is nickname.
@@ -56,6 +57,7 @@
 */
 typedef struct {
   unsigned char *data;
+  unsigned int data_len;
   SilcIdType type;
   void *id;
   unsigned long expire;
@@ -78,6 +80,7 @@ typedef void (*SilcIDCacheDestructor)(SilcIDCache cache,
 #define SILC_ID_CACHE_ANY ((void *)1)
 
 #define SILC_ID_CACHE_EXPIRE 3600
+#define SILC_ID_CACHE_EXPIRE_DEF (time(NULL) + SILC_ID_CACHE_EXPIRE)
 
 /* Prototypes */
 SilcIDCache silc_idcache_alloc(unsigned int count,
@@ -97,8 +100,8 @@ int silc_idcache_find_by_id_one(SilcIDCache cache, void *id, SilcIdType type,
 int silc_idcache_find_by_context(SilcIDCache cache, void *context, 
                                 SilcIDCacheEntry *ret);
 int silc_idcache_add(SilcIDCache cache, unsigned char *data, 
-                    SilcIdType id_type, void *id, void *context, int sort,
-                    int expire);
+                    unsigned int data_len, SilcIdType id_type, void *id, 
+                    void *context, int sort, int expire);
 int silc_idcache_del(SilcIDCache cache, SilcIDCacheEntry old);
 int silc_idcache_del_by_data(SilcIDCache cache, unsigned char *data);
 int silc_idcache_del_by_id(SilcIDCache cache, SilcIdType type, void *id);