updates.
authorPekka Riikonen <priikone@silcnet.org>
Sun, 16 Sep 2001 14:53:25 +0000 (14:53 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 16 Sep 2001 14:53:25 +0000 (14:53 +0000)
CHANGES
TODO
apps/silcd/command.c
apps/silcd/server.c
lib/silcclient/client.c
lib/silcclient/client_notify.c
lib/silcclient/command.c
lib/silcclient/command_reply.c
lib/silcclient/idlist.c
lib/silcclient/idlist.h
lib/silcske/silcske.c

diff --git a/CHANGES b/CHANGES
index 0173db9144eb77995e098556a4e85babd884baa2..3cae5b3bfaedd6529f53779af9b05fdb43703d15 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -11,6 +11,29 @@ Sun Sep 16 12:32:58 EEST 2001  Pekka Riikonen <priikone@silcnet.org>
        * Print the selected security properties to the log files in
          the server.  Affected file silcd/protocol.c.
 
+       * Add SKE's reference counter even if calling the completion
+         callback manually.  Otherwise it goes negative, although it
+         does not cause any problems.  The affected file is
+         lib/silcske/silcske.c.
+
+       * Remove the client entry with short timeout after giving the
+         KILL command.  Affected file lib/silcclient/command.c.
+
+       * Fixed to send error reply in WHOIS and IDENTIFY commands in
+         case all found clients are already disconnected (WHOWAS would
+         found them) in the server.  Affected file silcd/command.c.
+
+       * Update the last_receive (time of last data received) to be 
+         updated only when received private or channel message so that
+         the idle time showed in WHOIS makes more sense.
+
+       * Added boolean field `valid' in to the SilcClientEntry in the
+         client library to indicate whether the entry is valid or not.
+         This fixes the nickname change bug on channel when changing
+         the nickname to be same than the old (like nick to Nick) the
+         nickname formatter doesn't set the new nick anymore to Nick@host.
+         Affected file lib/silcclient/idlist.[ch].
+
 Sat Sep 15 13:29:17 EEST 2001  Pekka Riikonen <priikone@silcnet.org>
 
        * Check that the public key exists in the GETKEY command before
diff --git a/TODO b/TODO
index aca1fcc95254871d65b6647dc746281919001907..6ff015e301b6d05aac03ff56927c1f7c771433b8 100644 (file)
--- a/TODO
+++ b/TODO
@@ -38,13 +38,6 @@ TODO/bugs in Irssi SILC client
 TODO/bugs In SILC Client Library
 ================================
 
- o Someone changing nickname on the channel from nick to Nick will cause
-   that the new nick becomes Nick@host, because the old nick is not
-   removed from the cache before adding the new one.  This is because
-   of the way NICK_CHANGE notify is handled.  This should be fixed so
-   that if the old nick is to be removed the new nick will *replace*
-   the old one.
-
  o JOIN command's argument handling is buggy.  See the XXX in the code.
 
 
@@ -53,8 +46,6 @@ TODO/bugs In SILC Server
 
  o Add perhaps /var/run/silcd.pid for PID information for the server.
 
- o Update idle times only for private/channel messaegs.
-
  o Add a timeout to handling incmoing JOIN commands.  It should be 
    enforced that JOIN command is executed only once in a second or two
    seconds.  Now it is possible to accept n incoming JOIN commands
index 0125c55e5a10372c82f160d8b61b5eae82aa3217..567a0f9228de8c0d11b75f8bd0bc32aeb0e4e286 100644 (file)
@@ -678,6 +678,24 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
     if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
       len++;
 
+  if (len == 0 && clients_count) {
+    entry = clients[0];
+    if (entry->nickname) {
+      silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
+                                          SILC_STATUS_ERR_NO_SUCH_NICK,
+                                          3, entry->nickname, 
+                                          strlen(entry->nickname));
+    } else {
+      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_CLIENT_ID,
+                                          2, idp->data, idp->len);
+      silc_buffer_free(idp);
+    }
+
+    return;
+  }
+
   status = SILC_STATUS_OK;
   if (len > 1)
     status = SILC_STATUS_LIST_START;
@@ -1629,6 +1647,24 @@ silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
       if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
        len++;
 
+    if (len == 0 && clients_count) {
+      entry = clients[0];
+      if (entry->nickname) {
+       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
+                                            SILC_STATUS_ERR_NO_SUCH_NICK,
+                                            3, entry->nickname, 
+                                            strlen(entry->nickname));
+      } else {
+       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_CLIENT_ID,
+                                            2, idp->data, idp->len);
+       silc_buffer_free(idp);
+      }
+      
+      return;
+    }
+
     if (len > 1)
       status = SILC_STATUS_LIST_START;
 
@@ -1639,7 +1675,7 @@ silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
        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_CLIENT_ID,
+                                        SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
                                               2, idp->data, idp->len);
          silc_buffer_free(idp);
        }
index 02b1cc894524885a72876b72154f1b7585d0580a..5c93bed5ff664308ecffe150b7bc1ed49fdcecec 100644 (file)
@@ -772,7 +772,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
       silc_free(ctx->dest_id);
     silc_free(ctx);
     silc_schedule_task_del_by_callback(server->schedule,
-                                    silc_server_failure_callback);
+                                      silc_server_failure_callback);
     silc_server_disconnect_remote(server, sock, "Server closed connection: "
                                  "Key exchange failed");
     return;
@@ -1215,6 +1215,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
   SilcServer server = (SilcServer)ctx->server;
   SilcSocketConnection sock = ctx->sock;
   SilcServerHBContext hb_context;
+  SilcUnknownEntry entry = (SilcUnknownEntry)sock->user_data;
   void *id_entry = NULL;
 
   SILC_LOG_DEBUG(("Start"));
@@ -1241,6 +1242,8 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
     return;
   }
 
+  entry->data.last_receive = time(NULL);
+
   switch (ctx->conn_type) {
   case SILC_SOCKET_TYPE_CLIENT:
     {
@@ -1363,7 +1366,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
 
  out:
   silc_schedule_task_del_by_callback(server->schedule,
-                                  silc_server_failure_callback);
+                                    silc_server_failure_callback);
   silc_protocol_free(protocol);
   if (ctx->packet)
     silc_packet_context_free(ctx->packet);
@@ -1493,7 +1496,6 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
   /* Get keys and stuff from ID entry */
   idata = (SilcIDListData)sock->user_data;
   if (idata) {
-    idata->last_receive = time(NULL);
     cipher = idata->receive_key;
     hmac = idata->hmac_receive;
   }
@@ -1673,6 +1675,7 @@ void silc_server_packet_parse_type(SilcServer server,
                                   SilcPacketContext *packet)
 {
   SilcPacketType type = packet->type;
+  SilcIDListData idata = (SilcIDListData)sock->user_data;
 
   SILC_LOG_DEBUG(("Parsing packet type %d", type));
 
@@ -1750,6 +1753,7 @@ void silc_server_packet_parse_type(SilcServer server,
     SILC_LOG_DEBUG(("Channel Message packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
+    idata->last_receive = time(NULL);
     silc_server_channel_message(server, sock, packet);
     break;
 
@@ -1803,6 +1807,7 @@ void silc_server_packet_parse_type(SilcServer server,
     SILC_LOG_DEBUG(("Private Message packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
+    idata->last_receive = time(NULL);
     silc_server_private_message(server, sock, packet);
     break;
 
index 681d9e0eaf300ff1f9d88047a55ef1ce58214905..a5b3f8157c0599cd50530c7325e26a5e2e0fcc3f 100644 (file)
@@ -1388,6 +1388,7 @@ void silc_client_receive_new_id(SilcClient client,
     conn->local_entry->hostname = strdup(client->hostname);
   conn->local_entry->server = strdup(conn->remote_host);
   conn->local_entry->id = conn->local_id;
+  conn->local_entry->valid = TRUE;
   
   /* Put it to the ID cache */
   silc_idcache_add(conn->client_cache, strdup(conn->nickname), conn->local_id, 
index a07991736323e7930e1f33c0657609266cffc75c..82a0654fa9158a125f53a06b4ad0de17a673a8a1 100644 (file)
@@ -2,7 +2,7 @@
 
   client_notify.c
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2001 Pekka Riikonen
 
@@ -123,7 +123,7 @@ void silc_client_notify_by_server(SilcClient client,
     /* Get the channel entry */
     channel = NULL;
     if (silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
-                               &id_cache))
+                                   &id_cache))
       channel = (SilcChannelEntry)id_cache->context;
 
     /* Get sender Client ID */
@@ -202,9 +202,6 @@ void silc_client_notify_by_server(SilcClient client,
       silc_list_add(channel->clients, chu);
     }
 
-    /* XXX add support for multiple same nicks on same channel. Check
-       for them here */
-
     /* Notify application. The channel entry is sent last as this notify
        is for channel but application don't know it from the arguments
        sent by server. */
@@ -366,6 +363,8 @@ void silc_client_notify_by_server(SilcClient client,
       goto out;
     silc_free(client_id);
 
+    client_entry->valid = FALSE;
+
     /* Get new Client ID */
     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
     if (!tmp)
@@ -767,8 +766,6 @@ void silc_client_notify_by_server(SilcClient client,
 
  out:
   silc_notify_payload_free(payload);
-  if (client_id)
-    silc_free(client_id);
-  if (channel_id)
-    silc_free(channel_id);
+  silc_free(client_id);
+  silc_free(channel_id);
 }
index 0388f29a082476385b276d1ab4312beeba3b174c..b23149360466262c0d358472f4e2ea6c4aad8b95 100644 (file)
@@ -600,12 +600,11 @@ SILC_CLIENT_CMD_FUNC(invite)
       client_entry = silc_idlist_get_client(client, conn, nickname, 
                                            cmd->argv[2], TRUE);
       if (!client_entry) {
-       silc_free(nickname);
-       
        if (cmd->pending) {
          COMMAND_ERROR;
          goto out;
        }
+       silc_free(nickname);
       
        /* Client entry not found, it was requested thus mark this to be
           pending command. */
@@ -717,6 +716,56 @@ SILC_CLIENT_CMD_FUNC(quit)
   silc_client_command_free(cmd);
 }
 
+/* Timeout callback to remove the killed client from cache */
+
+SILC_TASK_CALLBACK(silc_client_command_kill_remove_later)
+{
+  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+  SilcClient client = cmd->client;
+  SilcClientConnection conn = cmd->conn;
+  SilcClientEntry target;
+  char *nickname = NULL;
+  
+  /* Parse the typed nickname. */
+  if (client->params->nickname_parse)
+    client->params->nickname_parse(cmd->argv[1], &nickname);
+  else
+    nickname = strdup(cmd->argv[1]);
+
+  /* Get the target client */
+  target = silc_idlist_get_client(cmd->client, conn, nickname, 
+                                 cmd->argv[1], FALSE);
+  if (target) {
+    silc_client_remove_from_channels(client, conn, target);
+    silc_client_del_client(client, conn, target);
+  }
+
+  silc_free(nickname);
+  silc_client_command_free(cmd);
+}
+
+/* Kill command's pending command callback to actually remove the killed
+   client from our local cache. */
+
+SILC_CLIENT_CMD_FUNC(kill_remove)
+{
+  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+  SilcClientCommandReplyContext reply = 
+    (SilcClientCommandReplyContext)context2;
+  SilcCommandStatus status;
+
+  SILC_GET16_MSB(status, silc_argument_get_arg_type(reply->args, 1, NULL));
+  if (status == SILC_STATUS_OK) {
+    /* Remove with timeout */
+    silc_schedule_task_add(cmd->client->schedule, cmd->conn->sock->sock,
+                          silc_client_command_kill_remove_later, context,
+                          1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+    return;
+  }
+
+  silc_client_command_free(cmd);
+}
+
 /* Command KILL. Router operator can use this command to remove an client
    fromthe SILC Network. */
 
@@ -752,13 +801,13 @@ SILC_CLIENT_CMD_FUNC(kill)
   target = silc_idlist_get_client(cmd->client, conn, nickname, 
                                  cmd->argv[1], TRUE);
   if (!target) {
-    silc_free(nickname);
-
     if (cmd->pending) {
       COMMAND_ERROR;
       goto out;
     }
 
+    silc_free(nickname);
+
     /* Client entry not found, it was requested thus mark this to be
        pending command. */
     silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, 
@@ -773,10 +822,12 @@ SILC_CLIENT_CMD_FUNC(kill)
   /* Send the KILL command to the server */
   idp = silc_id_payload_encode(target->id, SILC_ID_CLIENT);
   if (cmd->argc == 2)
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_KILL, 0, 1, 
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_KILL, 
+                                           ++conn->cmd_ident, 1, 
                                            1, idp->data, idp->len);
   else
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_KILL, 0, 2, 
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_KILL, 
+                                           ++conn->cmd_ident, 2, 
                                            1, idp->data, idp->len,
                                            2, cmd->argv[2], 
                                            strlen(cmd->argv[2]));
@@ -788,6 +839,12 @@ SILC_CLIENT_CMD_FUNC(kill)
   /* Notify application */
   COMMAND;
 
+  /* Register a pending callback that will actually remove the killed
+     client from our cache. */
+  silc_client_command_pending(conn, SILC_COMMAND_KILL, conn->cmd_ident,
+                             NULL, silc_client_command_kill_remove,
+                             silc_client_command_dup(cmd));
+
  out:
   silc_free(nickname);
   silc_client_command_free(cmd);
@@ -1370,13 +1427,13 @@ SILC_CLIENT_CMD_FUNC(cumode)
   client_entry = silc_idlist_get_client(cmd->client, conn, nickname,
                                        cmd->argv[3], TRUE);
   if (!client_entry) {
-    silc_free(nickname);
-
     if (cmd->pending) {
       COMMAND_ERROR;
       goto out;
     }
 
+    silc_free(nickname);
+
     /* Client entry not found, it was requested thus mark this to be
        pending command. */
     silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, 
index 0396ae9ca5388a2bd49d96e6cdbc352a60536ce2..228dce57f1cddb43724a392b7a504b73e4b009e4 100644 (file)
@@ -742,10 +742,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(kill)
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
   SilcCommandStatus status;
-  unsigned char *tmp;
 
-  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-  SILC_GET16_MSB(status, tmp);
+  SILC_GET16_MSB(status, silc_argument_get_arg_type(cmd->args, 1, NULL));
   if (status != SILC_STATUS_OK) {
     cmd->client->ops->say(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
             "%s", silc_client_command_status_message(status));
index af4d3476cad6be704525f94546f77559bbe4f774..dae275ef89efda7d5679a85a968e18121aaace9b 100644 (file)
@@ -543,6 +543,7 @@ silc_client_add_client(SilcClient client, SilcClientConnection conn,
   /* Save the client infos */
   client_entry = silc_calloc(1, sizeof(*client_entry));
   client_entry->id = id;
+  client_entry->valid = TRUE;
   silc_parse_userfqdn(nickname, &nick, &client_entry->server);
   silc_parse_userfqdn(username, &client_entry->username, 
                      &client_entry->hostname);
@@ -845,7 +846,7 @@ void silc_client_nickname_format(SilcClient client,
   char *newnick = NULL;
   int i, off = 0, len;
   SilcClientEntry *clients;
-  uint32 clients_count;
+  uint32 clients_count = 0;
 
   if (!client->params->nickname_format[0])
     return;
@@ -862,6 +863,13 @@ void silc_client_nickname_format(SilcClient client,
   if (!clients && !client->params->nickname_force_format)
     return;
 
+  len = 0;
+  for (i = 0; i < clients_count; i++)
+    if (clients[i]->valid)
+      len++;
+  if (!len)
+    return;
+
   cp = client->params->nickname_format;
   while (*cp) {
     if (*cp == '%') {
@@ -925,7 +933,7 @@ void silc_client_nickname_format(SilcClient client,
          break;
 
        for (i = 0; i < clients_count; i++) {
-         if (strncmp(clients[i]->nickname, newnick, off))
+         if (strncasecmp(clients[i]->nickname, newnick, off))
            continue;
          if (strlen(clients[i]->nickname) <= off)
            continue;
index 6ff551ca076c1cf7ded57cc65a3f01bb49561496..0dc48f8f316e19e90c329bcd8c139dcb86506268 100644 (file)
@@ -34,13 +34,14 @@ typedef struct {
   uint32 num;
   uint32 mode;                 /* User mode in SILC */
   SilcClientID *id;            /* The Client ID */
+  bool valid;                  /* FALSE if this entry is not valid */
   SilcCipher send_key;         /* Private message key for sending */
   SilcCipher receive_key;      /* Private message key for receiving */
   unsigned char *key;          /* Set only if appliation provided the
                                   key material. NULL if the library 
                                   generated the key. */
   uint32 key_len;
-  int generated;               /* TRUE if library generated the key */
+  bool generated;              /* TRUE if library generated the key */
   SilcClientKeyAgreement ke;   /* Current key agreement context or NULL */
 } *SilcClientEntry;
 
index 575c347e75497df8f1e3043fb13f71a57973a117..e69fc0f9df52914c69fc0bff33ff2023944d40ed 100644 (file)
@@ -580,6 +580,7 @@ SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
   }
 
   /* Continue to final state */
+  ske->users++;
   silc_ske_initiator_finish_final(ske, SILC_SKE_STATUS_OK, NULL);
 
   return SILC_SKE_STATUS_OK;
@@ -933,6 +934,7 @@ SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
   }
 
   /* Continue to final state */
+  ske->users++;
   silc_ske_responder_phase2_final(ske, SILC_SKE_STATUS_OK, NULL);
 
   return SILC_SKE_STATUS_OK;