updates.
authorPekka Riikonen <priikone@silcnet.org>
Thu, 11 Apr 2002 19:42:02 +0000 (19:42 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 11 Apr 2002 19:42:02 +0000 (19:42 +0000)
15 files changed:
CHANGES
apps/irssi/src/silc/core/client_ops.c
apps/irssi/src/silc/core/silc-servers.c
apps/silcd/command.c
apps/silcd/command_reply.c
apps/silcd/packet_receive.c
apps/silcd/server.c
apps/silcd/server.h
apps/silcd/silcd.c
doc/Makefile.am.pre
doc/draft-riikonen-silc-commands-03.nroff
doc/draft-riikonen-silc-pp-05.nroff
doc/draft-riikonen-silc-spec-05.nroff
lib/silcclient/client_notify.c
lib/silcutil/silcschedule.c

diff --git a/CHANGES b/CHANGES
index 3a357a62b00f83e4108f0c597081f05acb80cb77..99dde0ab10bcae418e9e12d10d9cd71365e0541d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,9 @@
+Thu Apr 11 22:29:33 EEST 2002  Pekka Riikonen <priikone@silcnet.org>
+
+       * Defined that server receives USERS command reply for private
+         and secret channels too.  Updated protocol specs and the
+         code in server.  Affected file silcd/command.c.
+
 Thu Apr 11 16:32:08 EEST 2002  Pekka Riikonen <priikone@silcnet.org>
 
        * Changed the UMODE's mode mask argument to be optional.  If
index b4f71907dd2d8a07d499755ef17cf8d1476d4bf3..664d625a3718de1750a8b42e62e44bca4680bf0a 100644 (file)
@@ -335,6 +335,9 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
 
     client_entry = va_arg(va, SilcClientEntry);
     client_entry2 = va_arg(va, SilcClientEntry);
+
+    if (!strcmp(client_entry->nickname, client_entry2->nickname))
+      break;
     
     memset(userhost, 0, sizeof(userhost));
     snprintf(userhost, sizeof(userhost) - 1, "%s@%s",
@@ -1913,8 +1916,7 @@ silc_detach(SilcClient client, SilcClientConnection conn,
   /* Save the detachment data to file. */
 
   memset(file, 0, sizeof(file));
-  snprintf(file, sizeof(file) - 1, "%s/session.%s.%d", get_irssi_dir(),
-          conn->remote_host, conn->remote_port);
+  snprintf(file, sizeof(file) - 1, "%s/session", get_irssi_dir());
   silc_file_writefile(file, detach_data, detach_data_len);
 }
 
index fdcbd431f52320990d0057aec74901ece9f0baea..9ae0003bc4922a135c155e73489881526722304f 100644 (file)
@@ -204,7 +204,7 @@ static void sig_connected(SILC_SERVER_REC *server)
   /* Try to read detached session data and use it if found. */
   memset(&params, 0, sizeof(params));
   memset(file, 0, sizeof(file));
-  snprintf(file, sizeof(file) - 1, "%s/session.%s.%d", get_irssi_dir(),
+  snprintf(file, sizeof(file) - 1, "%s/session", get_irssi_dir(),
           server->connrec->address, server->connrec->port);
   params.detach_data = silc_file_readfile(file, &params.detach_data_len);
 
index afb9e5394e9f8c6e8e789113d783209bd9951dbe..dd8a43fe3f779924b59825ad9de067c845ccb52d 100644 (file)
@@ -791,9 +791,8 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
       
     SILC_PUT32_MSB(entry->mode, mode);
 
-    if (entry->connection) {
+    if (entry->connection)
       SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
-    }
 
     packet = 
       silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
@@ -2457,7 +2456,7 @@ SILC_SERVER_CMD_FUNC(invite)
     }
 
     /* Get the client entry */
-    dest = silc_server_get_client_resolve(server, dest_id, &resolve);
+    dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
     if (!dest) {
       if (server->server_type != SILC_SERVER || !resolve) {
        silc_server_command_send_status_reply(
@@ -3074,7 +3073,8 @@ static void silc_server_command_join_channel(SilcServer server,
   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
     client = (SilcClientEntry)sock->user_data;
   } else {
-    client = silc_server_get_client_resolve(server, client_id, &resolve);
+    client = silc_server_get_client_resolve(server, client_id, FALSE, 
+                                           &resolve);
     if (!client) {
       if (cmd->pending)
        goto out;
@@ -5102,20 +5102,13 @@ SILC_SERVER_CMD_FUNC(users)
   }
 
   /* If the channel is private or secret do not send anything, unless the
-     user requesting this command is on the channel. */
+     user requesting this command is on the channel or is server */
   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
        && !silc_server_client_on_channel(cmd->sock->user_data, channel, 
                                          NULL)) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
-                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
-      goto out;
-    }
-  } else {
-    if (channel->mode & 
-       (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
-                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
+                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
       goto out;
     }
   }
@@ -5198,7 +5191,8 @@ SILC_SERVER_CMD_FUNC(getkey)
                                             client_id, TRUE, NULL);
     
     if ((!client && !cmd->pending && !server->standalone) ||
-       (client && !client->connection && !cmd->pending) ||
+       (client && !client->connection && !cmd->pending &&
+        !(client->mode & SILC_UMODE_DETACHED)) ||
        (client && !client->data.public_key && !cmd->pending)) {
       SilcBuffer tmpbuf;
       SilcUInt16 old_ident;
index ccb425f00d51b480495018e18a811caa1b1aecba..c524111bd2389923bebafc479f4152a6692f90a7 100644 (file)
@@ -988,7 +988,7 @@ SILC_SERVER_CMD_REPLY_FUNC(stats)
   }
 
  out:
-  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
+  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_STATS);
 }
 
 SILC_SERVER_CMD_REPLY_FUNC(users)
index 29752416068c1b32778e492cfe1fc2561a041ca0..eddd848aa40b024b8cf4f7a8894ab8322e35aa12 100644 (file)
@@ -464,7 +464,7 @@ void silc_server_notify(SilcServer server,
       if (client) {
        /* Send the NICK_CHANGE notify type to local clients on the channels
           this client is joined to. */
-       silc_server_send_notify_on_channels(server, NULL, client,
+       silc_server_send_notify_on_channels(server, client, client,
                                            SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
                                            id, tmp_len, id2, tmp_len,
                                            nickname, nickname ?
@@ -1460,8 +1460,7 @@ void silc_server_private_message(SilcServer server,
     SilcBuffer idp;
 
     if (client && client->mode & SILC_UMODE_DETACHED) {
-      SILC_LOG_DEBUG(("Locally connected client is detached, "
-                     "discarding packet"));
+      SILC_LOG_DEBUG(("Client is detached, discarding packet"));
       return;
     }
 
@@ -1747,9 +1746,8 @@ SilcClientEntry silc_server_new_client(SilcServer server,
   SilcBuffer buffer = packet->buffer;
   SilcClientEntry client;
   SilcClientID *client_id;
-  SilcBuffer reply;
   SilcIDListData idata;
-  char *username = NULL, *realname = NULL, *id_string;
+  char *username = NULL, *realname = NULL;
   SilcUInt16 username_len;
   SilcUInt32 id_len;
   int ret;
@@ -1925,17 +1923,8 @@ SilcClientEntry silc_server_new_client(SilcServer server,
                            client->id, SILC_ID_CLIENT, id_len);
   
   /* Send the new client ID to the client. */
-  id_string = silc_id_id2str(client->id, SILC_ID_CLIENT);
-  reply = silc_buffer_alloc_size(2 + 2 + id_len);
-  silc_buffer_format(reply,
-                    SILC_STR_UI_SHORT(SILC_ID_CLIENT),
-                    SILC_STR_UI_SHORT(id_len),
-                    SILC_STR_UI_XNSTRING(id_string, id_len),
-                    SILC_STR_END);
-  silc_server_packet_send(server, sock, SILC_PACKET_NEW_ID, 0, 
-                         reply->data, reply->len, FALSE);
-  silc_free(id_string);
-  silc_buffer_free(reply);
+  silc_server_send_new_id(server, sock, FALSE, client->id, SILC_ID_CLIENT,
+                         silc_id_get_len(client->id, SILC_ID_CLIENT));
 
   /* Send some nice info to the client */
   silc_server_send_connect_notifys(server, sock, client);
@@ -2816,6 +2805,7 @@ typedef struct {
   SilcServer server;
   SilcSocketConnection sock;
   SilcPacketContext *packet;
+  void *data;
 } *SilcServerResumeResolve;
 
 SILC_SERVER_CMD_FUNC(resume_resolve)
@@ -2824,8 +2814,11 @@ SILC_SERVER_CMD_FUNC(resume_resolve)
   SilcServer server = r->server;
   SilcSocketConnection sock = r->sock;
   SilcServerCommandReplyContext reply = context2;
+  SilcClientEntry client;
+
+  SILC_LOG_DEBUG(("Start"));
 
-  if (!context2 || !silc_command_get_status(reply->payload, NULL, NULL)) {
+  if (!reply || !silc_command_get_status(reply->payload, NULL, NULL)) {
     SILC_LOG_ERROR(("Client %s (%s) tried to resume unknown client, "
                    "closing connection", sock->hostname, sock->ip));
     silc_server_disconnect_remote(server, sock, 
@@ -2834,12 +2827,40 @@ SILC_SERVER_CMD_FUNC(resume_resolve)
     goto out;
   }
 
+  if (reply && silc_command_get(reply->payload) == SILC_COMMAND_WHOIS) {
+    /* Get entry to the client, and resolve it if we don't have it. */
+    client = silc_idlist_find_client_by_id(server->local_list, 
+                                          r->data, TRUE, NULL);
+    if (!client) {
+      client = silc_idlist_find_client_by_id(server->global_list,
+                                            r->data, TRUE, NULL);
+      if (!client) {
+       SILC_LOG_ERROR(("Client %s (%s) tried to resume unknown client, "
+                       "closing connection", sock->hostname, sock->ip));
+       silc_server_disconnect_remote(server, sock, 
+                                     "Server closed connection: "
+                                     "Incomplete resume information");
+       goto out;
+      }
+    }
+
+    if (!(client->mode & SILC_UMODE_DETACHED)) {
+      SILC_LOG_ERROR(("Client %s (%s) tried to resume un-detached client, "
+                     "closing connection", sock->hostname, sock->ip));
+      silc_server_disconnect_remote(server, sock, 
+                                   "Server closed connection: "
+                                   "Incomplete resume information");
+      goto out;
+    }
+  }
+
   /* Reprocess the packet */
   silc_server_resume_client(server, sock, r->packet);
 
  out:
   silc_socket_free(r->sock);
   silc_packet_context_free(r->packet);
+  silc_free(r->data);
   silc_free(r);
 }
 
@@ -2859,9 +2880,14 @@ void silc_server_resume_client(SilcServer server,
   unsigned char *id_string, *auth = NULL;
   SilcUInt16 id_len, auth_len = 0;
   int ret, nickfail = 0;
-  bool resolved, local;
+  bool resolved, local, nick_change = FALSE;
+  SilcChannelEntry channel;
+  SilcHashTableList htl;
+  SilcChannelClientEntry chl;
   SilcServerResumeResolve r;
 
+  SILC_LOG_DEBUG(("Start"));
+
   ret = silc_buffer_unformat(buffer,
                             SILC_STR_UI16_NSTRING(&id_string, &id_len),
                             SILC_STR_END);
@@ -2871,9 +2897,6 @@ void silc_server_resume_client(SilcServer server,
   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
     /* Client send this and is attempting to resume to old client session */
     SilcClientEntry client;
-    SilcChannelEntry channel;
-    SilcHashTableList htl;
-    SilcChannelClientEntry chl;
     SilcBuffer keyp;
 
     if (ret != -1) {
@@ -2896,19 +2919,20 @@ void silc_server_resume_client(SilcServer server,
     idata = (SilcIDListData)client;
 
     /* Get entry to the client, and resolve it if we don't have it. */
-    detached_client = silc_server_get_client_resolve(server, client_id, 
+    detached_client = silc_server_get_client_resolve(server, client_id, FALSE,
                                                     &resolved);
     if (!detached_client) {
       if (resolved) {
        /* The client info is being resolved. Reprocess this packet after
           receiving the reply to the query. */
+       SILC_LOG_DEBUG(("Resolving client"));
        r = silc_calloc(1, sizeof(*r));
        if (!r)
          return;
-
        r->server = server;
        r->sock = silc_socket_dup(sock);
        r->packet = silc_packet_context_dup(packet);
+       r->data = silc_id_dup(client_id, SILC_ID_CLIENT);
        silc_server_command_pending(server, SILC_COMMAND_WHOIS,
                                    server->cmd_ident,
                                    silc_server_command_resume_resolve, r);
@@ -2924,10 +2948,28 @@ void silc_server_resume_client(SilcServer server,
 
     /* Check that the client is detached */
     if (!(detached_client->mode & SILC_UMODE_DETACHED)) {
-      SILC_LOG_ERROR(("Client %s (%s) tried to resume un-detached client, "
-                     "closing connection", sock->hostname, sock->ip));
-      silc_server_disconnect_remote(server, sock, "Server closed connection: "
-                                   "Incomplete resume information");
+      if (server->server_type == SILC_SERVER && !server->standalone) {
+       /* The client info is being resolved. Reprocess this packet after
+          receiving the reply to the query. */
+       SILC_LOG_DEBUG(("Resolving client mode"));
+       silc_server_get_client_resolve(server, client_id, TRUE, NULL);
+       r = silc_calloc(1, sizeof(*r));
+       if (!r)
+         return;
+       r->server = server;
+       r->sock = silc_socket_dup(sock);
+       r->packet = silc_packet_context_dup(packet);
+       r->data = silc_id_dup(client_id, SILC_ID_CLIENT);
+       silc_server_command_pending(server, SILC_COMMAND_WHOIS,
+                                   server->cmd_ident,
+                                   silc_server_command_resume_resolve, r);
+      } else {
+       SILC_LOG_ERROR(("Client %s (%s) tried to resume un-detached client, "
+                       "closing connection", sock->hostname, sock->ip));
+       silc_server_disconnect_remote(server, sock, 
+                                     "Server closed connection: "
+                                     "Incomplete resume information");
+      }
       return;
     }
 
@@ -2945,10 +2987,12 @@ void silc_server_resume_client(SilcServer server,
        SilcSocketConnection dest_sock = 
          silc_server_get_client_route(server, NULL, 0, client_id, NULL, NULL);
 
+       SILC_LOG_DEBUG(("Resolving client public key"));
+
        silc_server_send_command(server, dest_sock ? dest_sock : 
                                 server->router->connection,
                                 SILC_COMMAND_GETKEY, ++server->cmd_ident,
-                                1, idp->data, idp->len);
+                                1, 1, idp->data, idp->len);
 
        r = silc_calloc(1, sizeof(*r));
        if (!r)
@@ -2993,17 +3037,27 @@ void silc_server_resume_client(SilcServer server,
 
     /* Send the RESUME_CLIENT packet to our primary router so that others
        know this client isn't detached anymore. */
-    if (!server->standalone) {
-      buf = silc_buffer_alloc_size(2 + id_len);
-      silc_buffer_format(buf,
-                        SILC_STR_UI_SHORT(id_len),
-                        SILC_STR_UI_XNSTRING(id_string, id_len),
-                        SILC_STR_END);
+    buf = silc_buffer_alloc_size(2 + id_len);
+    silc_buffer_format(buf,
+                      SILC_STR_UI_SHORT(id_len),
+                      SILC_STR_UI_XNSTRING(id_string, id_len),
+                      SILC_STR_END);
+
+    /* Send to primary router */
+    if (!server->standalone)
       silc_server_packet_send(server, server->router->connection,
                              SILC_PACKET_RESUME_CLIENT, 0, 
                              buf->data, buf->len, TRUE);
-      silc_buffer_free(buf);
-    }
+
+    /* As router we must deliver this packet directly to the original
+       server whom this client was earlier. */
+    if (server->server_type == SILC_ROUTER && detached_client->router)
+      silc_server_packet_send(server, detached_client->router->connection,
+                             SILC_PACKET_RESUME_CLIENT, 0, 
+                             buf->data, buf->len, TRUE);
+    silc_buffer_free(buf);
+
+    detached_client->router = NULL;
 
     /* Delete this client entry since we're resuming to old one. */
     server->stat.my_clients--;
@@ -3028,39 +3082,54 @@ void silc_server_resume_client(SilcServer server,
        snprintf(&client->nickname[strlen(client->nickname) - 1], 1, 
                 "%d", nickfail);
       }
+      nick_change = TRUE;
+    }
 
+    if (nick_change) {
       /* Notify about Client ID change, nickname doesn't actually change. */
       if (!server->standalone)
        silc_server_send_notify_nick_change(server, server->router->connection,
                                            FALSE, client->id, client_id,
                                            client->nickname);
-      
-      silc_free(client->id);
-      client->id = client_id;
+    }
+
+    /* Send the new client ID to the client. After this client may start
+       receiving other packets, and may start sending packets too. */
+    silc_server_send_new_id(server, sock, FALSE, client_id, SILC_ID_CLIENT,
+                           silc_id_get_len(client_id, SILC_ID_CLIENT));
+
+    if (nick_change) {
+      /* Send NICK change notify to channels as well. */
+      SilcBuffer oidp, nidp;
+      oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+      nidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
+      silc_server_send_notify_on_channels(server, NULL, client, 
+                                         SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
+                                         oidp->data, oidp->len, 
+                                         nidp->data, nidp->len,
+                                         client->nickname, 
+                                         strlen(client->nickname));
+      silc_buffer_free(oidp);
+      silc_buffer_free(nidp);
     }
 
     /* Add the client again to the ID cache to get it to correct list */
     if (!silc_idcache_del_by_context(server->local_list->clients, client))
       silc_idcache_del_by_context(server->global_list->clients, client);
+    silc_free(client->id);
+    client->id = client_id;
+    client_id = NULL;
     silc_idcache_add(server->local_list->clients, client->nickname,
-                    client->id, client, client->mode, NULL);
-
-    /* Send the new client ID to the client. */
-    id_string = silc_id_id2str(client->id, SILC_ID_CLIENT);
-    buf = silc_buffer_alloc_size(2 + 2 + id_len);
-    silc_buffer_format(buf,
-                      SILC_STR_UI_SHORT(SILC_ID_CLIENT),
-                      SILC_STR_UI_SHORT(id_len),
-                      SILC_STR_UI_XNSTRING(id_string, id_len),
-                      SILC_STR_END);
-    silc_server_packet_send(server, sock, SILC_PACKET_NEW_ID, 0, 
-                           buf->data, buf->len, FALSE);
-    silc_free(id_string);
-    silc_buffer_free(buf);
+                    client->id, client, 0, NULL);
 
     /* Send some nice info to the client */
     silc_server_send_connect_notifys(server, sock, client);
 
+    /* XXX normal server may not know about any joined channels!!! 
+       Do this by saving the joined list in the resume_resolve callback.
+       Resolve it here with USERS per channel. */
+
+
     /* Send all channel keys of channels the client has joined */
     silc_hash_table_list(client->channels, &htl);
     while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
@@ -3079,6 +3148,7 @@ void silc_server_resume_client(SilcServer server,
       /* Send the key packet to client */
       silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0, 
                              keyp->data, keyp->len, FALSE);
+      channel->global_users = silc_server_channel_has_global(channel);
     }
     silc_hash_table_list_reset(&htl);
 
@@ -3146,19 +3216,32 @@ void silc_server_resume_client(SilcServer server,
       }
     }
 
+    SILC_LOG_DEBUG(("Resuming detached client"));
+
     /* Change the client to correct list. */
     if (!silc_idcache_del_by_context(server->local_list->clients,
                                     detached_client))
       silc_idcache_del_by_context(server->global_list->clients,
                                  detached_client);
-    silc_idcache_add(local ? server->local_list->clients :
-                    server->global_list->clients, detached_client->nickname,
+    silc_idcache_add(local && server->server_type == SILC_ROUTER ? 
+                    server->local_list->clients : 
+                    server->global_list->clients, 
+                    detached_client->nickname,
                     detached_client->id, detached_client, FALSE, NULL);
 
     /* Change the owner of the client if needed */
     if (detached_client->router != server_entry)
       detached_client->router = server_entry;
 
+    /* Update channel information regarding global clients on channel. */
+    if (server->server_type == SILC_SERVER) {
+      silc_hash_table_list(detached_client->channels, &htl);
+      while (silc_hash_table_get(&htl, NULL, (void **)&chl))
+       chl->channel->global_users = 
+         silc_server_channel_has_global(chl->channel);
+      silc_hash_table_list_reset(&htl);
+    }
+
     /* If the sender of this packet is server and we are router we need to
        broadcast this packet to other routers in the network. */
     if (!server->standalone && server->server_type == SILC_ROUTER &&
index bb633a65ecd6c4839e404b2f6153dd013f1450c4..064ff3860b57922d4bbbf797e50d07b304ef382f 100644 (file)
@@ -3888,6 +3888,7 @@ void silc_server_save_users_on_channel(SilcServer server,
   SilcClientID *client_id;
   SilcClientEntry client;
   SilcIDCacheEntry cache;
+  SilcChannelClientEntry chl;
   bool global;
 
   SILC_LOG_DEBUG(("Start"));
@@ -3951,15 +3952,18 @@ void silc_server_save_users_on_channel(SilcServer server,
 
     silc_free(client_id);
 
-    if (!silc_server_client_on_channel(client, channel, NULL)) {
+    if (!silc_server_client_on_channel(client, channel, &chl)) {
       /* Client was not on the channel, add it. */
-      SilcChannelClientEntry chl = silc_calloc(1, sizeof(*chl));
+      chl = silc_calloc(1, sizeof(*chl));
       chl->client = client;
       chl->mode = mode;
       chl->channel = channel;
       silc_hash_table_add(channel->user_list, chl->client, chl);
       silc_hash_table_add(client->channels, chl->channel, chl);
       channel->user_count++;
+    } else {
+      /* Update mode */
+      chl->mode = mode;
     }
   }
 }
@@ -4107,6 +4111,7 @@ SilcBuffer silc_server_get_client_channel_list(SilcServer server,
 
 SilcClientEntry silc_server_get_client_resolve(SilcServer server,
                                               SilcClientID *client_id,
+                                              bool always_resolve,
                                               bool *resolved)
 {
   SilcClientEntry client;
@@ -4126,7 +4131,8 @@ SilcClientEntry silc_server_get_client_resolve(SilcServer server,
   if (!client && server->standalone)
     return NULL;
 
-  if (!client || !client->nickname || !client->username) {
+  if (!client || !client->nickname || !client->username ||
+      always_resolve) {
     SilcBuffer buffer, idp;
 
     client->data.status |= SILC_IDLIST_STATUS_RESOLVING;
index a90e7dd166a5217dc25bf029e5fd5da9c94aeebb..74326d1990700eca441e64851053de488aa28c7c 100644 (file)
@@ -219,6 +219,7 @@ SilcBuffer silc_server_get_client_channel_list(SilcServer server,
                                               SilcClientEntry client);
 SilcClientEntry silc_server_get_client_resolve(SilcServer server,
                                               SilcClientID *client_id,
+                                              bool always_resolve,
                                               bool *resolved);
 void silc_server_stderr(char *message);
 
index 35693a717f1f5421c4b81c6b5baa65754a2af79c..53b7f81eb12a57efd4bed910f83f5699874dc60f 100644 (file)
@@ -426,8 +426,8 @@ int main(int argc, char **argv)
 
   /* Stop the server and free it. */
   silc_server_stop(silcd);
-  silc_server_free(silcd);
   silc_server_config_destroy(silcd->config);
+  silc_server_free(silcd);
 
   /* Flush the logging system */
   silc_log_flush_all();
index 778714a448e31af8a5bdaa55b2e2c153ce76529c..504b53ce0850316dbedb0644a1a71969c06185f4 100644 (file)
@@ -24,19 +24,21 @@ DIST_SUBDIRS = SILC_DISTRIBUTION_SUBDIRS
 makerfc = ../scripts/makerfc
 
 all:
-       touch draft-riikonen-silc-spec-04.txt
-       touch draft-riikonen-silc-pp-04.txt
-       touch draft-riikonen-silc-ke-auth-04.txt
-       touch draft-riikonen-silc-commands-02.txt
+       touch draft-riikonen-silc-spec-05.txt
+       touch draft-riikonen-silc-pp-05.txt
+       touch draft-riikonen-silc-ke-auth-05.txt
+       touch draft-riikonen-silc-commands-03.txt
+       touch draft-riikonen-silc-flags-payloads-00.txt
        -cd ..
 
 if SILC_DIST_CLIENT
 dist-hook:
        rm draft-riikonen*.txt
-       touch draft-riikonen-silc-spec-04.txt
-       touch draft-riikonen-silc-pp-04.txt
-       touch draft-riikonen-silc-ke-auth-04.txt
-       touch draft-riikonen-silc-commands-02.txt
+       touch draft-riikonen-silc-spec-05.txt
+       touch draft-riikonen-silc-pp-05.txt
+       touch draft-riikonen-silc-ke-auth-05.txt
+       touch draft-riikonen-silc-commands-03.txt
+       touch draft-riikonen-silc-flags-payloads-00.txt
 else
 if SILC_DIST_TOOLKIT
 dist-hook:
@@ -48,32 +50,38 @@ dist-hook:
        else  \
          echo ROBODoc is not compiled! Cannot generate documentation! ; \
         fi
-       touch draft-riikonen-silc-spec-04.txt
-       touch draft-riikonen-silc-pp-04.txt
-       touch draft-riikonen-silc-ke-auth-04.txt
-       touch draft-riikonen-silc-commands-02.txt
-       $(makerfc) draft-riikonen-silc-spec-04.nroff \
-               draft-riikonen-silc-spec-04.txt
-       $(makerfc) draft-riikonen-silc-pp-04.nroff \
-               draft-riikonen-silc-pp-04.txt
-       $(makerfc) draft-riikonen-silc-ke-auth-04.nroff \
-               draft-riikonen-silc-ke-auth-04.txt
-       $(makerfc) draft-riikonen-silc-commands-02.nroff \
-               draft-riikonen-silc-commands-02.txt
+       touch draft-riikonen-silc-spec-05.txt
+       touch draft-riikonen-silc-pp-05.txt
+       touch draft-riikonen-silc-ke-auth-05.txt
+       touch draft-riikonen-silc-commands-03.txt
+       touch draft-riikonen-silc-flags-payloads-00.txt
+       $(makerfc) draft-riikonen-silc-spec-05.nroff \
+               draft-riikonen-silc-spec-05.txt
+       $(makerfc) draft-riikonen-silc-pp-05.nroff \
+               draft-riikonen-silc-pp-05.txt
+       $(makerfc) draft-riikonen-silc-ke-auth-05.nroff \
+               draft-riikonen-silc-ke-auth-05.txt
+       $(makerfc) draft-riikonen-silc-commands-03.nroff \
+               draft-riikonen-silc-commands-03.txt
+       $(makerfc) draft-riikonen-silc-flags-payloads-00.nroff \
+               draft-riikonen-silc-flags-payloads-00.txt
 else
 dist-hook:
-       touch draft-riikonen-silc-spec-04.txt
-       touch draft-riikonen-silc-pp-04.txt
-       touch draft-riikonen-silc-ke-auth-04.txt
-       touch draft-riikonen-silc-commands-02.txt
-       $(makerfc) draft-riikonen-silc-spec-04.nroff \
-               draft-riikonen-silc-spec-04.txt
-       $(makerfc) draft-riikonen-silc-pp-04.nroff \
-               draft-riikonen-silc-pp-04.txt
-       $(makerfc) draft-riikonen-silc-ke-auth-04.nroff \
-               draft-riikonen-silc-ke-auth-04.txt
-       $(makerfc) draft-riikonen-silc-commands-02.nroff \
-               draft-riikonen-silc-commands-02.txt
+       touch draft-riikonen-silc-spec-05.txt
+       touch draft-riikonen-silc-pp-05.txt
+       touch draft-riikonen-silc-ke-auth-05.txt
+       touch draft-riikonen-silc-commands-03.txt
+       touch draft-riikonen-silc-flags-payloads-00.txt
+       $(makerfc) draft-riikonen-silc-spec-05.nroff \
+               draft-riikonen-silc-spec-05.txt
+       $(makerfc) draft-riikonen-silc-pp-05.nroff \
+               draft-riikonen-silc-pp-05.txt
+       $(makerfc) draft-riikonen-silc-ke-auth-05.nroff \
+               draft-riikonen-silc-ke-auth-05.txt
+       $(makerfc) draft-riikonen-silc-commands-03.nroff \
+               draft-riikonen-silc-commands-03.txt
+       $(makerfc) draft-riikonen-silc-flags-payloads-00.nroff \
+               draft-riikonen-silc-flags-payloads-00.txt
 endif
 endif
 
index c915a498d4965d017a492a6ef0a0afc6f4d24556..421013fe748e1d2fd6ca767a94934ff4a88e6942 100644 (file)
@@ -1631,16 +1631,13 @@ List of all defined commands in SILC follows.
         This command is used to list user names currently on the requested
         channel; either the argument <Channel ID> or the <channel name>. 
         One of these arguments must be present.  The server MUST resolve
-        the user names and send a comma (`,') separated list of user names
-        on the channel.  Server or router MAY resolve the names by sending
-        SILC_COMMAND_WHOIS or SILC_COMMAND_IDENTIFY commands.
+        the joined clients and reply with a lists of users on the channel
+       and with list of user modes on the channel.
 
         If the requested channel is a private or secret channel, this
-        command MUST NOT send the list of users, as private and secret
-        channels cannot be seen by outside.  In this case the returned
-        name list MAY include a indication that the server could not 
-        resolve the names of the users on the channel.  Also, in this case
-        Client ID's or client modes are not sent either.
+        command MUST NOT send the list of users, but error is returned
+        to the sender, except if the sender is on the channel, or the
+        sender is server.
 
         Reply messages to the command:
 
index b991f5a263e7f729e12ef81991c429b6cf9720d5..fcc4b85020d93b6ed833f8bf57304146ed584d96 100644 (file)
@@ -1321,6 +1321,8 @@ UTF-8 [RFC2279] encoded.
       The <Old Client ID> is the old ID of the client which changed
       the nickname.  The <New Client ID> is the new ID generated by
       the change of the nickname.  The <nickname> is the new nickname.
+      Note that it is possible to send this notify even if the nickname
+      hasn't changed, but client ID has changed.
 
 
 7     SILC_NOTIFY_TYPE_CMODE_CHANGE
index e8ee48427382e80bc2a9dc68f862e696239eae76..f039a94d66230fc80870adf5049936ee7f1cf99b 100644 (file)
@@ -2164,7 +2164,9 @@ in the SKE protocol for this connection.  If the signature is valid
 the server MUST unset the SILC_UMODE_DETACHED flag, and send the
 SILC_PACKET_RESUME_CLIENT packet to its primary router.  The routers
 MUST broadcast the packet and unset the SILC_UMODE_DETACHED flag
-when the packet is received.
+when the packet is received.  If the server is router server it also
+MUST send the SILC_PACKET_RESUME_CLIENT packet to the original server
+whom owned the detached client.
 
 The servers and routers that receives the SILC_PACKET_RESUME_CLIENT
 packet MUST know whether the packet already has been received for
index 1e7778583f6e864b8ab307ff57f2484d4bf980c9..50aebb3ca84f19db80c87459f2450b7237abd492 100644 (file)
@@ -456,7 +456,7 @@ void silc_client_notify_by_server(SilcClient client,
       goto out;
 
     /* Ignore my ID */
-    if (SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
+    if (conn->local_id && SILC_ID_CLIENT_COMPARE(client_id, conn->local_id))
       break;
 
     /* Find old Client entry */
@@ -482,6 +482,31 @@ void silc_client_notify_by_server(SilcClient client,
     tmp = silc_argument_get_arg_type(args, 3, NULL);
     if (tmp) {
       /* Protocol version 1.1 */
+      char *tmp_nick;
+
+      /* Check whether nickname changed at all.  It is possible that nick
+        change notify is received but nickname didn't changed, only the
+        ID changes. */
+      if (client->internal->params->nickname_parse)
+       client->internal->params->nickname_parse(client_entry->nickname,
+                                                &tmp_nick);
+      else
+       tmp_nick = strdup(tmp);
+
+      if (!strcmp(tmp, tmp_nick)) {
+       /* Nickname didn't change. Update only the ID */
+       silc_idcache_del_by_context(conn->client_cache, client_entry);
+       silc_free(client_entry->id);
+       client_entry->id = silc_id_dup(client_id, SILC_ID_CLIENT);
+       silc_idcache_add(conn->client_cache, strdup(tmp),
+                        client_entry->id, client_entry, 0, NULL);
+
+       /* Notify application */
+       client->internal->ops->notify(client, conn, type, 
+                                     client_entry, client_entry);
+       break;
+      }
+      silc_free(tmp_nick);
 
       /* Create new client entry, and save all old information with the
         new nickname and client ID */
index 828e78748e639167b95b043064312d28656fb5c7..db939c3ad201df748aa4f7fde12362d681245dde 100644 (file)
@@ -936,6 +936,7 @@ static void silc_task_queue_alloc(SilcTaskQueue *queue)
 static void silc_task_queue_free(SilcTaskQueue queue)
 {
   silc_mutex_free(queue->lock);
+  memset(queue, 'F', sizeof(*queue));
   silc_free(queue);
 }
 
@@ -1172,10 +1173,11 @@ static int silc_schedule_task_remove(SilcTaskQueue queue, SilcTask task)
     next = first;
 
     while(1) {
-      next = next->next;
-      silc_free(next->prev);
-      if (next == first)
+      old = next->next;
+      silc_free(next);
+      if (old == first)
        break;
+      next = old;
     }
 
     queue->task = NULL;