updates. silc.toolkit.0.7
authorPekka Riikonen <priikone@silcnet.org>
Mon, 3 Dec 2001 20:29:51 +0000 (20:29 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 3 Dec 2001 20:29:51 +0000 (20:29 +0000)
23 files changed:
CHANGES
TODO
apps/irssi/src/silc/core/client_ops.c
apps/irssi/src/silc/core/silc-servers.h
apps/silcd/command.c
apps/silcd/command_reply.c
apps/silcd/idlist.c
apps/silcd/idlist.h
apps/silcd/packet_receive.c
apps/silcd/packet_send.c
apps/silcd/packet_send.h
apps/silcd/server.c
apps/silcd/server_util.c
lib/LIBINDEX
lib/silcclient/client.c
lib/silcclient/client_notify.c
lib/silcclient/command.c
lib/silcclient/command_reply.c
lib/silcclient/idlist.c
lib/silccore/silcidcache.c
lib/silccore/silcidcache.h
prepare
silc_optimize

diff --git a/CHANGES b/CHANGES
index e261a9c791a6b106b34ed413ff0d2ff199c60f18..af0fee613c80cb74dd1261808addce3bab69b4fc 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,34 @@
+Mon Dec  3 18:49:45 EET 2001  Pekka Riikonen <priikone@silcnet.org>
+
+       * Do not print "you are now server operator" or similar when
+         giving /away command.  Affected files are
+         irssi/src/silc/core/client_ops.c, silc-servers.h.
+
+       * Made the silc_server_command_pending_error_check to send
+         the same command reply payload it received back to the
+         original sender of the command.  This way all arguments
+         that was received by the server will be received by the
+         client too.  Affected file silcd/command.c.
+
+       * Added the silc_idcache_add to return the created cache entry
+         to a pointer.  Affected file lib/silccore/silcidcache.[ch].
+
+       * Add global clients to expire if they are not on any channel.
+         This is because normal server will never know if they signoff
+         if they are not on any channel.  The cache expiry will take
+         case of these entries.  This is done by normal servers only.
+         The affected files are silcd/command_reply.c,
+         silcd/idlist.[ch], silcd/server and silcd/packet_receive.c.
+
+       * If server receives invalid ID notification for WHOIS or
+         IDENTIFY and the ID exists in the lists, it is removed.
+         Affected file silcd/command_reply.c.
+
+       * If NO_SUCH_CLIENT_ID is received for WHOIS or IDENTIFY command
+         in client then client entry that it matches is searched and
+         the nickname is printed on the screen for user.  Affected
+         file irssi/src/silc/core/client_ops.c.
+
 Mon Dec  3 11:56:59 EET 2001  Pekka Riikonen <priikone@silcnet.org>
 
        * Use cache entry expire time in the LIST command reply to
diff --git a/TODO b/TODO
index 22dbc70afee6ad8179cd9997dffd82488041c628..0d1cdb587526b1ce98f1514045c3f7b8ccf1eed1 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,9 +1,6 @@
 TODO/bugs in Irssi SILC client
 ==============================
 
- o Setting /away prints server/router operator modes as well.
-   Print modes that was just set only.
-
  o Add local command to switch the channel's private key when channel has
    several private keys.  Currently sending channel messages with many
    keys is not possible because changing the key is not possible by the
@@ -33,17 +30,21 @@ TODO/bugs in Irssi SILC client
 TODO/bugs In SILC Client Library
 ================================
 
- o N/A
+ o Process the NO_SUCH_CLIENT_ID for WHOIS and IDENTIFY, since it can
+   be received for example after sending MSG to non-existent client.
+   It actually should be done always when it is received and the old
+   entry should be removed.
+
+   Doing this now however causes that /msg nick might give "no such nick"
+   for the first time, and then after the entry is removed /msg nick
+   may actually to go any nick client, which is not desired behaviour.
+   The /msg must be fixed to use the specific nickname user typed 
+   (nick must not match nick@host).
 
 
 TODO/bugs In SILC Server
 ========================
 
- o Make the silc_server_command_pending_error_check function to
-   take all arguments it received and put them to the reply it is 
-   sending.  Otherwise for example WHOIS on normal server for bogus
-   nickname does not print anything in the client.
-
  o Backup router related issues
 
        o Channel user mode changes are notified unnecessarely when
index 9d7d7d86828499030bb7d5826a2a91dc28a42464..76be0744d7adff60ffb07546cc97a1a56d37010b 100644 (file)
@@ -406,15 +406,33 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
       SilcBuffer channels;
       SilcClientEntry client_entry;
       
-      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);
+      if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
+       /* Print the unknown nick for user */
+       unsigned char *tmp =
+         silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
+                                    3, NULL);
        if (tmp)
          silc_say_error("%s: %s", tmp, 
                         silc_client_command_status_message(status));
        break;
+      } else if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
+       /* Try to find the entry for the unknown client ID, since we
+          might have, and print the nickname of it for user. */
+       uint32 tmp_len;
+       unsigned char *tmp =
+         silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
+                                    2, &tmp_len);
+       if (tmp) {
+         SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
+         if (client_id) {
+           client_entry = silc_client_get_client_by_id(client, conn,
+                                                       client_id);
+           if (client_entry && client_entry->nickname)
+             silc_say_error("%s: %s", client_entry->nickname,
+                            silc_client_command_status_message(status));
+           silc_free(client_id);
+         }
+       }
       }
       
       if (!success)
@@ -499,6 +517,45 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
     }
     break;
     
+  case SILC_COMMAND_IDENTIFY:
+    {
+      SilcClientEntry client_entry;
+      
+      /* Identify command is used only internally by the client library
+        but it still might send some interesting stuff for user interface
+        so let's print errors. */
+      
+      if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
+       /* Print the unknown nick for user */
+       unsigned char *tmp =
+         silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
+                                    3, NULL);
+       if (tmp)
+         silc_say_error("%s: %s", tmp, 
+                        silc_client_command_status_message(status));
+       break;
+      } else if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
+       /* Try to find the entry for the unknown client ID, since we
+          might have, and print the nickname of it for user. */
+       uint32 tmp_len;
+       unsigned char *tmp =
+         silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
+                                    2, &tmp_len);
+       if (tmp) {
+         SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
+         if (client_id) {
+           client_entry = silc_client_get_client_by_id(client, conn,
+                                                       client_id);
+           if (client_entry && client_entry->nickname)
+             silc_say_error("%s: %s", client_entry->nickname,
+                            silc_client_command_status_message(status));
+           silc_free(client_id);
+         }
+       }
+      }
+    }
+    break;
+
   case SILC_COMMAND_WHOWAS:
     {
       char *nickname, *username, *realname;
@@ -662,13 +719,17 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
       
       mode = va_arg(vp, uint32);
       
-      if (mode & SILC_UMODE_SERVER_OPERATOR)
+      if (mode & SILC_UMODE_SERVER_OPERATOR &&
+         !(server->umode & SILC_UMODE_SERVER_OPERATOR))
        printformat_module("fe-common/silc", server, NULL,
                           MSGLEVEL_CRAP, SILCTXT_SERVER_OPER);
 
-      if (mode & SILC_UMODE_ROUTER_OPERATOR)
+      if (mode & SILC_UMODE_ROUTER_OPERATOR &&
+         !(server->umode & SILC_UMODE_ROUTER_OPERATOR))
        printformat_module("fe-common/silc", server, NULL,
                           MSGLEVEL_CRAP, SILCTXT_ROUTER_OPER);
+
+      server->umode = mode;
     }
     break;
     
index 7add2f55494dc71f66ee9cdab5924a228a44c019..c90b84f35ac2c7814cc8cfb6b4de65f433455e82 100644 (file)
@@ -56,6 +56,7 @@ typedef struct {
   
   gpointer chanqueries;
   SilcClientConnection conn;
+  uint32 umode;
 } SILC_SERVER_REC;
 
 SILC_SERVER_REC *silc_server_connect(SILC_SERVER_CONNECT_REC *conn);
index ae85305af7b0f85f6dcc622633f16ba7ed430c1f..a1e5e16c7d953022651e80ab7c22033429f60115 100644 (file)
@@ -439,8 +439,16 @@ silc_server_command_pending_error_check(SilcServerCommandContext cmd,
       status != SILC_STATUS_LIST_START &&
       status != SILC_STATUS_LIST_ITEM &&
       status != SILC_STATUS_LIST_END) {
-    /* Send the error message */
-    silc_server_command_send_status_reply(cmd, command, status);
+    SilcBuffer buffer;
+
+    /* Send the same command reply payload */
+    silc_command_set_ident(cmdr->payload, 
+                          silc_command_get_ident(cmd->payload));
+    buffer = silc_command_payload_encode_payload(cmdr->payload);
+    silc_server_packet_send(cmd->server, cmd->sock,
+                           SILC_PACKET_COMMAND_REPLY, 0, 
+                           buffer->data, buffer->len, FALSE);
+    silc_buffer_free(buffer);
     return TRUE;
   }
 
@@ -2018,7 +2026,7 @@ SILC_SERVER_CMD_FUNC(nick)
 
   /* Update client cache */
   silc_idcache_add(server->local_list->clients, client->nickname, 
-                  client->id, (void *)client, FALSE);
+                  client->id, (void *)client, 0, NULL);
 
   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
 
index 5bf79b6aaa1b48e3e87d88522c297d165d1562fa..56c222263714c293046d1259d11bfbb21059cd5f 100644 (file)
@@ -140,6 +140,7 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
   char global = FALSE;
   char *nick;
   uint32 mode = 0, len, id_len, flen;
+  int expire = 0;
 
   id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
   nickname = silc_argument_get_arg_type(cmd->args, 3, &len);
@@ -188,7 +189,8 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
     client = silc_idlist_add_client(server->global_list, nick, 
                                    strdup(username), 
                                    strdup(realname), client_id, 
-                                   cmd->sock->user_data, NULL);
+                                   cmd->sock->user_data, NULL, 
+                                   time(NULL) + 300);
     if (!client) {
       SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
       return FALSE;
@@ -224,10 +226,16 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
     client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
     client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
 
+    /* If client is global and is not on any channel then add that we'll
+       expire the entry after a while. */
+    if (global && !silc_hash_table_count(client->channels) &&
+       server->server_type == SILC_SERVER)
+      expire = time(NULL) + 300;
+
     /* Create new cache entry */
     silc_idcache_add(global ? server->global_list->clients :
                     server->local_list->clients, nick, client->id, 
-                    client, FALSE);
+                    client, expire, NULL); 
     silc_free(client_id);
   }
 
@@ -246,6 +254,7 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
 SILC_SERVER_CMD_REPLY_FUNC(whois)
 {
   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
+  SilcServer server = cmd->server;
   SilcCommandStatus status;
 
   COMMAND_CHECK_STATUS_LIST;
@@ -261,6 +270,27 @@ SILC_SERVER_CMD_REPLY_FUNC(whois)
   }
 
  out:
+  /* If we received notify for invalid ID we'll remove the ID if we
+     have it cached. */
+  if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
+      cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
+    SilcClientEntry client;
+    uint32 tmp_len;
+    unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+    if (tmp) {
+      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
+      if (client_id) {
+       SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
+                       "the entry from cache"));
+       client = silc_idlist_find_client_by_id(server->global_list, 
+                                              client_id, FALSE, NULL);
+       if (client)
+         silc_idlist_del_client(server->global_list, client);
+       silc_free(client_id);
+      }
+    }
+  }
+
   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
   SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_WHOIS);
   silc_server_command_reply_free(cmd);
@@ -318,16 +348,14 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
     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);
+                                   cmd->sock->user_data, NULL,
+                                   SILC_ID_CACHE_EXPIRE_DEF);
     if (!client) {
       SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
       return FALSE;
     }
 
     client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED; 
-    client = silc_idlist_find_client_by_id(server->global_list, 
-                                          client_id, TRUE, &cache);
-    cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
     client->servername = servername;
   } else {
     /* We have the client already, update the data */
@@ -347,7 +375,7 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
                                server->local_list->clients, client);
     silc_idcache_add(global ? server->global_list->clients :
                     server->local_list->clients, nick, client->id, 
-                    client, FALSE);
+                    client, 0, NULL);
   }
 
   silc_free(client_id);
@@ -400,6 +428,7 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
   char *nick = NULL;
   SilcIDPayload idp = NULL;
   SilcIdType id_type;
+  int expire = 0;
 
   id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
   if (!id_data)
@@ -443,7 +472,8 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
         global. */
       client = silc_idlist_add_client(server->global_list, nick, 
                                      info ? strdup(info) : NULL, NULL,
-                                     client_id, cmd->sock->user_data, NULL);
+                                     client_id, cmd->sock->user_data, NULL,
+                                     time(NULL) + 300);
       if (!client) {
        SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
        goto error;
@@ -477,10 +507,16 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
       client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
       
       if (name) {
+       /* If client is global and is not on any channel then add that we'll
+          expire the entry after a while. */
+       if (global && !silc_hash_table_count(client->channels) &&
+           server->server_type == SILC_SERVER)
+         expire = time(NULL) + 300;
+
        /* Add new cache entry */
        silc_idcache_add(global ? server->global_list->clients :
                         server->local_list->clients, nick, client->id, 
-                        client, FALSE);
+                        client, expire, NULL);
       }
 
       silc_free(client_id);
@@ -550,8 +586,7 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
       /* We don't have that server anywhere, add it. */
       channel = silc_idlist_add_channel(server->global_list, strdup(name),
                                        SILC_CHANNEL_MODE_NONE, channel_id, 
-                                       server->router, 
-                                       NULL, NULL);
+                                       server->router, NULL, NULL, 0);
       if (!channel) {
        silc_free(channel_id);
        goto error;
@@ -579,6 +614,7 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
 SILC_SERVER_CMD_REPLY_FUNC(identify)
 {
   SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
+  SilcServer server = cmd->server;
   SilcCommandStatus status;
 
   COMMAND_CHECK_STATUS_LIST;
@@ -594,6 +630,27 @@ SILC_SERVER_CMD_REPLY_FUNC(identify)
   }
 
  out:
+  /* If we received notify for invalid ID we'll remove the ID if we
+     have it cached. */
+  if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID &&
+      cmd->sock->type == SILC_SOCKET_TYPE_ROUTER) {
+    SilcClientEntry client;
+    uint32 tmp_len;
+    unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+    if (tmp) {
+      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len);
+      if (client_id) {
+       SILC_LOG_DEBUG(("Received invalid client ID notification, deleting "
+                       "the entry from cache"));
+       client = silc_idlist_find_client_by_id(server->global_list, 
+                                              client_id, FALSE, NULL);
+       if (client)
+         silc_idlist_del_client(server->global_list, client);
+       silc_free(client_id);
+      }
+    }
+  }
+
   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_IDENTIFY);
   SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_IDENTIFY);
   silc_server_command_reply_free(cmd);
@@ -821,7 +878,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
     /* Add the channel to our local list. */
     entry = silc_idlist_add_channel(server->local_list, strdup(channel_name), 
                                    SILC_CHANNEL_MODE_NONE, id, 
-                                   server->router, NULL, hmac);
+                                   server->router, NULL, hmac, 0);
     if (!entry) {
       silc_free(id);
       goto out;
@@ -1100,6 +1157,7 @@ SILC_SERVER_CMD_REPLY_FUNC(list)
   uint32 len;
   unsigned char *tmp, *name, *topic;
   uint32 usercount = 0;
+  bool global_list = FALSE;
 
   COMMAND_CHECK_STATUS_LIST;
 
@@ -1117,9 +1175,11 @@ SILC_SERVER_CMD_REPLY_FUNC(list)
   /* Add the channel entry if we do not have it already */
   channel = silc_idlist_find_channel_by_name(server->local_list, 
                                             name, &cache);
-  if (!channel)
+  if (!channel) {
     channel = silc_idlist_find_channel_by_name(server->global_list, 
                                               name, &cache);
+    global_list = TRUE;
+  }
   if (!channel) {
     /* If router did not find such channel in its lists then this must
        be bogus channel or some router in the net is buggy. */
@@ -1128,19 +1188,15 @@ SILC_SERVER_CMD_REPLY_FUNC(list)
     
     channel = silc_idlist_add_channel(server->global_list, strdup(name),
                                      SILC_CHANNEL_MODE_NONE, channel_id, 
-                                     server->router, NULL, NULL);
+                                     server->router, NULL, NULL, 
+                                     time(NULL) + 60);
     if (!channel)
       goto out;
-
-    /* Update cache entry expiry */
-    if (silc_idlist_find_channel_by_id(server->global_list, channel_id, 
-                                      &cache))
-      cache->expire = time(NULL) + 60;
-
     channel_id = NULL;
   } else {
     /* Found, update expiry */
-    cache->expire = time(NULL) + 60;
+    if (global_list && server->server_type == SILC_SERVER)
+      cache->expire = time(NULL) + 60;
   }
 
   if (topic) {
index fa084ec69496e6349eacc35489e03431b6c57ee8..502744eb3e9ad2400e866b0285331dbf7db7e34d 100644 (file)
@@ -88,7 +88,7 @@ SILC_TASK_CALLBACK_GLOBAL(silc_idlist_purge)
   silc_idcache_purge(i->cache);
   silc_schedule_task_add(i->schedule, 0, 
                         silc_idlist_purge,
-                        (void *)i, 600, 0,
+                        (void *)i, i->timeout, 0,
                         SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
 }
 
@@ -121,7 +121,7 @@ silc_idlist_add_server(SilcIDList id_list,
   server->connection = connection;
 
   if (!silc_idcache_add(id_list->servers, server->server_name, 
-                       (void *)server->id, (void *)server, FALSE)) {
+                       (void *)server->id, (void *)server, 0, NULL)) {
     silc_free(server);
     return NULL;
   }
@@ -270,7 +270,7 @@ silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
   server->id = new_id;
 
   silc_idcache_add(id_list->servers, server->server_name, server->id, 
-                  server, FALSE);
+                  server, 0, NULL);
 
   SILC_LOG_DEBUG(("Found"));
 
@@ -319,7 +319,8 @@ int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry)
 SilcClientEntry
 silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username, 
                       char *userinfo, SilcClientID *id, 
-                      SilcServerEntry router, void *connection)
+                      SilcServerEntry router, void *connection,
+                      int expire)
 {
   SilcClientEntry client;
 
@@ -336,7 +337,7 @@ silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
                                           NULL, NULL, NULL, NULL, TRUE);
 
   if (!silc_idcache_add(id_list->clients, nickname, (void *)client->id, 
-                       (void *)client, FALSE)) {
+                       (void *)client, expire, NULL)) {
     silc_hash_table_free(client->channels);
     silc_free(client);
     return NULL;
@@ -522,7 +523,7 @@ silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
   silc_free(client->id);
   client->id = new_id;
 
-  silc_idcache_add(id_list->clients, NULL, client->id, client, FALSE);
+  silc_idcache_add(id_list->clients, NULL, client->id, client, 0, NULL);
 
   SILC_LOG_DEBUG(("Replaced"));
 
@@ -561,7 +562,8 @@ void silc_idlist_client_destructor(SilcIDCache cache,
 SilcChannelEntry
 silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
                        SilcChannelID *id, SilcServerEntry router,
-                       SilcCipher channel_key, SilcHmac hmac)
+                       SilcCipher channel_key, SilcHmac hmac,
+                       int expire)
 {
   SilcChannelEntry channel;
 
@@ -585,7 +587,7 @@ silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
                                             NULL, NULL, NULL, TRUE);
 
   if (!silc_idcache_add(id_list->channels, channel->channel_name, 
-                       (void *)channel->id, (void *)channel, FALSE)) {
+                       (void *)channel->id, (void *)channel, expire, NULL)) {
     silc_hmac_free(channel->hmac);
     silc_hash_table_free(channel->user_list);
     silc_free(channel);
@@ -731,7 +733,7 @@ silc_idlist_replace_channel_id(SilcIDList id_list, SilcChannelID *old_id,
   channel->id = new_id;
 
   silc_idcache_add(id_list->channels, channel->channel_name, channel->id, 
-                  channel, FALSE);
+                  channel, 0, NULL);
 
   SILC_LOG_DEBUG(("Replaced"));
 
index 37d3e9bb55ff85befdae4b59dae1809f6e3ee740..74d054f7b22938b4efa21056b9d699596f01f52a 100644 (file)
@@ -31,6 +31,7 @@ typedef struct SilcChannelEntryStruct *SilcChannelEntry;
 typedef struct {
   SilcIDCache cache;
   SilcSchedule schedule;
+  uint32 timeout;
 } *SilcIDListPurge;
 
 /* Channel key re-key context. */
@@ -579,7 +580,8 @@ int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry);
 SilcClientEntry
 silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username, 
                       char *userinfo, SilcClientID *id, 
-                      SilcServerEntry router, void *connection);
+                      SilcServerEntry router, void *connection,
+                      int expire);
 int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry);
 int silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
                                        char *server, 
@@ -600,7 +602,8 @@ void silc_idlist_client_destructor(SilcIDCache cache,
 SilcChannelEntry
 silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
                        SilcChannelID *id, SilcServerEntry router,
-                       SilcCipher channel_key, SilcHmac hmac);
+                       SilcCipher channel_key, SilcHmac hmac,
+                       int expire);
 int silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry);
 SilcChannelEntry
 silc_idlist_find_channel_by_name(SilcIDList id_list, char *name,
index 248442d70a427d7b7a745a92202e6cf95f615dc2..926163899005ea30c40485d2b411a3e4c16db780 100644 (file)
@@ -180,7 +180,7 @@ void silc_server_notify(SilcServer server,
        client = 
          silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
                                 silc_id_dup(client_id, SILC_ID_CLIENT), 
-                                sock->user_data, NULL);
+                                sock->user_data, NULL, 0);
        if (!client) {
          SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
          silc_free(client_id);
@@ -1220,9 +1220,22 @@ void silc_server_private_message(SilcServer server,
     if (!idp)
       return;
 
-    silc_server_send_command_reply(server, sock, SILC_COMMAND_IDENTIFY,
-                                  SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0, 1,
-                                  2, idp, idp->len);
+    if (packet->src_id_type == SILC_ID_CLIENT) {
+      SilcClientID *client_id = silc_id_str2id(packet->src_id,
+                                              packet->src_id_len,
+                                              packet->src_id_type);
+      silc_server_send_dest_command_reply(server, sock, 
+                                         client_id, SILC_ID_CLIENT,
+                                         SILC_COMMAND_IDENTIFY,
+                                         SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 
+                                         0, 1, 2, idp->data, idp->len);
+      silc_free(client_id);
+    } else {
+      silc_server_send_command_reply(server, sock, SILC_COMMAND_IDENTIFY,
+                                    SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 
+                                    0, 1, 2, idp->data, idp->len);
+    }
+
     silc_buffer_free(idp);
     return;
   }
@@ -1611,7 +1624,7 @@ SilcClientEntry silc_server_new_client(SilcServer server,
 
   /* Add the client again to the ID cache */
   silc_idcache_add(server->local_list->clients, client->nickname,
-                  client_id, client, FALSE);
+                  client_id, client, 0, NULL);
 
   /* Notify our router about new client on the SILC network */
   if (!server->standalone)
@@ -1779,7 +1792,7 @@ SilcServerEntry silc_server_new_server(SilcServer server,
   /* Add again the entry to the ID cache. */
   silc_idcache_add(local ? server->local_list->servers : 
                   server->global_list->servers, server_name, server_id, 
-                  new_server, FALSE);
+                  new_server, 0, NULL);
 
   /* Distribute the information about new server in the SILC network
      to our router. If we are normal server we won't send anything
@@ -1925,7 +1938,7 @@ static void silc_server_new_id_real(SilcServer server,
         global list. Cell wide information however is kept in the local
         list. */
       entry = silc_idlist_add_client(id_list, NULL, NULL, NULL, 
-                                    id, router, NULL);
+                                    id, router, NULL, 0);
       if (!entry) {
        SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
 
@@ -2164,7 +2177,7 @@ void silc_server_new_channel(SilcServer server,
                      sock->hostname));
     
       silc_idlist_add_channel(server->global_list, strdup(channel_name), 
-                             0, channel_id, sock->user_data, NULL, NULL);
+                             0, channel_id, sock->user_data, NULL, NULL, 0);
       server->stat.channels++;
     }
   } else {
index 0278ff1c64e1cc2a037bd82b5f877d58e0860d8e..b67071a694efc2f5ddf8dae68df5fe894b54dcab 100644 (file)
@@ -1769,6 +1769,32 @@ void silc_server_send_command_reply(SilcServer server,
   va_end(ap);
 }
 
+/* Generic function to send any command reply. The arguments must be sent
+   already encoded into correct form in correct order. */
+
+void silc_server_send_dest_command_reply(SilcServer server, 
+                                        SilcSocketConnection sock,
+                                        void *dst_id,
+                                        SilcIdType dst_id_type,
+                                        SilcCommand command, 
+                                        SilcCommandStatus status,
+                                        uint16 ident,
+                                        uint32 argc, ...)
+{
+  SilcBuffer packet;
+  va_list ap;
+
+  va_start(ap, argc);
+
+  packet = silc_command_reply_payload_encode_vap(command, status, ident, 
+                                                argc, ap);
+  silc_server_packet_send_dest(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
+                              dst_id, dst_id_type, packet->data, 
+                              packet->len, TRUE);
+  silc_buffer_free(packet);
+  va_end(ap);
+}
+
 /* Send the heartbeat packet. */
 
 void silc_server_send_heartbeat(SilcServer server,
index 412799b1a2a43bb0b2f9dc61c12801f318291f59..0bf835418b63611855505298da981b2dc06254ae 100644 (file)
@@ -232,6 +232,14 @@ void silc_server_send_command_reply(SilcServer server,
                                    SilcCommandStatus status,
                                    uint16 ident,
                                    uint32 argc, ...);
+void silc_server_send_dest_command_reply(SilcServer server, 
+                                        SilcSocketConnection sock,
+                                        void *dst_id,
+                                        SilcIdType dst_id_type,
+                                        SilcCommand command, 
+                                        SilcCommandStatus status,
+                                        uint16 ident,
+                                        uint32 argc, ...);
 void silc_server_send_heartbeat(SilcServer server,
                                SilcSocketConnection sock);
 void silc_server_relay_packet(SilcServer server,
index 8f58188eb09208c6ad063a129977e3f3be65435c..2dfbbbbbf7c357dd48a2f28e63bbd019be1f567e 100644 (file)
@@ -329,18 +329,20 @@ int silc_server_init(SilcServer server)
   purge = silc_calloc(1, sizeof(*purge));
   purge->cache = server->local_list->clients;
   purge->schedule = server->schedule;
+  purge->timeout = 600;
   silc_schedule_task_add(purge->schedule, 0, 
                         silc_idlist_purge,
-                        (void *)purge, 600, 0,
+                        (void *)purge, purge->timeout, 0,
                         SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
 
   /* Clients global list */
   purge = silc_calloc(1, sizeof(*purge));
   purge->cache = server->global_list->clients;
   purge->schedule = server->schedule;
+  purge->timeout = 300;
   silc_schedule_task_add(purge->schedule, 0, 
                         silc_idlist_purge,
-                        (void *)purge, 300, 0,
+                        (void *)purge, purge->timeout, 0,
                         SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
 
   SILC_LOG_DEBUG(("Server initialized"));
@@ -1319,7 +1321,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
         and other information is created after we have received NEW_CLIENT
         packet from client. */
       client = silc_idlist_add_client(server->local_list, 
-                                     NULL, NULL, NULL, NULL, NULL, sock);
+                                     NULL, NULL, NULL, NULL, NULL, sock, 0);
       if (!client) {
        SILC_LOG_ERROR(("Could not add new client to cache"));
        silc_free(sock->user_data);
@@ -2773,7 +2775,7 @@ SilcChannelEntry silc_server_create_new_channel(SilcServer server,
   }
   entry = silc_idlist_add_channel(server->local_list, channel_name, 
                                  SILC_CHANNEL_MODE_NONE, channel_id, 
-                                 NULL, key, newhmac);
+                                 NULL, key, newhmac, 0);
   if (!entry) {
     silc_free(channel_name);
     silc_cipher_free(key);
@@ -2844,7 +2846,7 @@ silc_server_create_new_channel_with_id(SilcServer server,
   /* Create the channel */
   entry = silc_idlist_add_channel(server->local_list, channel_name, 
                                  SILC_CHANNEL_MODE_NONE, channel_id, 
-                                 NULL, key, newhmac);
+                                 NULL, key, newhmac, 0);
   if (!entry) {
     silc_free(channel_name);
     return NULL;
@@ -3666,13 +3668,14 @@ void silc_server_save_users_on_channel(SilcServer server,
                                       uint32 user_count)
 {
   int i;
+  uint16 idp_len;
+  uint32 mode;
+  SilcClientID *client_id;
+  SilcClientEntry client;
+  SilcIDCacheEntry cache;
+  bool global;
 
   for (i = 0; i < user_count; i++) {
-    uint16 idp_len;
-    uint32 mode;
-    SilcClientID *client_id;
-    SilcClientEntry client;
-
     /* Client ID */
     SILC_GET16_MSB(idp_len, user_list->data + 2);
     idp_len += 4;
@@ -3689,14 +3692,18 @@ void silc_server_save_users_on_channel(SilcServer server,
       silc_free(client_id);
       continue;
     }
+
+    global = FALSE;
     
     /* Check if we have this client cached already. */
     client = silc_idlist_find_client_by_id(server->local_list, client_id,
-                                          server->server_type, NULL);
-    if (!client)
+                                          server->server_type, &cache);
+    if (!client) {
       client = silc_idlist_find_client_by_id(server->global_list, 
                                             client_id, server->server_type,
-                                            NULL);
+                                            &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. */
@@ -3710,7 +3717,7 @@ void silc_server_save_users_on_channel(SilcServer server,
         global. */
       client = silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
                                      silc_id_dup(client_id, SILC_ID_CLIENT), 
-                                     sock->user_data, NULL);
+                                     sock->user_data, NULL, 0);
       if (!client) {
        SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
        silc_free(client_id);
@@ -3718,6 +3725,11 @@ void silc_server_save_users_on_channel(SilcServer server,
       }
 
       client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
+    } else {
+      /* Found, if it is from global list we'll assure that we won't
+        expire it now that the entry is on channel. */
+      if (global)
+       cache->expire = 0;
     }
 
     silc_free(client_id);
index a29c2fd3757685017be70b928ae0368b528ea117..1f21972ee1af751f96665a0a4e0fe000f1771a9c 100644 (file)
@@ -371,7 +371,7 @@ silc_server_update_clients_by_real_server(SilcServer server,
            SILC_LOG_DEBUG(("Moving client to local list"));
            silc_idcache_add(server->local_list->clients, client_cache->name,
                             client_cache->id, client_cache->context,
-                            client_cache->expire);
+                            client_cache->expire, NULL);
            silc_idcache_del_by_context(server->global_list->clients, client);
          }
          server_entry = server_entry->router;
@@ -382,7 +382,7 @@ silc_server_update_clients_by_real_server(SilcServer server,
            SILC_LOG_DEBUG(("Moving client to local list"));
            silc_idcache_add(server->local_list->clients, client_cache->name,
                             client_cache->id, client_cache->context,
-                            client_cache->expire);
+                            client_cache->expire, NULL);
            silc_idcache_del_by_context(server->global_list->clients, client);
          }
        }
@@ -418,7 +418,7 @@ silc_server_update_clients_by_real_server(SilcServer server,
            SILC_LOG_DEBUG(("Moving client to global list"));
            silc_idcache_add(server->global_list->clients, client_cache->name,
                             client_cache->id, client_cache->context,
-                            client_cache->expire);
+                            client_cache->expire, NULL);
            silc_idcache_del_by_context(server->local_list->clients, client);
          }
          server_entry = server_entry->router;
@@ -429,7 +429,7 @@ silc_server_update_clients_by_real_server(SilcServer server,
            SILC_LOG_DEBUG(("Moving client to global list"));
            silc_idcache_add(server->global_list->clients, client_cache->name,
                             client_cache->id, client_cache->context,
-                            client_cache->expire);
+                            client_cache->expire, NULL);
            silc_idcache_del_by_context(server->local_list->clients, client);
          }
        }
index e19fcbaf0df07e8bca8e925f421222e9f21559f1..4a5f7cd05dfec22aa425653beacb92fb2a0393a1 100644 (file)
@@ -6,7 +6,7 @@
 <FONT SIZE="+3" COLOR="#000044"><B>SILC Toolkit Reference Manual</B></FONT>
 <BR>
 Copyright (C) GNU GPL 2001 The SILC Project<BR>
-Version: 0.6.3<BR>
+Version: 0.7<BR>
 Updated: @DATE@
 <BR><BR>
 <B><FONT SIZE="2">Note that this document is still under work and does not
index 58bcad2b44871972ce3c4b2f288c24d1c959c0aa..4676dc514305f4d82f77f471497965fa4d8c95e6 100644 (file)
@@ -1478,7 +1478,7 @@ void silc_client_receive_new_id(SilcClient client,
   
   /* Put it to the ID cache */
   silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id, 
-                  (void *)conn->local_entry, FALSE);
+                  (void *)conn->local_entry, 0, NULL);
 
   if (connecting) {
     /* Issue INFO comqmand to fetch the real server name and server information
@@ -1518,7 +1518,7 @@ SilcChannelEntry silc_client_new_channel_id(SilcClient client,
 
   /* Put it to the ID cache */
   silc_idcache_add(conn->channel_cache, channel->channel_name, 
-                  (void *)channel->id, (void *)channel, FALSE);
+                  (void *)channel->id, (void *)channel, 0, NULL);
 
   return channel;
 }
index d819b97280ac6710b55f1247194fcd4c8cc0ffd0..b4d4a78e8e166228f6c0b6e4f80f49099f3438cd 100644 (file)
@@ -724,7 +724,7 @@ void silc_client_notify_by_server(SilcClient client,
 
     /* Add the channel entry again to ID cache */
     silc_idcache_add(conn->channel_cache, channel->channel_name, 
-                    channel->id, channel, FALSE);
+                    channel->id, channel, 0, NULL);
 
     /* Notify application */
     client->ops->notify(client, conn, type, channel, channel);
index dd329441f6c94e23cda33ad4ff79b5c8f22ded6f..d1cf1f698934d8acacba27268caa01a44bd1bf53 100644 (file)
@@ -370,7 +370,7 @@ SILC_CLIENT_CMD_FUNC(nick_change)
     conn->nickname = strdup(cmd->argv[1]);
     conn->local_entry->nickname = conn->nickname;
     silc_idcache_add(conn->client_cache, strdup(cmd->argv[1]), 
-                    conn->local_entry->id, conn->local_entry, FALSE);
+                    conn->local_entry->id, conn->local_entry, 0, NULL);
     COMMAND;
   } else {
     COMMAND_ERROR;
index 5b5ef427294c94cbff3a960512fce938a2ff9758..a9d3ba704ceb4eabd1fb7e8d9dda66259fdcc487 100644 (file)
@@ -492,7 +492,8 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd,
       
       /* Add server to cache */
       silc_idcache_add(conn->server_cache, server_entry->server_name,
-                      server_entry->server_id, (void *)server_entry, FALSE);
+                      server_entry->server_id, (void *)server_entry, 
+                      0, NULL);
     } else {
       server_entry = (SilcServerEntry)id_cache->context;
     }
@@ -837,7 +838,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(info)
 
     /* Add it to the cache */
     silc_idcache_add(conn->server_cache, server->server_name,
-                    server->server_id, (void *)server, FALSE);
+                    server->server_id, (void *)server, 0, NULL);
 
     if (SILC_ID_SERVER_COMPARE(server_id, conn->remote_id))
       goto out;
index 02f54cee95627797636b7fcd427ee1acaab94796..da646b52255a2f6c3ccd2e7f7cd1d9eb1caea6df 100644 (file)
@@ -587,7 +587,7 @@ silc_client_add_client(SilcClient client, SilcClientConnection conn,
   
   /* Add client to cache, the non-formatted nickname is saved to cache */
   if (!silc_idcache_add(conn->client_cache, nick, client_entry->id, 
-                       (void *)client_entry, FALSE)) {
+                       (void *)client_entry, 0, NULL)) {
     silc_free(client_entry->nickname);
     silc_free(client_entry->username);
     silc_free(client_entry->hostname);
@@ -629,7 +629,7 @@ void silc_client_update_client(SilcClient client,
     /* Remove the old cache entry and create a new one */
     silc_idcache_del_by_context(conn->client_cache, client_entry);
     silc_idcache_add(conn->client_cache, nick, client_entry->id, 
-                    client_entry, FALSE);
+                    client_entry, 0, NULL);
   }
 }
 
index c4b658e80ed02f3827d06ad687de3c154e9577e1..5cf2533af07d99bf5fae68e32c14b6a9f43f9952 100644 (file)
@@ -142,10 +142,9 @@ void silc_idcache_free(SilcIDCache cache)
    the entry never expires from the cache. */
 
 bool silc_idcache_add(SilcIDCache cache, char *name, void *id, 
-                     void *context, int expire)
+                     void *context, int expire, SilcIDCacheEntry *ret)
 {
   SilcIDCacheEntry c;
-  uint32 curtime = time(NULL);
 
   SILC_LOG_DEBUG(("Adding cache entry"));
 
@@ -153,7 +152,7 @@ bool silc_idcache_add(SilcIDCache cache, char *name, void *id,
   c = silc_calloc(1, sizeof(*c));
   c->id = id;
   c->name = name;
-  c->expire = (expire ? (curtime + SILC_ID_CACHE_EXPIRE) : 0);
+  c->expire = expire;
   c->context = context;
 
   /* Add the new entry to the hash tables */
@@ -173,6 +172,9 @@ bool silc_idcache_add(SilcIDCache cache, char *name, void *id,
     silc_hash_table_rehash(cache->context_table, 0);
   }
 
+  if (ret)
+    *ret = c;
+
   return TRUE;
 }
 
index cadda8c0cfdd561f5ce28667f96a8f01b5d5b40c..e5c86a513e5c394adb970c7d425efd03fdf14300 100644 (file)
@@ -172,12 +172,15 @@ void silc_idcache_free(SilcIDCache cache);
  *    Add new entry to the cache. Returns TRUE if the entry was added and
  *    FALSE if it could not be added. The `name' is the name associated with
  *    the ID, the `id' the actual ID and the `context' a used specific context.
- *    If the `expire' is TRUE the entry expires in default time and if FALSE
- *    the entry never expires from the cache.
+ *    If the `expire' is non-zero the entry expires in that specified time.
+ *    If zero the entry never expires from the cache.
+ *
+ *    If the `ret' is non-NULL the created ID Cache entry is returned to 
+ *    that pointer.
  *
  ***/
 bool silc_idcache_add(SilcIDCache cache, char *name, void *id, 
-                     void *context, int expire);
+                     void *context, int expire, SilcIDCacheEntry *ret);
 
 /****f* silccore/SilcIDCacheAPI/silc_idcache_del
  *
diff --git a/prepare b/prepare
index 9d1d8e081c87ee3b3a2cea89a6718832301f420c..bbd966f4701d354c1cd113ca41f311a58126a4c1 100755 (executable)
--- a/prepare
+++ b/prepare
@@ -37,7 +37,7 @@
 # SILC Distribution versions. Set here or give the version on the command
 # line as argument.
 #
-SILC_VERSION=0.6.2                     # Base version
+SILC_VERSION=0.7                       # Base version
 
 #############################################################################
 
index 655ac714a499bd498342b1aabe93558ff88d2e89..94ec41a07396a2c1f337a37851c4edf8b0592327 100644 (file)
@@ -45,6 +45,10 @@ o Library
          when necessary.  This way we can move the data handling in one 
          place.
 
+       o Add silc_id_str2id to accept the destination buffer as argument
+         and thus not require any memory allocation.  Same will happen
+         with silc_id_payload_* functions.
+
 o Server
 
        o When processing the decrypted and parsed packet we call the