Moved rewritten server redirection code from core to irc. This new code

should be able to do the redirecting a lot more error-proof. Changed
lag-checking to use PINGs instead of NOTIFYs. This breaks scripts using
redirection. Hopefully this doesn't break too much things in irssi :)


git-svn-id: http://svn.irssi.org/repos/irssi/trunk@1980 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Timo Sirainen 2001-11-11 18:59:19 +00:00 committed by cras
commit 850cf993eb
28 changed files with 908 additions and 786 deletions

View file

@ -44,7 +44,6 @@ libcore_a_SOURCES = \
rawlog.c \
servers.c \
servers-reconnect.c \
servers-redirect.c \
servers-setup.c \
settings.c \
signals.c \
@ -92,7 +91,6 @@ noinst_HEADERS = \
rawlog.h \
servers.h \
servers-reconnect.h \
servers-redirect.h \
servers-setup.h \
settings.h \
signals.h \

View file

@ -26,7 +26,6 @@
#include "window-item-def.h"
#include "servers.h"
#include "servers-redirect.h"
#include "channels.h"
#include "lib-config/iconfig.h"
@ -853,10 +852,8 @@ static void parse_command(const char *command, int expand_aliases,
}
cmd = g_strconcat("command ", newcmd, NULL);
if (server != NULL)
server_redirect_default(SERVER(server), cmd);
g_strdown(cmd);
oldcmd = current_command;
current_command = cmd+8;
if (!signal_emit(cmd, 3, args, server, item)) {

View file

@ -21,11 +21,6 @@ GIOChannel *connect_pipe[2];
int connect_tag;
int connect_pid;
/* For deciding if event should be handled internally */
GHashTable *eventtable; /* "event xxx" : GSList* of REDIRECT_RECs */
GHashTable *eventgrouptable; /* event group : GSList* of REDIRECT_RECs */
GHashTable *cmdtable; /* "command xxx" : REDIRECT_CMD_REC* */
RAWLOG_REC *rawlog;
LINEBUF_REC *buffer; /* receive buffer */
GHashTable *module_data;

View file

@ -1,359 +0,0 @@
/*
server-redirect.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "module.h"
#include "signals.h"
#include "misc.h"
#include "servers.h"
#include "servers-redirect.h"
static int redirect_group;
static void server_eventtable_destroy(char *key, GSList *value)
{
GSList *tmp;
g_free(key);
for (tmp = value; tmp != NULL; tmp = tmp->next) {
REDIRECT_REC *rec = tmp->data;
g_free_not_null(rec->arg);
g_free(rec->name);
g_free(rec);
}
g_slist_free(value);
}
static void server_eventgrouptable_destroy(gpointer key, GSList *value)
{
g_slist_foreach(value, (GFunc) g_free, NULL);
g_slist_free(value);
}
static void server_cmdtable_destroy(char *key, REDIRECT_CMD_REC *value)
{
g_free(key);
g_slist_foreach(value->events, (GFunc) g_free, NULL);
g_slist_free(value->events);
g_free(value);
}
static void sig_disconnected(SERVER_REC *server)
{
g_return_if_fail(IS_SERVER(server));
if (server->eventtable != NULL) {
g_hash_table_foreach(server->eventtable,
(GHFunc) server_eventtable_destroy, NULL);
g_hash_table_destroy(server->eventtable);
}
g_hash_table_foreach(server->eventgrouptable,
(GHFunc) server_eventgrouptable_destroy, NULL);
g_hash_table_destroy(server->eventgrouptable);
if (server->cmdtable != NULL) {
g_hash_table_foreach(server->cmdtable,
(GHFunc) server_cmdtable_destroy, NULL);
g_hash_table_destroy(server->cmdtable);
}
}
void server_redirect_initv(SERVER_REC *server, const char *command,
int last, GSList *list)
{
REDIRECT_CMD_REC *rec;
g_return_if_fail(IS_SERVER(server));
g_return_if_fail(command != NULL);
g_return_if_fail(last > 0);
if (g_hash_table_lookup(server->cmdtable, command) != NULL) {
/* already in hash table. list of events SHOULD be the same. */
g_slist_foreach(list, (GFunc) g_free, NULL);
g_slist_free(list);
return;
}
rec = g_new(REDIRECT_CMD_REC, 1);
rec->last = last;
rec->events = list;
g_hash_table_insert(server->cmdtable, g_strdup(command), rec);
}
void server_redirect_init(SERVER_REC *server, const char *command,
int last, ...)
{
va_list args;
GSList *list;
char *event;
va_start(args, last);
list = NULL;
while ((event = va_arg(args, gchar *)) != NULL)
list = g_slist_append(list, g_strdup(event));
va_end(args);
server_redirect_initv(server, command, last, list);
}
int server_redirect_single_event(SERVER_REC *server, const char *arg,
int last, int group, const char *event,
const char *signal, int argpos)
{
REDIRECT_REC *rec;
GSList *list, *grouplist;
char *origkey;
g_return_val_if_fail(IS_SERVER(server), 0);
g_return_val_if_fail(event != NULL, 0);
g_return_val_if_fail(signal != NULL, 0);
g_return_val_if_fail(arg != NULL || argpos == -1, 0);
if (group == 0) group = ++redirect_group;
rec = g_new0(REDIRECT_REC, 1);
rec->arg = arg == NULL ? NULL : g_strdup(arg);
rec->argpos = argpos;
rec->name = g_strdup(signal);
rec->group = group;
rec->last = last;
if (g_hash_table_lookup_extended(server->eventtable, event,
(gpointer *) &origkey,
(gpointer *) &list)) {
g_hash_table_remove(server->eventtable, origkey);
} else {
list = NULL;
origkey = g_strdup(event);
}
grouplist = g_hash_table_lookup(server->eventgrouptable,
GINT_TO_POINTER(group));
if (grouplist != NULL) {
g_hash_table_remove(server->eventgrouptable,
GINT_TO_POINTER(group));
}
list = g_slist_append(list, rec);
grouplist = g_slist_append(grouplist, g_strdup(event));
g_hash_table_insert(server->eventtable, origkey, list);
g_hash_table_insert(server->eventgrouptable,
GINT_TO_POINTER(group), grouplist);
return group;
}
void server_redirect_event(SERVER_REC *server, const char *arg, int last, ...)
{
va_list args;
char *event, *signal;
int argpos, group;
g_return_if_fail(IS_SERVER(server));
va_start(args, last);
group = 0;
while ((event = va_arg(args, gchar *)) != NULL) {
signal = va_arg(args, gchar *);
argpos = va_arg(args, gint);
group = server_redirect_single_event(server, arg, last > 0,
group, event, signal,
argpos);
last--;
}
va_end(args);
}
void server_redirect_default(SERVER_REC *server, const char *command)
{
REDIRECT_CMD_REC *cmdrec;
REDIRECT_REC *rec;
GSList *events, *list, *grouplist;
char *event, *origkey;
int last;
g_return_if_fail(IS_SERVER(server));
g_return_if_fail(command != NULL);
if (server->cmdtable == NULL)
return; /* not connected yet */
cmdrec = g_hash_table_lookup(server->cmdtable, command);
if (cmdrec == NULL) return;
/* add all events used by command to eventtable and eventgrouptable */
redirect_group++; grouplist = NULL; last = cmdrec->last;
for (events = cmdrec->events; events != NULL; events = events->next) {
event = events->data;
if (g_hash_table_lookup_extended(server->eventtable, event,
(gpointer *) &origkey,
(gpointer *) &list)) {
g_hash_table_remove(server->eventtable, origkey);
} else {
list = NULL;
origkey = g_strdup(event);
}
rec = g_new0(REDIRECT_REC, 1);
rec->argpos = -1;
rec->name = g_strdup(event);
rec->group = redirect_group;
rec->last = last > 0;
grouplist = g_slist_append(grouplist, g_strdup(event));
list = g_slist_append(list, rec);
g_hash_table_insert(server->eventtable, origkey, list);
last--;
}
g_hash_table_insert(server->eventgrouptable,
GINT_TO_POINTER(redirect_group), grouplist);
}
void server_redirect_remove_next(SERVER_REC *server, const char *event,
GSList *item)
{
REDIRECT_REC *rec;
GSList *grouplist, *list, *events, *tmp;
char *origkey;
int group;
g_return_if_fail(IS_SERVER(server));
g_return_if_fail(event != NULL);
if (!g_hash_table_lookup_extended(server->eventtable, event,
(gpointer *) &origkey,
(gpointer *) &list))
return;
rec = item == NULL ? list->data : item->data;
if (!rec->last) {
/* this wasn't last expected event */
return;
}
group = rec->group;
/* get list of events from this group */
grouplist = g_hash_table_lookup(server->eventgrouptable,
GINT_TO_POINTER(group));
/* remove all of them */
for (list = grouplist; list != NULL; list = list->next) {
char *event = list->data;
if (!g_hash_table_lookup_extended(server->eventtable, event,
(gpointer *) &origkey,
(gpointer *) &events)) {
g_warning("server_redirect_remove_next() : "
"event in eventgrouptable but not in "
"eventtable");
continue;
}
/* remove the right group */
for (tmp = events; tmp != NULL; tmp = tmp->next) {
rec = tmp->data;
if (rec->group == group)
break;
}
if (rec == NULL) {
g_warning("server_redirect_remove_next() : "
"event in eventgrouptable but not in "
"eventtable (group)");
continue;
}
g_free(event);
events = g_slist_remove(events, rec);
g_free_not_null(rec->arg);
g_free(rec->name);
g_free(rec);
/* update hash table */
g_hash_table_remove(server->eventtable, origkey);
if (events == NULL)
g_free(origkey);
else {
g_hash_table_insert(server->eventtable,
origkey, events);
}
}
g_hash_table_remove(server->eventgrouptable, GINT_TO_POINTER(group));
g_slist_free(grouplist);
}
GSList *server_redirect_getqueue(SERVER_REC *server, const char *event,
const char *args)
{
REDIRECT_REC *rec;
GSList *list;
char **arglist;
int found;
g_return_val_if_fail(IS_SERVER(server), NULL);
g_return_val_if_fail(event != NULL, NULL);
list = g_hash_table_lookup(server->eventtable, event);
for (; list != NULL; list = list->next) {
rec = list->data;
if (rec->argpos == -1)
break;
if (rec->arg == NULL || args == NULL)
continue;
/* we need to check that the argument is right.. */
arglist = g_strsplit(args, " ", -1);
found = (strarray_length(arglist) > rec->argpos &&
find_substr(rec->arg, arglist[rec->argpos]));
g_strfreev(arglist);
if (found) break;
}
return list;
}
void servers_redirect_init(void)
{
redirect_group = 0;
signal_add("server disconnected", (SIGNAL_FUNC) sig_disconnected);
}
void servers_redirect_deinit(void)
{
signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected);
}

View file

@ -1,36 +0,0 @@
#ifndef __SERVERS_REDIRECT_H
#define __SERVERS_REDIRECT_H
typedef struct {
int last; /* number of "last" events at the start of the events list */
GSList *events; /* char* list of events */
} REDIRECT_CMD_REC;
typedef struct {
char *name; /* event name */
char *arg; /* argument for event we are expecting or NULL */
int argpos; /* argument position */
int group; /* group of events this belongs to */
int last; /* if this event is received, remove all the events in this group */
}
REDIRECT_REC;
void server_redirect_init(SERVER_REC *server, const char *command, int last, ...);
void server_redirect_initv(SERVER_REC *server, const char *command, int last, GSList *list);
/* ... = char *event1, char *event2, ..., NULL */
void server_redirect_event(SERVER_REC *server, const char *arg, int last, ...);
/* ... = char *event, char *callback_signal, int argpos, ..., NULL */
int server_redirect_single_event(SERVER_REC *server, const char *arg, int last, int group,
const char *event, const char *signal, int argpos);
void server_redirect_default(SERVER_REC *server, const char *command);
void server_redirect_remove_next(SERVER_REC *server, const char *event, GSList *item);
GSList *server_redirect_getqueue(SERVER_REC *server, const char *event, const char *args);
void servers_redirect_init(void);
void servers_redirect_deinit(void);
#endif

View file

@ -31,7 +31,6 @@
#include "chat-protocols.h"
#include "servers.h"
#include "servers-reconnect.h"
#include "servers-redirect.h"
#include "servers-setup.h"
#include "channels.h"
#include "queries.h"
@ -136,10 +135,6 @@ void server_connect_finished(SERVER_REC *server)
server->connect_time = time(NULL);
server->rawlog = rawlog_create();
server->eventtable = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal);
server->eventgrouptable = g_hash_table_new((GHashFunc) g_direct_hash, (GCompareFunc) g_direct_equal);
server->cmdtable = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal);
servers = g_slist_append(servers, server);
signal_emit("server connected", 1, server);
}
@ -553,7 +548,6 @@ void servers_init(void)
signal_add("chat protocol deinit", (SIGNAL_FUNC) sig_chat_protocol_deinit);
servers_reconnect_init();
servers_redirect_init();
servers_setup_init();
}
@ -562,7 +556,6 @@ void servers_deinit(void)
signal_remove("chat protocol deinit", (SIGNAL_FUNC) sig_chat_protocol_deinit);
servers_setup_deinit();
servers_redirect_deinit();
servers_reconnect_deinit();
module_uniq_destroy("SERVER");