Fri Feb 13 13:13:07 CET 2004 Jochen Eisinger <jochen@penguin-breeder.org>
authorJochen Eisinger <coffee@silcnet.org>
Fri, 13 Feb 2004 12:16:52 +0000 (12:16 +0000)
committerJochen Eisinger <coffee@silcnet.org>
Fri, 13 Feb 2004 12:16:52 +0000 (12:16 +0000)
* redirect all silc_client_command_calls through a queueing framework.
  This fixes /CYCLE and the annoying "nick change after auto-joining
  a channel".  Furthermore it defines one central point where
  command parameters can be UTF-8-ified.  Affected files
  irssi/src/silc/core/Makefile, client_ops.c, silc-channels.c,
  silc-servers.[ch], silc-core.c, silc-cmdqueue.[ch], silc-lag.c

CHANGES
apps/irssi/src/silc/core/Makefile.am
apps/irssi/src/silc/core/client_ops.c
apps/irssi/src/silc/core/silc-channels.c
apps/irssi/src/silc/core/silc-cmdqueue.c [new file with mode: 0644]
apps/irssi/src/silc/core/silc-cmdqueue.h [new file with mode: 0644]
apps/irssi/src/silc/core/silc-core.c
apps/irssi/src/silc/core/silc-lag.c
apps/irssi/src/silc/core/silc-servers.c
apps/irssi/src/silc/core/silc-servers.h

diff --git a/CHANGES b/CHANGES
index 1d74cb0fd150a3af4ca8b37ae1e6d602b482a757..11263b3bc6d16ccc799bd99a0aba95771eef45a8 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,12 @@
+Fri Feb 13 13:13:07 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * redirect all silc_client_command_calls through a queueing framework.
+         This fixes /CYCLE and the annoying "nick change after auto-joining
+         a channel".  Furthermore it defines one central point where
+         command parameters can be UTF-8-ified.  Affected files
+         irssi/src/silc/core/Makefile, client_ops.c, silc-channels.c,
+         silc-servers.[ch], silc-core.c, silc-cmdqueue.[ch], silc-lag.c
+
 Fri Feb 13 12:04:41 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
 
        * use asynchronous connect() to establish router connections.
index 04e3a8edb90eb8404874058d9af308d7071d81cc..fb35564c7d890d6dc1b00f3a498e8d62bc7a1f36 100644 (file)
@@ -24,7 +24,8 @@ libsilc_core_a_SOURCES = \
        silc-expandos.c \
        silc-servers-reconnect.c \
        silc-lag.c \
-       silc-chatnets.c
+       silc-chatnets.c \
+       silc-cmdqueue.c
 
 noinst_HEADERS = \
        module.h \
@@ -36,5 +37,6 @@ noinst_HEADERS = \
        silc-commands.h \
        silc-queries.h \
        silc-servers.h \
-       silc-chatnets.h
+       silc-chatnets.h \
+       silc-cmdqueue.h
 
index 3b5ca0ccb1a4726993b75b70149d68c5c3bd94f8..48891788dbec07fce4de9ac0f911c4ed3f174a83 100644 (file)
@@ -29,6 +29,7 @@
 #include "silc-channels.h"
 #include "silc-queries.h"
 #include "silc-nicklist.h"
+#include "silc-cmdqueue.h"
 
 #include "signals.h"
 #include "levels.h"
@@ -761,7 +762,7 @@ void silc_notify(SilcClient client, SilcClientConnection conn,
 
     client_entry = va_arg(va, SilcClientEntry);
     channel = va_arg(va, SilcChannelEntry);
-
+    
     memset(buf, 0, sizeof(buf));
     if (client_entry->username)
       snprintf(buf, sizeof(buf) - 1, "%s@%s",
@@ -1268,6 +1269,9 @@ void silc_connect(SilcClient client, SilcClientConnection conn,
   switch (status) {
   case SILC_CLIENT_CONN_SUCCESS:
     /* We have successfully connected to server */
+    if ((client->nickname != NULL) && 
+        (strcmp(client->nickname, client->username)))
+      silc_queue_enable(conn); /* enable queueing until we have our nick */
     server->connected = TRUE;
     signal_emit("event connected", 1, server);
     break;
@@ -1984,6 +1988,11 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
                             client_entry, client_entry->nickname);
       signal_emit("message own_nick", 4, server, server->nick, old, "");
       g_free(old);
+
+      /* when connecting to a server, the last thing we receive
+         is a SILC_COMMAND_LIST reply. Since we enable queueing
+        during the connection, we can now safely disable it again */
+      silc_queue_disable(conn);
       break;
     }
 
@@ -2442,6 +2451,13 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
     }
     break;
 
+  case SILC_COMMAND_LEAVE:
+    {
+      /* we might be cycling, so disable queueing again */
+      silc_queue_disable(conn);
+    }
+    break;
+
   }
 
   va_end(vp);
index 66b9e990bce565f86cdc5f3335999e9e427cf4fd..4ca89b36ab5da93e02e360188b0cd51d1acaeac7 100644 (file)
@@ -38,6 +38,7 @@
 #include "silc-channels.h"
 #include "silc-queries.h"
 #include "silc-nicklist.h"
+#include "silc-cmdqueue.h"
 #include "window-item-def.h"
 
 #include "fe-common/core/printtext.h"
@@ -103,6 +104,8 @@ static void sig_channel_destroyed(SILC_CHANNEL_REC *channel)
     /* destroying channel record without actually
        having left the channel yet */
     silc_command_exec(channel->server, "LEAVE", channel->name);
+    /* enable queueing because we destroy the channel immedially */
+    silc_queue_enable(channel->server->conn);
   }
 }
 
@@ -195,6 +198,8 @@ static void command_part(const char *data, SILC_SERVER_REC *server,
   
   chanrec->left = TRUE;
   silc_command_exec(server, "LEAVE", chanrec->name);
+  /* enable queueing because we destroy the channel immedially */
+  silc_queue_enable(server->conn);
   signal_stop();
 
   channel_destroy(CHANNEL(chanrec));
diff --git a/apps/irssi/src/silc/core/silc-cmdqueue.c b/apps/irssi/src/silc/core/silc-cmdqueue.c
new file mode 100644 (file)
index 0000000..e2b8892
--- /dev/null
@@ -0,0 +1,126 @@
+#include "module.h"
+#include "silc-cmdqueue.h"
+
+#include <stdarg.h>
+
+GHashTable *cmd_queues;
+
+void silc_queue_init(void)
+{
+  cmd_queues = g_hash_table_new(NULL, NULL);
+}
+
+static void cmd_list_remove_cb(char *cmd)
+{
+  silc_free(cmd);
+}
+
+static int cmd_queue_remove_cb(void *key, GSList *list)
+{
+  if ((list != NULL) && (list->next != NULL)) {
+    g_slist_foreach(list, (GFunc) cmd_list_remove_cb, NULL);
+    g_slist_free(list);
+  }
+
+  return TRUE;
+}
+
+void silc_queue_deinit(void)
+{
+  g_hash_table_foreach_remove(cmd_queues, (GHRFunc) cmd_queue_remove_cb, NULL);
+  g_hash_table_destroy(cmd_queues);
+}
+
+void silc_queue_flush(SilcClientConnection conn)
+{
+  GSList *list = g_hash_table_lookup(cmd_queues, conn);
+
+  if (list != NULL) {
+    GSList *tmp;
+
+    for (tmp = g_slist_next(list); tmp != NULL; tmp = g_slist_next(tmp)) 
+      silc_client_command_call(silc_client, conn, tmp->data);
+
+    g_slist_foreach(list, (GFunc) cmd_list_remove_cb, NULL);
+    /* free all but the first element ... */
+    g_slist_free(g_slist_remove_link(list, list));
+  }
+}
+
+void silc_queue_enable(SilcClientConnection conn)
+{
+  GSList *list = g_hash_table_lookup(cmd_queues, conn);
+
+  if (list == NULL)
+    g_hash_table_insert(cmd_queues, conn, g_slist_alloc());
+}
+
+void silc_queue_disable(SilcClientConnection conn)
+{
+  GSList *list = g_hash_table_lookup(cmd_queues, conn);
+   if (list != NULL) {
+     silc_queue_flush(conn);
+     g_slist_free(list);
+     g_hash_table_remove(cmd_queues, conn);
+   }
+}
+
+bool silc_queue_command_call(SilcClient client,
+                       SilcClientConnection conn,
+                       const char *command_line, ...)
+{
+  va_list ap;
+  char *cmd = (char *) command_line;
+  GSList *list = g_hash_table_lookup(cmd_queues, conn);
+  bool need_free = FALSE;
+
+  va_start(ap, command_line);
+
+  if (command_line == NULL) {
+    char *tmp = va_arg(ap, char *);
+
+    need_free = TRUE;
+
+    if (tmp == NULL) {
+      va_end(ap);
+      return FALSE;
+    }
+
+    cmd = g_strdup(tmp);
+
+    for (tmp = va_arg(ap, char *); tmp != NULL; tmp = va_arg(ap, char *)) {
+      char *old = cmd;
+
+      cmd = g_strconcat(cmd, " ", tmp, NULL);
+      g_free(old);
+    }
+
+  }
+
+  va_end(ap);
+
+  /* FIXME: UTF-8-tify parameters of cmd */
+
+  /* queueing disabled -> immediate execution */
+  if (list == NULL) {
+    bool result = silc_client_command_call(client, conn, cmd);
+
+    if (need_free)
+      g_free(cmd);
+
+    return result;
+  }
+
+  g_hash_table_remove(cmd_queues, conn);
+  g_hash_table_insert(cmd_queues, conn, g_slist_append(list, g_strdup(cmd)));
+
+  if (need_free)
+    g_free(cmd);
+
+  return TRUE;
+}
+
+bool silc_queue_get_state(SilcClientConnection conn) {
+  return g_hash_table_lookup(cmd_queues, conn) != NULL;
+}
diff --git a/apps/irssi/src/silc/core/silc-cmdqueue.h b/apps/irssi/src/silc/core/silc-cmdqueue.h
new file mode 100644 (file)
index 0000000..ee18373
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __SILC_CMDQUEUE_H
+#define __SILC_CMDQUEUE_H
+
+/* wrappers for queuing commands:
+
+   basically the same as the correspondening silc_client_* functions 
+   with one additional parameter:
+   
+   bool sync           - command must be executed in sync (i.e. no
+                         other command may be send before completion)
+   */
+
+bool silc_queue_command_call(SilcClient client, 
+                               SilcClientConnection conn,
+                               const char *command_line, ...);
+
+#define silc_queue_command_pending silc_client_command_pending
+
+/*
+   enable and/or disable command queueing. If command queueing is
+   disabled, all silc_queue_* calls will immedially call silc_client_*
+   functions. If queueing is enabled, all silc_queue_* calls don't have
+   any effect until queueing is disabled again.
+
+   queueing is enabled and disabled for each SilcClientConnection
+   seperatly.
+
+   If queueing is enabled, silc_queue_flush will send all currently
+   queued commands but won't disable queueing.
+ */
+void silc_queue_enable(SilcClientConnection conn);
+void silc_queue_disable(SilcClientConnection conn);
+void silc_queue_flush(SilcClientConnection conn);
+
+/* returns true if queueing is enabled */
+bool silc_queue_get_state(SilcClientConnection conn);
+
+void silc_queue_init(void);
+void silc_queue_deinit(void);
+
+#endif
index 6d826f944b792853d18e2260e797585daac95541..709966ab991053f437f18f3f064c5d26a887609f 100644 (file)
@@ -30,6 +30,7 @@
 #include "silc-queries.h"
 #include "silc-nicklist.h"
 #include "silc-chatnets.h"
+#include "silc-cmdqueue.h"
 
 #include "signals.h"
 #include "levels.h"
@@ -476,6 +477,7 @@ void silc_core_init(void)
   chat_protocol_register(rec);
   g_free(rec);
 
+  silc_queue_init();
   silc_server_init();
   silc_channels_init();
   silc_queries_init();
@@ -498,6 +500,7 @@ void silc_core_deinit(void)
   signal_remove("setup changed", (SIGNAL_FUNC) sig_setup_changed);
   signal_remove("irssi init finished", (SIGNAL_FUNC) sig_init_finished);
 
+  silc_queue_deinit();
   silc_server_deinit();
   silc_channels_deinit();
   silc_queries_deinit();
index 1c5ad516dacd679d13b9839f4cfc266309139a05..ba2d9b30ebbed5b1690a607f51bb9101cb45dd06 100644 (file)
@@ -82,7 +82,7 @@ static int sig_check_lag(void)
                                server_disconnect((SERVER_REC *) rec);
                        }
                } else if (rec->lag_last_check+lag_check_time < now &&
-                        rec->cmdcount == 0 && rec->connected) {
+                        rec->connected) {
                        /* no commands in buffer - get the lag */
                        lag_get(rec);
                }
index cc901cad3bcf4c34a3d6365efddb961155c993dc..0a952318950a5e0e638cc2c49688a137de416629 100644 (file)
@@ -39,6 +39,7 @@
 #include "silc-channels.h"
 #include "silc-queries.h"
 #include "silc-nicklist.h"
+#include "silc-cmdqueue.h"
 #include "window-item-def.h"
 
 #include "fe-common/core/printtext.h"
@@ -455,7 +456,7 @@ void silc_command_exec(SILC_SERVER_REC *server,
 
   /* Call the command */
   data = g_strconcat(command, " ", args, NULL);
-  silc_client_command_call(silc_client, server->conn, data);
+  silc_queue_command_call(silc_client, server->conn, data);
   g_free(data);
 }
 
index 5e63c09bf9b3a6075c2972e67e33113bff4fed6c..cc6b94439f1f5ca551c4f7931014df02320b0a67 100644 (file)
@@ -38,18 +38,6 @@ typedef struct {
 #define STRUCT_SERVER_CONNECT_REC SILC_SERVER_CONNECT_REC
 typedef struct {
 #include "server-rec.h"
-  /* Command sending queue */
-  int cmdcount;                /* number of commands in `cmdqueue'. Can be more than
-                          there actually is, to make flood control remember
-                          how many messages can be sent before starting the
-                          flood control */
-  int cmd_last_split;  /* Last command wasn't sent entirely to server.
-                          First item in `cmdqueue' should be re-sent. */
-  GSList *cmdqueue;
-  GTimeVal last_cmd;   /* last time command was sent to server */
-  
-  GSList *idles;       /* Idle queue - send these commands to server
-                          if there's nothing else to do */
 
   SilcDList ftp_sessions;
   FtpSession current_session;