updates
authorPekka Riikonen <priikone@silcnet.org>
Mon, 20 Nov 2000 21:22:30 +0000 (21:22 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 20 Nov 2000 21:22:30 +0000 (21:22 +0000)
CHANGES
apps/silcd/command.c
apps/silcd/command.h
apps/silcd/command_reply.c
apps/silcd/server.c
apps/silcd/server_internal.h

diff --git a/CHANGES b/CHANGES
index 9b005e6958317a04d6f203d236008273a20e62fa..98e2f3ac6dde5c5013dba749007c78d4269c1f5c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,11 @@
+Mon Nov 20 23:47:03 EET 2000  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * Made joining to a channel working in router environment.
+
+       * Cleaned up JOIN command on server side and create function
+         silc_server_command_join_channel internal routine to make the
+         joining happen.
+
 Thu Nov  9 21:12:39 EET 2000  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Changed silc_command_pending list to SilcDList.  Also, added
index d937dd36822c3aad7c0f0b83777d910d26163038..d027389b01878bce964b3a1b159e2627302ec1a7 100644 (file)
@@ -38,6 +38,9 @@ silc_server_command_send_status_data(SilcServerCommandContext cmd,
                                     unsigned char *arg,
                                     unsigned int arg_len);
 static void silc_server_command_free(SilcServerCommandContext cmd);
+void silc_server_command_send_names(SilcServer server,
+                                   SilcSocketConnection sock,
+                                   SilcChannelEntry channel);
 
 /* Server command list. */
 SilcServerCommand silc_command_list[] =
@@ -75,9 +78,6 @@ SilcServerCommand silc_command_list[] =
   { NULL, 0 },
 };
 
-/* List of pending commands. */
-SilcDList silc_command_pending;
-
 /* Returns TRUE if the connection is registered. Unregistered connections
    usually cannot send commands hence the check. */
 
@@ -176,7 +176,8 @@ void silc_server_command_process(SilcServer server,
    the `callback' will be executed when received reply with command
    identifier `ident'. */
 
-void silc_server_command_pending(SilcCommand reply_cmd,
+void silc_server_command_pending(SilcServer server,
+                                SilcCommand reply_cmd,
                                 unsigned short ident,
                                 SilcCommandCb callback,
                                 void *context)
@@ -188,19 +189,21 @@ void silc_server_command_pending(SilcCommand reply_cmd,
   reply->ident = ident;
   reply->context = context;
   reply->callback = callback;
-  silc_dlist_add(silc_command_pending, reply);
+  silc_dlist_add(server->pending_commands, reply);
 }
 
 /* Deletes pending command by reply command type. */
 
-void silc_server_command_pending_del(SilcCommand reply_cmd,
+void silc_server_command_pending_del(SilcServer server,
+                                    SilcCommand reply_cmd,
                                     unsigned short ident)
 {
   SilcServerCommandPending *r;
 
-  while ((r = silc_dlist_get(silc_command_pending)) != SILC_LIST_END) {
+  silc_dlist_start(server->pending_commands);
+  while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
     if (r->reply_cmd == reply_cmd && r->ident == ident) {
-      silc_dlist_del(silc_command_pending, r);
+      silc_dlist_del(server->pending_commands, r);
       break;
     }
   }
@@ -209,13 +212,15 @@ void silc_server_command_pending_del(SilcCommand reply_cmd,
 /* Checks for pending commands and marks callbacks to be called from
    the command reply function. Returns TRUE if there were pending command. */
 
-int silc_server_command_pending_check(SilcServerCommandReplyContext ctx,
+int silc_server_command_pending_check(SilcServer server,
+                                     SilcServerCommandReplyContext ctx,
                                      SilcCommand command, 
                                      unsigned short ident)
 {
   SilcServerCommandPending *r;
 
-  while ((r = silc_dlist_get(silc_command_pending)) != SILC_LIST_END) {
+  silc_dlist_start(server->pending_commands);
+  while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
     if (r->reply_cmd == command && r->ident == ident) {
       ctx->context = r->context;
       ctx->callback = r->callback;
@@ -1169,12 +1174,17 @@ SILC_TASK_CALLBACK(silc_server_command_join_notify)
                                       SILC_NOTIFY_TYPE_JOIN, 1,
                                       clidp->data, clidp->len);
 
+    /* Send NAMES command reply to the joined channel so the user sees who
+       is currently on the channel. */
+    silc_server_command_send_names(ctx->server, ctx->client->connection, 
+                                  ctx->channel);
+
     silc_buffer_free(clidp);
     silc_free(ctx);
   } else {
     silc_task_register(ctx->server->timeout_queue, fd,
                       silc_server_command_join_notify, context,
-                      0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+                      0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
   }
 }
 
@@ -1205,55 +1215,26 @@ void silc_server_command_send_names(SilcServer server,
   silc_free(idp);
 }
 
-/* Server side of command JOIN. Joins client into requested channel. If 
-   the channel does not exist it will be created. */
+/* Internal routine to join channel. The channel sent to this function
+   has been either created or resolved from ID lists. This joins the sent
+   client to the channel. */
 
-SILC_SERVER_CMD_FUNC(join)
+static void
+silc_server_command_join_channel(SilcServer server, 
+                                SilcServerCommandContext cmd,
+                                SilcChannelEntry channel,
+                                unsigned int umode)
 {
-  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
-  SilcServer server = cmd->server;
   SilcSocketConnection sock = cmd->sock;
-  SilcBuffer buffer = cmd->packet->buffer;
-  int argc, i, k, tmp_len;
-  char *tmp, *channel_name = NULL, *cipher = NULL;
+  unsigned char *tmp;
+  unsigned int tmp_len;
   unsigned char *passphrase = NULL, mode[4];
-  unsigned int umode = 0;
-  SilcChannelEntry channel;
+  SilcClientEntry client;
   SilcChannelClientEntry chl;
-  SilcServerID *router_id;
   SilcBuffer packet, idp;
-  SilcClientEntry client;
-
-  SILC_LOG_DEBUG(("Start"));
-
-  /* Check number of parameters */
-  argc = silc_argument_get_arg_num(cmd->args);
-  if (argc < 1) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
-                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
-    goto out;
-  }
-  if (argc > 3) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
-                                         SILC_STATUS_ERR_TOO_MANY_PARAMS);
-    goto out;
-  }
-
-  /* Get channel name */
-  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
-  if (!tmp) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
-                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
-    goto out;
-  }
-  channel_name = tmp;
 
-  if (silc_server_command_bad_chars(channel_name) == TRUE) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
-                                         SILC_STATUS_ERR_BAD_CHANNEL);
-    silc_free(channel_name);
-    goto out;
-  }
+  if (!channel)
+    return;
 
   /* Get passphrase */
   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
@@ -1262,67 +1243,6 @@ SILC_SERVER_CMD_FUNC(join)
     memcpy(passphrase, tmp, tmp_len);
   }
   
-  /* Get cipher name */
-  cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
-
-  /* See if the channel exists */
-  channel = 
-    silc_idlist_find_channel_by_name(server->local_list, channel_name);
-  if (!channel) {
-    /* Channel not found */
-
-    /* If we are standalone server we don't have a router, we just create 
-       the channel by  ourselves. */
-    if (server->standalone) {
-      router_id = server->id;
-      channel = silc_server_new_channel(server, router_id, cipher, 
-                                       channel_name);
-      umode |= SILC_CHANNEL_UMODE_CHANOP;
-      umode |= SILC_CHANNEL_UMODE_CHANFO;
-      if (!channel)
-       goto out;
-
-      goto join_channel;
-    }
-
-    /* No channel ID found, the channel does not exist on our server.
-       We send JOIN command to our router which will handle the joining
-       procedure (either creates the channel if it doesn't exist or
-       joins the client to it) - if we are normal server. */
-    if (server->server_type == SILC_SERVER) {
-
-      /* Forward the original JOIN command to the router */
-      silc_buffer_push(buffer, buffer->data - buffer->head);
-      silc_server_packet_forward(server, (SilcSocketConnection)
-                                server->id_entry->router->connection,
-                                buffer->data, buffer->len, TRUE);
-      
-      /* Add the command to be pending. It will be re-executed after
-        router has replied back to us. */
-      cmd->pending = TRUE;
-      silc_server_command_pending(SILC_COMMAND_JOIN, 0,
-                                 silc_server_command_join, context);
-      return;
-    }
-  }
-
-  /* If we are router and the channel does not exist we will check our
-     global list for the channel. */
-  if (!channel && server->server_type == SILC_ROUTER) {
-
-    /* Notify all routers about the new channel in SILC network. */
-    if (!server->standalone) {
-#if 0
-      silc_server_send_new_id(server, server->id_entry->router->connection, 
-                             TRUE,
-                             xxx, SILC_ID_CHANNEL, SILC_ID_CHANNEL_LEN);
-#endif
-    }
-
-  }
-
- join_channel:
-
   /*
    * Check channel modes
    */
@@ -1416,16 +1336,16 @@ SILC_SERVER_CMD_FUNC(join)
       packet = 
        silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
                                             SILC_STATUS_OK, 0, 3,
-                                            2, channel_name, 
-                                            strlen(channel_name),
+                                            2, channel->channel_name,
+                                            strlen(channel->channel_name),
                                             3, idp->data, idp->len,
                                             4, mode, 4);
     else
       packet = 
        silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
                                             SILC_STATUS_OK, 0, 4, 
-                                            2, channel_name, 
-                                            strlen(channel_name),
+                                            2, channel->channel_name, 
+                                            strlen(channel->channel_name),
                                             3, idp->data, idp->len,
                                             4, mode, 4,
                                             5, channel->topic, 
@@ -1477,7 +1397,7 @@ SILC_SERVER_CMD_FUNC(join)
       /* This is pending command request. Send the notify after we have
         received the key for the channel from the router. */
       JoinInternalContext *ctx = silc_calloc(1, sizeof(*ctx));
-      ctx->channel_name = channel_name;
+      ctx->channel_name = channel->channel_name;
       ctx->nickname = client->nickname;
       ctx->username = client->username;
       ctx->hostname = sock->hostname ? sock->hostname : sock->ip;
@@ -1488,11 +1408,112 @@ SILC_SERVER_CMD_FUNC(join)
                         silc_server_command_join_notify, ctx,
                         0, 10000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
     }
+
+    /* Send NAMES command reply to the joined channel so the user sees who
+       is currently on the channel. */
+    silc_server_command_send_names(server, sock, channel);
+  }
+
+ out:
+  if (passphrase)
+    silc_free(passphrase);
+}
+
+/* Server side of command JOIN. Joins client into requested channel. If 
+   the channel does not exist it will be created. */
+
+SILC_SERVER_CMD_FUNC(join)
+{
+  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  SilcServer server = cmd->server;
+  int argc, tmp_len;
+  char *tmp, *channel_name = NULL, *cipher = NULL;
+  SilcChannelEntry channel;
+  unsigned int umode = SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO;
+
+  SILC_LOG_DEBUG(("Start"));
+
+  /* Check number of parameters */
+  argc = silc_argument_get_arg_num(cmd->args);
+  if (argc < 1) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
+                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+    goto out;
+  }
+  if (argc > 3) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
+                                         SILC_STATUS_ERR_TOO_MANY_PARAMS);
+    goto out;
+  }
+
+  /* Get channel name */
+  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+  if (!tmp) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
+                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+    goto out;
+  }
+  channel_name = tmp;
+
+  if (silc_server_command_bad_chars(channel_name) == TRUE) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
+                                         SILC_STATUS_ERR_BAD_CHANNEL);
+    silc_free(channel_name);
+    goto out;
+  }
+
+  /* Get cipher name */
+  cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
+
+  /* See if the channel exists */
+  channel = silc_idlist_find_channel_by_name(server->local_list, channel_name);
+  if (!channel) {
+    /* Channel not found */
+
+    /* If we are standalone server we don't have a router, we just create 
+       the channel by ourselves. */
+    if (server->standalone) {
+      channel = silc_server_new_channel(server, server->id, cipher, 
+                                       channel_name);
+    } else {
+
+      /* The channel does not exist on our server. We send JOIN command to
+        our router which will handle the joining procedure (either creates
+        the channel if it doesn't exist or joins the client to it) - if we
+        are normal server. */
+      if (server->server_type == SILC_SERVER) {
+       SilcBuffer buffer = cmd->packet->buffer;
+       
+       /* Forward the original JOIN command to the router */
+       silc_buffer_push(buffer, buffer->data - buffer->head);
+       silc_server_packet_forward(server, (SilcSocketConnection)
+                                  server->id_entry->router->connection,
+                                  buffer->data, buffer->len, TRUE);
+       
+       /* Add the command to be pending. It will be re-executed after
+          router has replied back to us. */
+       cmd->pending = TRUE;
+       silc_server_command_pending(server, SILC_COMMAND_JOIN, 0,
+                                   silc_server_command_join, context);
+       return;
+      }
+      
+      /* We are router and the channel does not seem exist so we will check
+        our global list as well for the channel. */
+      channel = silc_idlist_find_channel_by_name(server->global_list, 
+                                                channel_name);
+      if (!channel) {
+       /* Channel really does not exist, create it */
+       channel = silc_server_new_channel(server, server->id, cipher, 
+                                         channel_name);
+       umode |= SILC_CHANNEL_UMODE_CHANOP;
+       umode |= SILC_CHANNEL_UMODE_CHANFO;
+      }
+    }
   }
 
-  /* Send NAMES command reply to the joined channel so the user sees who
-     is currently on the channel. */
-  silc_server_command_send_names(server, sock, channel);
+  /* Join to the channel */
+  silc_server_command_join_channel(server, cmd, channel, umode);
 
  out:
   silc_server_command_free(cmd);
@@ -2374,7 +2395,7 @@ SILC_SERVER_CMD_FUNC(names)
       /* XXX Send names command */
 
       cmd->pending = TRUE;
-      silc_server_command_pending(SILC_COMMAND_NAMES, 0,
+      silc_server_command_pending(server, SILC_COMMAND_NAMES, 0,
                                  silc_server_command_names, context);
       return;
     }
index 21677e8f287ee70126694eea0842a44d186efbef..e5fdc06ec901f6a538b2956ed235eae5e827de8d 100644 (file)
@@ -62,6 +62,7 @@ typedef struct {
 /* Structure holding pending commands. If command is pending it will be
    executed after command reply has been received and executed. */
 typedef struct SilcServerCommandPendingStruct {
+  SilcServer server;
   SilcCommand reply_cmd;
   SilcCommandCb callback;
   void *context;
@@ -80,25 +81,28 @@ typedef struct SilcServerCommandPendingStruct {
 void silc_server_command_##func(void *context)
 
 /* Executed pending command */
-#define SILC_SERVER_COMMAND_EXEC_PENDING(ctx, cmd)     \
-do {                                                   \
-  if (ctx->callback) {                                 \
-    (*ctx->callback)(ctx->context);                    \
-    silc_server_command_pending_del(cmd, ctx->ident);  \
-  }                                                    \
+#define SILC_SERVER_COMMAND_EXEC_PENDING(ctx, cmd)                     \
+do {                                                                   \
+  if (ctx->callback) {                                                 \
+    (*ctx->callback)(ctx->context);                                    \
+    silc_server_command_pending_del(ctx->server, cmd, ctx->ident);     \
+  }                                                                    \
 } while(0)
 
 /* Prototypes */
 void silc_server_command_process(SilcServer server,
                                 SilcSocketConnection sock,
                                 SilcPacketContext *packet);
-void silc_server_command_pending(SilcCommand reply_cmd,
+void silc_server_command_pending(SilcServer server,
+                                SilcCommand reply_cmd,
                                 unsigned short ident,
                                 SilcCommandCb callback,
                                 void *context);
-void silc_server_command_pending_del(SilcCommand reply_cmd,
+void silc_server_command_pending_del(SilcServer server,
+                                    SilcCommand reply_cmd,
                                     unsigned short ident);
-int silc_server_command_pending_check(SilcServerCommandReplyContext ctx,
+int silc_server_command_pending_check(SilcServer server,
+                                     SilcServerCommandReplyContext ctx,
                                      SilcCommand command, 
                                      unsigned short ident);
 SILC_SERVER_CMD_FUNC(whois);
index 853a52ff79dd3c372d188be634ac140c3a30b280..83eb257cfce88e0299ac71fe4c143eb11cd64279 100644 (file)
@@ -67,6 +67,8 @@ void silc_server_command_reply_process(SilcServer server,
   SilcCommand command;
   unsigned short ident;
 
+  SILC_LOG_DEBUG(("Start"));
+
   /* Get command reply payload from packet */
   payload = silc_command_payload_parse(buffer);
   if (!payload) {
@@ -85,8 +87,8 @@ void silc_server_command_reply_process(SilcServer server,
   ident = silc_command_get_ident(ctx->payload);
       
   /* Check for pending commands and mark to be exeucted */
-  silc_server_command_pending_check(ctx, silc_command_get(ctx->payload),
-                                   ident);
+  silc_server_command_pending_check(server, ctx, 
+                                   silc_command_get(ctx->payload), ident);
 
   /* Execute command reply */
   command = silc_command_get(ctx->payload);
@@ -267,9 +269,12 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
     goto out;
 
   channel_name = strdup(tmp);
+  id = silc_id_payload_parse_id(id_string, len);
+
+  SILC_LOG_DEBUG(("Adding new channel %s id(%s)", channel_name,
+                 silc_id_render(id, SILC_ID_CHANNEL)));
 
   /* Add the channel to our local list. */
-  id = silc_id_payload_parse_id(id_string, len);
   entry = silc_idlist_add_channel(server->local_list, channel_name, 
                                  SILC_CHANNEL_MODE_NONE, id, 
                                  server->id_entry->router, NULL);
@@ -279,10 +284,11 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
     goto out;
   }
 
-  entry->global_users = TRUE;
+  //entry->global_users = TRUE;
 
   /* Execute pending JOIN command so that the client who originally
      wanted to join the channel will be joined after all. */
+  SILC_LOG_DEBUG(("Re-executing JOIN command"));
   SILC_SERVER_COMMAND_EXEC_PENDING(cmd, SILC_COMMAND_JOIN);
 
  out:
index 6f1204a2d92ae92a3e5a1f1f4f3521d4f295fd9f..ec5359bcac9632f5be132ccf37786d9408236a9d 100644 (file)
@@ -57,6 +57,7 @@ int silc_server_alloc(SilcServer *new_server)
   server->standalone = TRUE;
   server->local_list = silc_calloc(1, sizeof(*server->local_list));
   server->global_list = silc_calloc(1, sizeof(*server->global_list));
+  server->pending_commands = silc_dlist_init();
 #ifdef SILC_SIM
   server->sim = silc_dlist_init();
 #endif
@@ -90,6 +91,9 @@ void silc_server_free(SilcServer server)
     if (server->params)
       silc_free(server->params);
 
+    if (server->pending_commands)
+      silc_dlist_uninit(server->pending_commands);
+
     silc_math_primegen_uninit(); /* XXX */
     silc_free(server);
   }
@@ -1674,14 +1678,13 @@ void silc_server_packet_forward(SilcServer server,
   /* Prepare outgoing data buffer for packet sending */
   silc_packet_send_prepare(sock, 0, 0, data_len);
 
-  /* Mungle the packet flags and add the FORWARDED flag */
-  if (data)
-    data[2] |= (unsigned char)SILC_PACKET_FLAG_FORWARDED;
-
   /* Put the data to the buffer */
   if (data && data_len)
     silc_buffer_put(sock->outbuf, data, data_len);
 
+  /* Add the FORWARDED flag to packet flags */
+  sock->outbuf->data[2] |= (unsigned char)SILC_PACKET_FLAG_FORWARDED;
+
   if (idata) {
     cipher = idata->send_key;
     hmac = idata->hmac;
@@ -3099,12 +3102,11 @@ SilcChannelEntry silc_server_new_channel(SilcServer server,
                                         SilcServerID *router_id,
                                         char *cipher, char *channel_name)
 {
-  int i, channel_len, key_len;
+  int i, key_len;
   SilcChannelID *channel_id;
   SilcChannelEntry entry;
   SilcCipher key;
-  unsigned char channel_key[32], *id_string;
-  SilcBuffer packet;
+  unsigned char channel_key[32];
 
   SILC_LOG_DEBUG(("Creating new channel"));
 
@@ -3139,26 +3141,9 @@ SilcChannelEntry silc_server_new_channel(SilcServer server,
   /* Notify other routers about the new channel. We send the packet
      to our primary route. */
   if (server->standalone == FALSE) {
-    channel_len = strlen(channel_name);
-    id_string = silc_id_id2str(entry->id, SILC_ID_CHANNEL);
-    packet = silc_buffer_alloc(2 + SILC_ID_CHANNEL_LEN);
-
-    silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
-    silc_buffer_format(packet,
-                      SILC_STR_UI_SHORT(channel_len),
-                      SILC_STR_UI_XNSTRING(channel_name, channel_len),
-                      SILC_STR_UI_SHORT(SILC_ID_CHANNEL_LEN),
-                      SILC_STR_UI_XNSTRING(id_string, SILC_ID_CHANNEL_LEN),
-                      SILC_STR_END);
-
-    /* Send the packet to our router. */
-    silc_server_packet_send(server, (SilcSocketConnection) 
-                           server->id_entry->router->connection,
-                           SILC_PACKET_NEW_CHANNEL_USER, 0, 
-                           packet->data, packet->len, TRUE);
-    
-    silc_free(id_string);
-    silc_buffer_free(packet);
+    silc_server_send_new_id(server, server->id_entry->router->connection,
+                           server->server_type == SILC_SERVER ? FALSE : TRUE,
+                           entry->id, SILC_ID_CHANNEL, SILC_ID_CHANNEL_LEN);
   }
 
   return entry;
index 0b748b528947af6b9460b988eac75e630804ee26..7278c6a3c6e94b503c010d2676670781707ad8ad 100644 (file)
@@ -97,6 +97,9 @@ struct SilcServerStruct {
   /* Server statistics */
   SilcServerStatistics stats;
 
+  /* Pending command queue */
+  SilcDList pending_commands;
+
   /* Default parameteres for server */
   SilcServerParams params;