From: Jochen Eisinger Date: Fri, 13 Feb 2004 12:16:52 +0000 (+0000) Subject: Fri Feb 13 13:13:07 CET 2004 Jochen Eisinger X-Git-Tag: silc.server.0.9.17~28 X-Git-Url: http://git.silcnet.org/gitweb/?a=commitdiff_plain;h=cf8d4b59db0e24b2531965f93633bc09036767e4;p=silc.git Fri Feb 13 13:13:07 CET 2004 Jochen Eisinger * 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 --- diff --git a/CHANGES b/CHANGES index 1d74cb0f..11263b3b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,12 @@ +Fri Feb 13 13:13:07 CET 2004 Jochen Eisinger + + * 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 * use asynchronous connect() to establish router connections. diff --git a/apps/irssi/src/silc/core/Makefile.am b/apps/irssi/src/silc/core/Makefile.am index 04e3a8ed..fb35564c 100644 --- a/apps/irssi/src/silc/core/Makefile.am +++ b/apps/irssi/src/silc/core/Makefile.am @@ -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 diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c index 3b5ca0cc..48891788 100644 --- a/apps/irssi/src/silc/core/client_ops.c +++ b/apps/irssi/src/silc/core/client_ops.c @@ -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); diff --git a/apps/irssi/src/silc/core/silc-channels.c b/apps/irssi/src/silc/core/silc-channels.c index 66b9e990..4ca89b36 100644 --- a/apps/irssi/src/silc/core/silc-channels.c +++ b/apps/irssi/src/silc/core/silc-channels.c @@ -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 index 00000000..e2b88927 --- /dev/null +++ b/apps/irssi/src/silc/core/silc-cmdqueue.c @@ -0,0 +1,126 @@ +#include "module.h" +#include "silc-cmdqueue.h" + +#include + +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 index 00000000..ee183738 --- /dev/null +++ b/apps/irssi/src/silc/core/silc-cmdqueue.h @@ -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 diff --git a/apps/irssi/src/silc/core/silc-core.c b/apps/irssi/src/silc/core/silc-core.c index 6d826f94..709966ab 100644 --- a/apps/irssi/src/silc/core/silc-core.c +++ b/apps/irssi/src/silc/core/silc-core.c @@ -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(); diff --git a/apps/irssi/src/silc/core/silc-lag.c b/apps/irssi/src/silc/core/silc-lag.c index 1c5ad516..ba2d9b30 100644 --- a/apps/irssi/src/silc/core/silc-lag.c +++ b/apps/irssi/src/silc/core/silc-lag.c @@ -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); } diff --git a/apps/irssi/src/silc/core/silc-servers.c b/apps/irssi/src/silc/core/silc-servers.c index cc901cad..0a952318 100644 --- a/apps/irssi/src/silc/core/silc-servers.c +++ b/apps/irssi/src/silc/core/silc-servers.c @@ -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); } diff --git a/apps/irssi/src/silc/core/silc-servers.h b/apps/irssi/src/silc/core/silc-servers.h index 5e63c09b..cc6b9443 100644 --- a/apps/irssi/src/silc/core/silc-servers.h +++ b/apps/irssi/src/silc/core/silc-servers.h @@ -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;