mirror of
https://github.com/irssi/irssi.git
synced 2024-12-04 14:46:39 -05:00
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:
parent
712f3b383d
commit
850cf993eb
@ -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 \
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
@ -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");
|
||||
|
@ -309,17 +309,10 @@ static void event_connected(IRC_SERVER_REC *server)
|
||||
return;
|
||||
|
||||
/* someone has our nick, find out who. */
|
||||
server_redirect_event(server, "whois", nick, FALSE, NULL,
|
||||
"event 311", "nickfind event whois",
|
||||
"", "event empty", NULL);
|
||||
irc_send_cmdv(server, "WHOIS %s", nick);
|
||||
server_redirect_event((SERVER_REC *) server, nick, 1,
|
||||
"event 318", "event empty", 1,
|
||||
"event 401", "event empty", 1,
|
||||
"event 311", "nickfind event whois", 1,
|
||||
"event 301", "event empty", 1,
|
||||
"event 312", "event empty", 1,
|
||||
"event 313", "event empty", 1,
|
||||
"event 317", "event empty", 1,
|
||||
"event 319", "event empty", 1, NULL);
|
||||
|
||||
}
|
||||
|
||||
static void event_nickfind_whois(IRC_SERVER_REC *server, const char *data)
|
||||
|
@ -30,7 +30,8 @@ libirc_core_a_SOURCES = \
|
||||
modes.c \
|
||||
mode-lists.c \
|
||||
netsplit.c \
|
||||
server-idle.c
|
||||
servers-idle.c \
|
||||
servers-redirect.c
|
||||
|
||||
noinst_HEADERS = \
|
||||
bans.h \
|
||||
@ -49,4 +50,5 @@ noinst_HEADERS = \
|
||||
mode-lists.h \
|
||||
module.h \
|
||||
netsplit.h \
|
||||
server-idle.h
|
||||
servers-idle.h \
|
||||
servers-redirect.h
|
||||
|
@ -209,11 +209,10 @@ static void channel_send_query(IRC_SERVER_REC *server, int query)
|
||||
for (tmp = chans; tmp != NULL; tmp = tmp->next) {
|
||||
chanrec = tmp->data;
|
||||
|
||||
server_redirect_event((SERVER_REC *) server, chanstr, 4,
|
||||
"event 403", "chanquery mode abort", 1,
|
||||
"event 442", "chanquery mode abort", 1, /* "you're not on that channel" */
|
||||
"event 479", "chanquery mode abort", 1, /* "Cannot join channel (illegal name)" IMHO this is not a logical reply from server. */
|
||||
"event 324", "chanquery mode", 1, NULL);
|
||||
server_redirect_event(server, "mode channel", chanstr, -1,
|
||||
"chanquery mode abort",
|
||||
"event 324", "chanquery mode",
|
||||
"", "chanquery mode abort", NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -223,11 +222,11 @@ static void channel_send_query(IRC_SERVER_REC *server, int query)
|
||||
for (tmp = chans; tmp != NULL; tmp = tmp->next) {
|
||||
chanrec = tmp->data;
|
||||
|
||||
server_redirect_event((SERVER_REC *) server, chanstr, 3,
|
||||
"event 401", "chanquery who abort", 1,
|
||||
"event 403", "chanquery who abort", 1,
|
||||
"event 315", "chanquery who end", 1,
|
||||
"event 352", "silent event who", 1, NULL);
|
||||
server_redirect_event(server, "who", chanstr, -1,
|
||||
"chanquery who abort",
|
||||
"event 315", "chanquery who end",
|
||||
"event 352", "silent event who",
|
||||
"", "chanquery who abort", NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -240,12 +239,11 @@ static void channel_send_query(IRC_SERVER_REC *server, int query)
|
||||
mode requests - if channels are joined manually
|
||||
irssi could ask modes separately but afterwards
|
||||
join the two b/e/I modes together */
|
||||
server_redirect_event((SERVER_REC *) server, chanstr, 4,
|
||||
"event 403", "chanquery mode abort", 1,
|
||||
"event 442", "chanquery mode abort", 1, /* "you're not on that channel" */
|
||||
"event 479", "chanquery mode abort", 1, /* "Cannot join channel (illegal name)" IMHO this is not a logical reply from server. */
|
||||
"event 368", "chanquery ban end", 1,
|
||||
"event 367", "chanquery ban", 1, NULL);
|
||||
server_redirect_event(server, "mode b", chanstr, -1,
|
||||
"chanquery mode abort",
|
||||
"event 367", "chanquery ban",
|
||||
"event 368", "chanquery ban end",
|
||||
"", "chanquery mode abort", NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -254,12 +252,11 @@ static void channel_send_query(IRC_SERVER_REC *server, int query)
|
||||
for (tmp = chans; tmp != NULL; tmp = tmp->next) {
|
||||
chanrec = tmp->data;
|
||||
|
||||
server_redirect_event((SERVER_REC *) server, chanstr, 4,
|
||||
"event 403", "chanquery mode abort", 1,
|
||||
"event 442", "chanquery mode abort", 1, /* "you're not on that channel" */
|
||||
"event 479", "chanquery mode abort", 1, /* "Cannot join channel (illegal name)" IMHO this is not a logical reply from server. */
|
||||
"event 349", "chanquery eban end", 1,
|
||||
"event 348", "chanquery eban", 1, NULL);
|
||||
server_redirect_event(server, "mode e", chanstr, -1,
|
||||
"chanquery mode abort",
|
||||
"event 348", "chanquery eban",
|
||||
"event 349", "chanquery eban end",
|
||||
"", "chanquery mode abort", NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -268,12 +265,11 @@ static void channel_send_query(IRC_SERVER_REC *server, int query)
|
||||
for (tmp = chans; tmp != NULL; tmp = tmp->next) {
|
||||
chanrec = tmp->data;
|
||||
|
||||
server_redirect_event((SERVER_REC *) server, chanstr, 4,
|
||||
"event 403", "chanquery mode abort", 1,
|
||||
"event 442", "chanquery mode abort", 1, /* "you're not on that channel" */
|
||||
"event 479", "chanquery mode abort", 1, /* "Cannot join channel (illegal name)" IMHO this is not a logical reply from server. */
|
||||
"event 347", "chanquery ilist end", 1,
|
||||
"event 346", "chanquery ilist", 1, NULL);
|
||||
server_redirect_event(server, "mode I", chanstr, -1,
|
||||
"chanquery mode abort",
|
||||
"event 346", "chanquery ilist",
|
||||
"event 347", "chanquery ilist end",
|
||||
"", "chanquery mode abort", NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -423,14 +419,6 @@ static void event_channel_mode(IRC_SERVER_REC *server, const char *data,
|
||||
g_free(params);
|
||||
}
|
||||
|
||||
static void multi_query_remove(IRC_SERVER_REC *server, const char *event, const char *data)
|
||||
{
|
||||
GSList *queue;
|
||||
|
||||
while ((queue = server_redirect_getqueue((SERVER_REC *) server, event, data)) != NULL)
|
||||
server_redirect_remove_next((SERVER_REC *) server, event, queue);
|
||||
}
|
||||
|
||||
static void event_end_of_who(IRC_SERVER_REC *server, const char *data)
|
||||
{
|
||||
IRC_CHANNEL_REC *chanrec;
|
||||
@ -447,7 +435,6 @@ static void event_end_of_who(IRC_SERVER_REC *server, const char *data)
|
||||
/* instead of multiple End of WHO replies we get
|
||||
only this one... */
|
||||
server->one_endofwho = TRUE;
|
||||
multi_query_remove(server, "event 315", data);
|
||||
|
||||
/* check that the WHO actually did return something
|
||||
(that it understood #chan1,#chan2,..) */
|
||||
@ -549,8 +536,6 @@ static void multi_command_error(IRC_SERVER_REC *server, const char *data,
|
||||
char *params, *channel, **chans;
|
||||
int n;
|
||||
|
||||
multi_query_remove(server, event, data);
|
||||
|
||||
params = event_get_params(data, 2, NULL, &channel);
|
||||
|
||||
chans = g_strsplit(channel, ",", -1);
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include "settings.h"
|
||||
|
||||
#include "irc-servers.h"
|
||||
#include "server-idle.h"
|
||||
#include "servers-idle.h"
|
||||
#include "ignore.h"
|
||||
|
||||
static void ctcp_queue_clean(IRC_SERVER_REC *server)
|
||||
@ -57,7 +57,7 @@ void ctcp_send_reply(IRC_SERVER_REC *server, const char *data)
|
||||
return;
|
||||
|
||||
/* Add to first in idle queue */
|
||||
tag = server_idle_add(server, data, NULL, 0, NULL);
|
||||
tag = server_idle_add(server, data);
|
||||
server->ctcpqueue =
|
||||
g_slist_append(server->ctcpqueue, GINT_TO_POINTER(tag));
|
||||
}
|
||||
|
@ -244,9 +244,6 @@ static void cmd_list(const char *data, IRC_SERVER_REC *server,
|
||||
|
||||
irc_send_cmdv(server, "LIST %s", str);
|
||||
cmd_params_free(free_arg);
|
||||
|
||||
/* add default redirection */
|
||||
server_redirect_default((SERVER_REC *) server, "bogus command list");
|
||||
}
|
||||
|
||||
/* SYNTAX: WHO [<nicks> | <channels> | **] */
|
||||
@ -275,9 +272,6 @@ static void cmd_who(const char *data, IRC_SERVER_REC *server,
|
||||
irc_send_cmdv(server, *rest == '\0' ? "WHO %s" : "WHO %s %s",
|
||||
channel, rest);
|
||||
cmd_params_free(free_arg);
|
||||
|
||||
/* add default redirection */
|
||||
server_redirect_default((SERVER_REC *) server, "bogus command who");
|
||||
}
|
||||
|
||||
static void cmd_names(const char *data, IRC_SERVER_REC *server,
|
||||
@ -323,43 +317,10 @@ static void cmd_nick(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item
|
||||
if (!cmd_get_params(data, &free_arg, 1, &nick))
|
||||
return;
|
||||
|
||||
if (strcmp(nick, server->nick) == 0) {
|
||||
/* don't bother trying to change the nick to the one you
|
||||
already have */
|
||||
cmd_params_free(free_arg);
|
||||
return;
|
||||
}
|
||||
|
||||
server->nick_changing = TRUE;
|
||||
irc_send_cmdv(server, "NICK %s", nick);
|
||||
|
||||
nick = g_strdup_printf("%s :%s", nick, nick);
|
||||
server_redirect_event(SERVER(server), nick, 5,
|
||||
"event nick", "nickchange over", -1,
|
||||
"event 433", "nickchange over", 1,
|
||||
/* 437: ircnet = target unavailable,
|
||||
dalnet = banned in channel,
|
||||
can't change nick */
|
||||
"event 437", "nickchange over", -1,
|
||||
"event 432", "nickchange over", 1,
|
||||
"event 438", "nickchange over", 1, NULL);
|
||||
g_free(nick);
|
||||
cmd_params_free(free_arg);
|
||||
}
|
||||
|
||||
static void sig_nickchange_over(IRC_SERVER_REC *server, const char *data,
|
||||
const char *nick, const char *addr)
|
||||
{
|
||||
char *signal;
|
||||
|
||||
server->nick_changing = FALSE;
|
||||
|
||||
signal = g_strconcat("event ", current_server_event, NULL);
|
||||
g_strdown(signal+6);
|
||||
signal_emit(signal, 4, server, data, nick, addr);
|
||||
g_free(signal);
|
||||
}
|
||||
|
||||
static char *get_redirect_nicklist(const char *nicks, int *free)
|
||||
{
|
||||
char *str, *ret;
|
||||
@ -419,20 +380,21 @@ static void cmd_whois(const char *data, IRC_SERVER_REC *server,
|
||||
event_402 = "whois event noserver";
|
||||
}
|
||||
|
||||
server->whois_found = FALSE;
|
||||
irc_send_cmd_split(server, tmpstr->str, 2, server->max_whois_in_cmd);
|
||||
|
||||
/* do automatic /WHOWAS if any of the nicks wasn't found */
|
||||
query = get_redirect_nicklist(query, &free_nick);
|
||||
|
||||
str = g_strconcat(qserver, " ", query, NULL);
|
||||
server_redirect_event(SERVER(server), str, 2,
|
||||
"event 318", "event 318", 1,
|
||||
"event 402", event_402, 1,
|
||||
"event 401", "whois not found", 1,
|
||||
"event 311", "whois event", 1, NULL);
|
||||
server_redirect_event(server, "whois", str, *qserver != '\0',
|
||||
NULL,
|
||||
"event 318", "event 318",
|
||||
"event 402", event_402,
|
||||
"event 401", "whois not found",
|
||||
"event 311", "whois event", NULL);
|
||||
g_free(str);
|
||||
|
||||
server->whois_found = FALSE;
|
||||
irc_send_cmd_split(server, tmpstr->str, 2, server->max_whois_in_cmd);
|
||||
|
||||
if (free_nick) g_free(query);
|
||||
cmd_params_free(free_arg);
|
||||
}
|
||||
@ -451,13 +413,14 @@ static void sig_whois_not_found(IRC_SERVER_REC *server, const char *data)
|
||||
g_return_if_fail(data != NULL);
|
||||
|
||||
params = event_get_params(data, 2, NULL, &nick);
|
||||
irc_send_cmdv(server, "WHOWAS %s 1", nick);
|
||||
|
||||
server->whowas_found = FALSE;
|
||||
server_redirect_event(SERVER(server), nick, 1,
|
||||
"event 369", "whowas event end", 1,
|
||||
"event 314", "whowas event", 1,
|
||||
"event 406", "event empty", 1, NULL);
|
||||
server_redirect_event(server, "whowas", nick, -1, NULL,
|
||||
"event 314", "whowas event",
|
||||
"event 369", "whowas event end",
|
||||
"", "event empty", NULL);
|
||||
irc_send_cmdv(server, "WHOWAS %s 1", nick);
|
||||
|
||||
g_free(params);
|
||||
}
|
||||
|
||||
@ -470,7 +433,7 @@ static void event_whowas(IRC_SERVER_REC *server, const char *data, const char *n
|
||||
/* SYNTAX: WHOWAS [<nicks> [<count>]] */
|
||||
static void cmd_whowas(const char *data, IRC_SERVER_REC *server)
|
||||
{
|
||||
char *nicks, *count;
|
||||
char *nicks, *count, *nicks_redir;
|
||||
void *free_arg;
|
||||
int free_nick;
|
||||
|
||||
@ -480,15 +443,15 @@ static void cmd_whowas(const char *data, IRC_SERVER_REC *server)
|
||||
return;
|
||||
if (*nicks == '\0') nicks = server->nick;
|
||||
|
||||
nicks_redir = get_redirect_nicklist(nicks, &free_nick);
|
||||
server_redirect_event(server, "whowas", nicks_redir, -1, NULL,
|
||||
"event 314", "whowas event", NULL);
|
||||
if (free_nick) g_free(nicks_redir);
|
||||
|
||||
server->whowas_found = FALSE;
|
||||
irc_send_cmdv(server, *count == '\0' ? "WHOWAS %s" :
|
||||
"WHOWAS %s %s", nicks, count);
|
||||
|
||||
nicks = get_redirect_nicklist(nicks, &free_nick);
|
||||
server_redirect_event(SERVER(server), nicks, 1,
|
||||
"event 369", "event 369", 1,
|
||||
"event 314", "whowas event", 1, NULL);
|
||||
if (free_nick) g_free(nicks);
|
||||
cmd_params_free(free_arg);
|
||||
}
|
||||
|
||||
@ -914,48 +877,6 @@ static void command_2self(const char *data, IRC_SERVER_REC *server)
|
||||
cmd_params_free(free_arg);
|
||||
}
|
||||
|
||||
static void sig_connected(IRC_SERVER_REC *server)
|
||||
{
|
||||
g_return_if_fail(server != NULL);
|
||||
|
||||
/* FIXME: these two aren't probably needed? this whole redirection
|
||||
thing might need some rethinking :) */
|
||||
/* WHOIS */
|
||||
/*server_redirect_init(SERVER(server), "", 2,
|
||||
"event 318", "event 402", "event 401",
|
||||
"event 301", "event 311", "event 312", "event 313",
|
||||
"event 317", "event 319", NULL);*/
|
||||
|
||||
/* NICK */
|
||||
/*server_redirect_init(SERVER(server), "", 5,
|
||||
"event nick", "event 433", "event 437",
|
||||
"event 432", "event 438", NULL);*/
|
||||
|
||||
/* problem (doesn't really apply currently since there's no GUI):
|
||||
|
||||
second argument of server_redirect_init() is the command that
|
||||
generates the redirection automatically when it's called, but the
|
||||
command handler doesn't really know about the redirection itself.
|
||||
|
||||
every time the command is called, this redirection is generated.
|
||||
this is a problem if the redirection is wanted sometimes but not
|
||||
always. for example /WHO #channel could create a window with a
|
||||
list of people in channel redirecting WHO's events to it's own use,
|
||||
but /WHO -nogui #channel would use the default WHO handler which
|
||||
doesn't know anything about redirection. with GUI /WHO the
|
||||
redirection would be done twice then..
|
||||
|
||||
so the kludgy workaround currently is this: make the default
|
||||
handler handle the redirection always.. when default WHO/LIST
|
||||
handler is called, they call
|
||||
server_redirect_default("bogus command who") or ..list..
|
||||
|
||||
this is really a problem if some script/plugin wants to override
|
||||
some default command to use redirections.. */
|
||||
server_redirect_init(SERVER(server), "bogus command who", 2, "event 401", "event 315", "event 352", NULL);
|
||||
server_redirect_init(SERVER(server), "bogus command list", 1, "event 321", "event 322", "event 323", NULL);
|
||||
}
|
||||
|
||||
void irc_commands_init(void)
|
||||
{
|
||||
tmpstr = g_string_new(NULL);
|
||||
@ -1048,11 +969,9 @@ void irc_commands_init(void)
|
||||
|
||||
signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
|
||||
signal_add("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
|
||||
signal_add("nickchange over", (SIGNAL_FUNC) sig_nickchange_over);
|
||||
signal_add("whois not found", (SIGNAL_FUNC) sig_whois_not_found);
|
||||
signal_add("whois event", (SIGNAL_FUNC) event_whois);
|
||||
signal_add("whowas event", (SIGNAL_FUNC) event_whowas);
|
||||
signal_add("server connected", (SIGNAL_FUNC) sig_connected);
|
||||
|
||||
command_set_options("connect", "+ircnet");
|
||||
command_set_options("topic", "delete");
|
||||
@ -1119,11 +1038,9 @@ void irc_commands_deinit(void)
|
||||
|
||||
signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
|
||||
signal_remove("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
|
||||
signal_remove("nickchange over", (SIGNAL_FUNC) sig_nickchange_over);
|
||||
signal_remove("whois not found", (SIGNAL_FUNC) sig_whois_not_found);
|
||||
signal_remove("whois event", (SIGNAL_FUNC) event_whois);
|
||||
signal_remove("whowas event", (SIGNAL_FUNC) event_whowas);
|
||||
signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
|
||||
|
||||
g_string_free(tmpstr, TRUE);
|
||||
}
|
||||
|
@ -33,8 +33,9 @@
|
||||
#include "irc-servers-setup.h"
|
||||
#include "irc-servers.h"
|
||||
#include "channel-rejoin.h"
|
||||
#include "server-idle.h"
|
||||
#include "servers-idle.h"
|
||||
#include "servers-reconnect.h"
|
||||
#include "servers-redirect.h"
|
||||
#include "modes.h"
|
||||
|
||||
#include "settings.h"
|
||||
@ -304,6 +305,7 @@ static void server_cmd_timeout(IRC_SERVER_REC *server, GTimeVal *now)
|
||||
/* add to rawlog without CR+LF */
|
||||
cmd[len-2] = '\0';
|
||||
rawlog_output(server->rawlog, cmd);
|
||||
server_redirect_command(server, cmd);
|
||||
|
||||
/* remove from queue */
|
||||
g_free(cmd);
|
||||
@ -506,6 +508,7 @@ void irc_servers_init(void)
|
||||
|
||||
irc_servers_setup_init();
|
||||
irc_servers_reconnect_init();
|
||||
servers_redirect_init();
|
||||
servers_idle_init();
|
||||
}
|
||||
|
||||
@ -527,5 +530,6 @@ void irc_servers_deinit(void)
|
||||
|
||||
irc_servers_setup_deinit();
|
||||
irc_servers_reconnect_deinit();
|
||||
servers_redirect_deinit();
|
||||
servers_idle_deinit();
|
||||
}
|
||||
|
@ -37,12 +37,16 @@ struct _IRC_SERVER_CONNECT_REC {
|
||||
struct _IRC_SERVER_REC {
|
||||
#include "server-rec.h"
|
||||
|
||||
/* For deciding if event should be redirected */
|
||||
GSList *redirects;
|
||||
void *redirect_next;
|
||||
void *redirect_continue;
|
||||
|
||||
char *real_address; /* address the irc server gives */
|
||||
char *usermode; /* The whole mode string .. */
|
||||
char *userhost; /* /USERHOST <nick> - set when joined to first channel */
|
||||
int channels_formed; /* channels formed in irc network */
|
||||
|
||||
unsigned int nick_changing:1; /* We've sent nick change command to server */
|
||||
unsigned int whois_coming:1; /* Mostly just to display away message right.. */
|
||||
unsigned int whois_found:1; /* Did WHOIS return any entries? */
|
||||
unsigned int whowas_found:1; /* Did WHOWAS return any entries? */
|
||||
|
@ -62,8 +62,10 @@ void irc_send_cmd_full(IRC_SERVER_REC *server, const char *cmd,
|
||||
cmd = str;
|
||||
}
|
||||
|
||||
if (send_now)
|
||||
if (send_now) {
|
||||
rawlog_output(server->rawlog, cmd);
|
||||
server_redirect_command(server, cmd);
|
||||
}
|
||||
|
||||
if (!raw) {
|
||||
/* Add CR+LF to command */
|
||||
@ -253,39 +255,34 @@ char *event_get_params(const char *data, int count, ...)
|
||||
return duprec;
|
||||
}
|
||||
|
||||
static void irc_server_event(IRC_SERVER_REC *server, const char *line, const char *nick, const char *address)
|
||||
static void irc_server_event(IRC_SERVER_REC *server, const char *line,
|
||||
const char *nick, const char *address)
|
||||
{
|
||||
char *event, *args, *callcmd;
|
||||
GSList *list;
|
||||
const char *signal;
|
||||
char *event, *args;
|
||||
|
||||
g_return_if_fail(line != NULL);
|
||||
|
||||
/* get command.. */
|
||||
/* split event / args */
|
||||
event = g_strconcat("event ", line, NULL);
|
||||
args = strchr(event+6, ' ');
|
||||
if (args != NULL) *args++ = '\0'; else args = "";
|
||||
while (*args == ' ') args++;
|
||||
g_strdown(event);
|
||||
|
||||
list = server_redirect_getqueue((SERVER_REC *) server, event, args);
|
||||
if (list == NULL)
|
||||
callcmd = g_strdup(event);
|
||||
else {
|
||||
/* event is redirected somewhere else.. */
|
||||
REDIRECT_REC *rec;
|
||||
|
||||
rec = list->data;
|
||||
callcmd = g_strdup(rec->name);
|
||||
rawlog_redirect(server->rawlog, callcmd);
|
||||
server_redirect_remove_next((SERVER_REC *) server, event, list);
|
||||
}
|
||||
/* check if event needs to be redirected */
|
||||
signal = server_redirect_get_signal(server, event, args);
|
||||
if (signal == NULL)
|
||||
signal = event;
|
||||
else
|
||||
rawlog_redirect(server->rawlog, signal);
|
||||
|
||||
/* emit it */
|
||||
current_server_event = event+6;
|
||||
g_strdown(callcmd);
|
||||
if (!signal_emit(callcmd, 4, server, args, nick, address))
|
||||
if (!signal_emit(signal, 4, server, args, nick, address))
|
||||
signal_emit_id(signal_default_event, 4, server, line, nick, address);
|
||||
current_server_event = NULL;
|
||||
|
||||
g_free(callcmd);
|
||||
g_free(event);
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "settings.h"
|
||||
|
||||
#include "irc-servers.h"
|
||||
#include "servers-redirect.h"
|
||||
|
||||
typedef struct {
|
||||
IRC_SERVER_REC *server;
|
||||
@ -53,6 +54,20 @@ static void lag_free(LAG_REC *rec)
|
||||
g_free(rec);
|
||||
}
|
||||
|
||||
static void lag_send(LAG_REC *lag)
|
||||
{
|
||||
IRC_SERVER_REC *server;
|
||||
|
||||
g_get_current_time(&lag->time);
|
||||
|
||||
server = lag->server;
|
||||
server->lag_sent = server->lag_last_check = time(NULL);
|
||||
server_redirect_event(server, "ping", NULL, FALSE,
|
||||
"lag ping error",
|
||||
"event pong", "lag pong", NULL);
|
||||
irc_send_cmdv(server, "PING %s", server->real_address);
|
||||
}
|
||||
|
||||
static void lag_get(IRC_SERVER_REC *server)
|
||||
{
|
||||
LAG_REC *lag;
|
||||
@ -61,57 +76,42 @@ static void lag_get(IRC_SERVER_REC *server)
|
||||
|
||||
/* nick changes may fail this check, so we should never do this
|
||||
while there's nick change request waiting for reply in server.. */
|
||||
if (server->nick_changing)
|
||||
return;
|
||||
|
||||
lag = g_new0(LAG_REC, 1);
|
||||
lags = g_slist_append(lags, lag);
|
||||
lag->server = server;
|
||||
|
||||
g_get_current_time(&lag->time);
|
||||
|
||||
if (server->lag_sent == 0)
|
||||
server->lag_sent = time(NULL);
|
||||
server->lag_last_check = time(NULL);
|
||||
|
||||
irc_send_cmdv(server, "NOTICE %s :\001IRSSILAG %ld %ld\001",
|
||||
server->nick, lag->time.tv_sec, lag->time.tv_usec);
|
||||
lag_send(lag);
|
||||
}
|
||||
|
||||
/* we use "ctcp reply" signal here, because "ctcp reply irssilag" can be
|
||||
ignored with /IGNORE * CTCPS */
|
||||
static void sig_irssilag(IRC_SERVER_REC *server, const char *data,
|
||||
const char *nick, const char *addr,
|
||||
const char *target)
|
||||
/* we didn't receive PONG for some reason .. try again */
|
||||
static void lag_ping_error(IRC_SERVER_REC *server)
|
||||
{
|
||||
GTimeVal now, sent;
|
||||
LAG_REC *lag;
|
||||
|
||||
lag = lag_find(server);
|
||||
if (lag != NULL)
|
||||
lag_send(lag);
|
||||
}
|
||||
|
||||
static void lag_event_pong(IRC_SERVER_REC *server, const char *data,
|
||||
const char *nick, const char *addr)
|
||||
{
|
||||
GTimeVal now;
|
||||
LAG_REC *lag;
|
||||
|
||||
g_return_if_fail(data != NULL);
|
||||
|
||||
if (strncmp(data, "IRSSILAG ", 9) != 0)
|
||||
return;
|
||||
data += 9;
|
||||
|
||||
lag = lag_find(server);
|
||||
if (lag == NULL) {
|
||||
/* not expecting lag reply.. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_strcasecmp(nick, server->nick) != 0) {
|
||||
/* we didn't sent this - not a lag notice */
|
||||
return;
|
||||
}
|
||||
|
||||
/* OK, it is a lag notice. */
|
||||
server->lag_sent = 0;
|
||||
|
||||
if (sscanf(data, "%ld %ld", &sent.tv_sec, &sent.tv_usec) == 2) {
|
||||
g_get_current_time(&now);
|
||||
server->lag = (int) get_timeval_diff(&now, &sent);
|
||||
server->lag = (int) get_timeval_diff(&now, &lag->time);
|
||||
signal_emit("server lag", 1, server);
|
||||
}
|
||||
|
||||
lag_free(lag);
|
||||
}
|
||||
@ -154,11 +154,6 @@ static int sig_check_lag(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void sig_empty(void)
|
||||
{
|
||||
/* don't print the "CTCP IRSSILAG reply .." text */
|
||||
}
|
||||
|
||||
void lag_init(void)
|
||||
{
|
||||
settings_add_int("misc", "lag_check_time", 30);
|
||||
@ -166,8 +161,8 @@ void lag_init(void)
|
||||
|
||||
lags = NULL;
|
||||
timeout_tag = g_timeout_add(1000, (GSourceFunc) sig_check_lag, NULL);
|
||||
signal_add("ctcp reply", (SIGNAL_FUNC) sig_irssilag);
|
||||
signal_add("ctcp reply irssilag", (SIGNAL_FUNC) sig_empty);
|
||||
signal_add_first("lag pong", (SIGNAL_FUNC) lag_event_pong);
|
||||
signal_add("lag ping error", (SIGNAL_FUNC) lag_ping_error);
|
||||
}
|
||||
|
||||
void lag_deinit(void)
|
||||
@ -175,6 +170,6 @@ void lag_deinit(void)
|
||||
g_source_remove(timeout_tag);
|
||||
while (lags != NULL)
|
||||
lag_free(lags->data);
|
||||
signal_remove("ctcp reply", (SIGNAL_FUNC) sig_irssilag);
|
||||
signal_remove("ctcp reply irssilag", (SIGNAL_FUNC) sig_empty);
|
||||
signal_remove("lag pong", (SIGNAL_FUNC) lag_event_pong);
|
||||
signal_remove("lag ping error", (SIGNAL_FUNC) lag_ping_error);
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
#ifndef __SERVER_IDLE_H
|
||||
#define __SERVER_IDLE_H
|
||||
|
||||
/* Add new idle command to queue */
|
||||
int server_idle_add(IRC_SERVER_REC *server, const char *cmd, const char *arg, int last, ...);
|
||||
|
||||
/* Add new idle command to first of queue */
|
||||
int server_idle_add_first(IRC_SERVER_REC *server, const char *cmd, const char *arg, int last, ...);
|
||||
|
||||
/* Add new idle command to specified position of queue */
|
||||
int server_idle_insert(IRC_SERVER_REC *server, const char *cmd, const char *arg, int tag, int last, ...);
|
||||
|
||||
/* Check if record is still in queue */
|
||||
int server_idle_find(IRC_SERVER_REC *server, int tag);
|
||||
|
||||
/* Remove record from idle queue */
|
||||
int server_idle_remove(IRC_SERVER_REC *server, int tag);
|
||||
|
||||
void servers_idle_init(void);
|
||||
void servers_idle_deinit(void);
|
||||
|
||||
#endif
|
@ -22,49 +22,54 @@
|
||||
#include "signals.h"
|
||||
|
||||
#include "irc-servers.h"
|
||||
#include "server-idle.h"
|
||||
#include "servers-idle.h"
|
||||
#include "servers-redirect.h"
|
||||
|
||||
typedef struct {
|
||||
char *event;
|
||||
char *signal;
|
||||
int argpos;
|
||||
} REDIRECT_IDLE_REC;
|
||||
|
||||
typedef struct {
|
||||
char *cmd;
|
||||
char *arg;
|
||||
int tag;
|
||||
|
||||
int last;
|
||||
char *redirect_cmd;
|
||||
int remote;
|
||||
char *failure_signal;
|
||||
GSList *redirects;
|
||||
} SERVER_IDLE_REC;
|
||||
|
||||
static int idle_tag, idlepos;
|
||||
|
||||
/* Add new idle command to queue */
|
||||
static SERVER_IDLE_REC *server_idle_create(const char *cmd, const char *arg, int last, va_list args)
|
||||
static SERVER_IDLE_REC *
|
||||
server_idle_create(const char *cmd, const char *redirect_cmd, const char *arg,
|
||||
int remote, const char *failure_signal, va_list va)
|
||||
{
|
||||
REDIRECT_IDLE_REC *rrec;
|
||||
SERVER_IDLE_REC *rec;
|
||||
char *event;
|
||||
const char *event, *signal;
|
||||
|
||||
g_return_val_if_fail(cmd != NULL, FALSE);
|
||||
|
||||
rec = g_new0(SERVER_IDLE_REC, 1);
|
||||
|
||||
rec->tag = ++idlepos;
|
||||
rec->arg = arg == NULL ? NULL : g_strdup(arg);
|
||||
rec->cmd = g_strdup(cmd);
|
||||
rec->last = last;
|
||||
rec->arg = g_strdup(arg);
|
||||
rec->tag = ++idlepos;
|
||||
|
||||
while ((event = va_arg(args, char *)) != NULL) {
|
||||
rrec = g_new(REDIRECT_IDLE_REC, 1);
|
||||
rec->redirects = g_slist_append(rec->redirects, rrec);
|
||||
rec->redirect_cmd = g_strdup(redirect_cmd);
|
||||
rec->remote = remote;
|
||||
rec->failure_signal = g_strdup(failure_signal);
|
||||
|
||||
rrec->event = g_strdup(event);
|
||||
rrec->signal = g_strdup(va_arg(args, char *));
|
||||
rrec->argpos = va_arg(args, int);
|
||||
while ((event = va_arg(va, const char *)) != NULL) {
|
||||
signal = va_arg(va, const char *);
|
||||
if (signal == NULL) {
|
||||
g_warning("server_idle_create(%s): "
|
||||
"signal not specified for event",
|
||||
redirect_cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
rec->redirects =
|
||||
g_slist_append(rec->redirects, g_strdup(event));
|
||||
rec->redirects =
|
||||
g_slist_append(rec->redirects, g_strdup(signal));
|
||||
}
|
||||
|
||||
return rec;
|
||||
@ -87,78 +92,82 @@ static SERVER_IDLE_REC *server_idle_find_rec(IRC_SERVER_REC *server, int tag)
|
||||
}
|
||||
|
||||
/* Add new idle command to queue */
|
||||
int server_idle_add(IRC_SERVER_REC *server, const char *cmd, const char *arg, int last, ...)
|
||||
int server_idle_add_redir(IRC_SERVER_REC *server, const char *cmd,
|
||||
const char *redirect_cmd, const char *arg,
|
||||
int remote, const char *failure_signal, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_list va;
|
||||
SERVER_IDLE_REC *rec;
|
||||
|
||||
g_return_val_if_fail(server != NULL, -1);
|
||||
|
||||
va_start(args, last);
|
||||
rec = server_idle_create(cmd, arg, last, args);
|
||||
va_start(va, failure_signal);
|
||||
rec = server_idle_create(cmd, redirect_cmd, arg, remote,
|
||||
failure_signal, va);
|
||||
server->idles = g_slist_append(server->idles, rec);
|
||||
va_end(args);
|
||||
va_end(va);
|
||||
|
||||
return rec->tag;
|
||||
}
|
||||
|
||||
/* Add new idle command to first of queue */
|
||||
int server_idle_add_first(IRC_SERVER_REC *server, const char *cmd, const char *arg, int last, ...)
|
||||
int server_idle_add_first_redir(IRC_SERVER_REC *server, const char *cmd,
|
||||
const char *redirect_cmd, const char *arg,
|
||||
int remote, const char *failure_signal, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_list va;
|
||||
SERVER_IDLE_REC *rec;
|
||||
|
||||
g_return_val_if_fail(server != NULL, -1);
|
||||
|
||||
va_start(args, last);
|
||||
rec = server_idle_create(cmd, arg, last, args);
|
||||
va_start(va, failure_signal);
|
||||
rec = server_idle_create(cmd, redirect_cmd, arg, remote,
|
||||
failure_signal, va);
|
||||
server->idles = g_slist_prepend(server->idles, rec);
|
||||
va_end(args);
|
||||
va_end(va);
|
||||
|
||||
return rec->tag;
|
||||
}
|
||||
|
||||
/* Add new idle command to specified position of queue */
|
||||
int server_idle_insert(IRC_SERVER_REC *server, const char *cmd, const char *arg, int tag, int last, ...)
|
||||
int server_idle_insert_redir(IRC_SERVER_REC *server, const char *cmd, int tag,
|
||||
const char *redirect_cmd, const char *arg,
|
||||
int remote, const char *failure_signal, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_list va;
|
||||
SERVER_IDLE_REC *rec;
|
||||
int pos;
|
||||
|
||||
g_return_val_if_fail(server != NULL, -1);
|
||||
|
||||
va_start(args, last);
|
||||
va_start(va, failure_signal);
|
||||
|
||||
/* find the position of tag in idle list */
|
||||
rec = server_idle_find_rec(server, tag);
|
||||
pos = g_slist_index(server->idles, rec);
|
||||
|
||||
rec = server_idle_create(cmd, arg, last, args);
|
||||
rec = server_idle_create(cmd, redirect_cmd, arg, remote,
|
||||
failure_signal, va);
|
||||
server->idles = pos < 0 ?
|
||||
g_slist_append(server->idles, rec) :
|
||||
g_slist_insert(server->idles, rec, pos);
|
||||
va_end(args);
|
||||
va_end(va);
|
||||
|
||||
return rec->tag;
|
||||
}
|
||||
|
||||
static void server_idle_destroy(IRC_SERVER_REC *server, SERVER_IDLE_REC *rec)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
g_return_if_fail(server != NULL);
|
||||
|
||||
server->idles = g_slist_remove(server->idles, rec);
|
||||
|
||||
for (tmp = rec->redirects; tmp != NULL; tmp = tmp->next) {
|
||||
REDIRECT_IDLE_REC *rec = tmp->data;
|
||||
|
||||
g_free(rec->event);
|
||||
g_free(rec->signal);
|
||||
g_free(rec);
|
||||
}
|
||||
g_slist_foreach(rec->redirects, (GFunc) g_free, NULL);
|
||||
g_slist_free(rec->redirects);
|
||||
|
||||
g_free_not_null(rec->arg);
|
||||
g_free_not_null(rec->redirect_cmd);
|
||||
g_free_not_null(rec->failure_signal);
|
||||
g_free(rec->cmd);
|
||||
g_free(rec);
|
||||
}
|
||||
@ -188,26 +197,20 @@ int server_idle_remove(IRC_SERVER_REC *server, int tag)
|
||||
static void server_idle_next(IRC_SERVER_REC *server)
|
||||
{
|
||||
SERVER_IDLE_REC *rec;
|
||||
GSList *tmp;
|
||||
int group;
|
||||
|
||||
g_return_if_fail(server != NULL);
|
||||
|
||||
if (server->idles == NULL) return;
|
||||
if (server->idles == NULL)
|
||||
return;
|
||||
rec = server->idles->data;
|
||||
|
||||
/* Send command */
|
||||
irc_send_cmd(server, rec->cmd);
|
||||
|
||||
/* Add server redirections */
|
||||
group = 0;
|
||||
for (tmp = rec->redirects; tmp != NULL; tmp = tmp->next) {
|
||||
REDIRECT_IDLE_REC *rrec = tmp->data;
|
||||
|
||||
group = server_redirect_single_event((SERVER_REC *) server, rec->arg, rec->last > 0,
|
||||
group, rrec->event, rrec->signal, rrec->argpos);
|
||||
if (rec->last > 0) rec->last--;
|
||||
if (rec->redirect_cmd != NULL) {
|
||||
server_redirect_event_list(server, rec->redirect_cmd, rec->arg,
|
||||
rec->remote, rec->failure_signal,
|
||||
rec->redirects);
|
||||
}
|
||||
irc_send_cmd(server, rec->cmd);
|
||||
|
||||
server_idle_destroy(server, rec);
|
||||
}
|
34
src/irc/core/servers-idle.h
Normal file
34
src/irc/core/servers-idle.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef __SERVERS_IDLE_H
|
||||
#define __SERVERS_IDLE_H
|
||||
|
||||
/* Add new idle command to queue */
|
||||
int server_idle_add_redir(IRC_SERVER_REC *server, const char *cmd,
|
||||
const char *redirect_cmd, const char *arg,
|
||||
int remote, const char *failure_signal, ...);
|
||||
#define server_idle_add(server, cmd) \
|
||||
server_idle_add_redir(server, cmd, NULL, NULL, 0, NULL, NULL)
|
||||
|
||||
/* Add new idle command to first of queue */
|
||||
int server_idle_add_first_redir(IRC_SERVER_REC *server, const char *cmd,
|
||||
const char *redirect_cmd, const char *arg,
|
||||
int remote, const char *failure_signal, ...);
|
||||
#define server_idle_add_first(server, cmd) \
|
||||
server_idle_add_first_redir(server, cmd, NULL, NULL, 0, NULL, NULL)
|
||||
|
||||
/* Add new idle command to specified position of queue */
|
||||
int server_idle_insert_redir(IRC_SERVER_REC *server, const char *cmd, int tag,
|
||||
const char *redirect_cmd, const char *arg,
|
||||
int remote, const char *failure_signal, ...);
|
||||
#define server_idle_insert(server, cmd, tag) \
|
||||
server_idle_insert_redir(server, cmd, tag, NULL, NULL, 0, NULL, NULL)
|
||||
|
||||
/* Check if record is still in queue */
|
||||
int server_idle_find(IRC_SERVER_REC *server, int tag);
|
||||
|
||||
/* Remove record from idle queue */
|
||||
int server_idle_remove(IRC_SERVER_REC *server, int tag);
|
||||
|
||||
void servers_idle_init(void);
|
||||
void servers_idle_deinit(void);
|
||||
|
||||
#endif
|
569
src/irc/core/servers-redirect.c
Normal file
569
src/irc/core/servers-redirect.c
Normal file
@ -0,0 +1,569 @@
|
||||
/*
|
||||
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 "irc-servers.h"
|
||||
#include "servers-redirect.h"
|
||||
|
||||
typedef struct {
|
||||
int refcount;
|
||||
|
||||
int remote;
|
||||
int timeout;
|
||||
GSList *start, *stop; /* char *event, int argpos, ... */
|
||||
} REDIRECT_CMD_REC;
|
||||
|
||||
typedef struct {
|
||||
REDIRECT_CMD_REC *cmd;
|
||||
time_t created;
|
||||
int destroyed;
|
||||
|
||||
char *arg;
|
||||
int remote;
|
||||
char *failure_signal, *default_signal;
|
||||
GSList *signals; /* event, signal, ... */
|
||||
} REDIRECT_REC;
|
||||
|
||||
static GHashTable *command_redirects; /* "command xxx" : REDIRECT_CMD_REC* */
|
||||
|
||||
/* Find redirection command record for specified command line. */
|
||||
static REDIRECT_CMD_REC *redirect_cmd_find(const char *command)
|
||||
{
|
||||
REDIRECT_CMD_REC *rec;
|
||||
const char *p;
|
||||
char *cmd;
|
||||
|
||||
p = strchr(command, ' ');
|
||||
if (p == NULL)
|
||||
rec = g_hash_table_lookup(command_redirects, command);
|
||||
else {
|
||||
cmd = g_strndup(command, (int) (p-command));
|
||||
rec = g_hash_table_lookup(command_redirects, cmd);
|
||||
g_free(cmd);
|
||||
}
|
||||
return rec;
|
||||
}
|
||||
|
||||
static void redirect_cmd_destroy(REDIRECT_CMD_REC *rec)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
for (tmp = rec->start; tmp != NULL; tmp = tmp->next->next)
|
||||
g_free(tmp->data);
|
||||
for (tmp = rec->stop; tmp != NULL; tmp = tmp->next->next)
|
||||
g_free(tmp->data);
|
||||
g_slist_free(rec->start);
|
||||
g_slist_free(rec->stop);
|
||||
g_free(rec);
|
||||
}
|
||||
|
||||
static void redirect_cmd_ref(REDIRECT_CMD_REC *rec)
|
||||
{
|
||||
rec->refcount++;
|
||||
}
|
||||
|
||||
static void redirect_cmd_unref(REDIRECT_CMD_REC *rec)
|
||||
{
|
||||
if (--rec->refcount <= 0)
|
||||
redirect_cmd_destroy(rec);
|
||||
}
|
||||
|
||||
static void redirect_destroy(REDIRECT_REC *rec)
|
||||
{
|
||||
redirect_cmd_unref(rec->cmd);
|
||||
|
||||
g_free_not_null(rec->arg);
|
||||
g_free_not_null(rec->failure_signal);
|
||||
g_free_not_null(rec->default_signal);
|
||||
g_slist_foreach(rec->signals, (GFunc) g_free, NULL);
|
||||
g_slist_free(rec->signals);
|
||||
g_free(rec);
|
||||
}
|
||||
|
||||
void server_redirect_register(const char *command,
|
||||
int remote, int timeout, ...)
|
||||
{
|
||||
va_list va;
|
||||
GSList *start, *stop, **list;
|
||||
const char *event;
|
||||
int argpos;
|
||||
|
||||
va_start(va, timeout);
|
||||
start = stop = NULL; list = &start;
|
||||
for (;;) {
|
||||
event = va_arg(va, const char *);
|
||||
if (event == NULL) {
|
||||
if (list == &stop)
|
||||
break;
|
||||
list = &stop;
|
||||
continue;
|
||||
}
|
||||
|
||||
argpos = va_arg(va, int);
|
||||
*list = g_slist_append(*list, g_strdup(event));
|
||||
*list = g_slist_append(*list, GINT_TO_POINTER(argpos));
|
||||
}
|
||||
|
||||
va_end(va);
|
||||
|
||||
server_redirect_register_list(command, remote, timeout, start, stop);
|
||||
}
|
||||
|
||||
void server_redirect_register_list(const char *command,
|
||||
int remote, int timeout,
|
||||
GSList *start, GSList *stop)
|
||||
{
|
||||
REDIRECT_CMD_REC *rec;
|
||||
gpointer key, value;
|
||||
|
||||
g_return_if_fail(command != NULL);
|
||||
g_return_if_fail(stop != NULL);
|
||||
|
||||
if (g_hash_table_lookup_extended(command_redirects, command,
|
||||
&key, &value)) {
|
||||
/* Already registered - might have changed so destroy
|
||||
the old one */
|
||||
g_hash_table_remove(command_redirects, command);
|
||||
redirect_cmd_unref(value);
|
||||
g_free(key);
|
||||
}
|
||||
|
||||
rec = g_new0(REDIRECT_CMD_REC, 1);
|
||||
redirect_cmd_ref(rec);
|
||||
rec->remote = remote;
|
||||
rec->timeout = timeout;
|
||||
rec->start = start;
|
||||
rec->stop = stop;
|
||||
g_hash_table_insert(command_redirects, g_strdup(command), rec);
|
||||
}
|
||||
|
||||
void server_redirect_event(IRC_SERVER_REC *server, const char *command,
|
||||
const char *arg, int remote,
|
||||
const char *failure_signal, ...)
|
||||
{
|
||||
GSList *signals;
|
||||
const char *event, *signal;
|
||||
va_list va;
|
||||
|
||||
va_start(va, failure_signal);
|
||||
signals = NULL;
|
||||
while ((event = va_arg(va, const char *)) != NULL) {
|
||||
signal = va_arg(va, const char *);
|
||||
if (signal == NULL) {
|
||||
g_warning("server_redirect_event(%s): "
|
||||
"signal not specified for event", command);
|
||||
break;
|
||||
}
|
||||
|
||||
signals = g_slist_append(signals, g_strdup(event));
|
||||
signals = g_slist_append(signals, g_strdup(signal));
|
||||
}
|
||||
|
||||
va_end(va);
|
||||
|
||||
server_redirect_event_list(server, command, arg, remote,
|
||||
failure_signal, signals);
|
||||
}
|
||||
|
||||
void server_redirect_event_list(IRC_SERVER_REC *server, const char *command,
|
||||
const char *arg, int remote,
|
||||
const char *failure_signal, GSList *signals)
|
||||
{
|
||||
REDIRECT_CMD_REC *cmdrec;
|
||||
REDIRECT_REC *rec;
|
||||
GSList *default_signal;
|
||||
char *default_signal_key;
|
||||
|
||||
g_return_if_fail(IS_IRC_SERVER(server));
|
||||
g_return_if_fail(command != NULL);
|
||||
g_return_if_fail((g_slist_length(signals) & 1) == 0);
|
||||
|
||||
if (server->redirect_next != NULL) {
|
||||
redirect_destroy(server->redirect_next);
|
||||
server->redirect_next = NULL;
|
||||
}
|
||||
|
||||
cmdrec = g_hash_table_lookup(command_redirects, command);
|
||||
if (cmdrec == NULL) {
|
||||
g_warning("Unknown redirection command: %s", command);
|
||||
return;
|
||||
}
|
||||
|
||||
redirect_cmd_ref(cmdrec);
|
||||
|
||||
rec = g_new0(REDIRECT_REC, 1);
|
||||
rec->created = time(NULL);
|
||||
rec->cmd = cmdrec;
|
||||
rec->arg = g_strdup(arg);
|
||||
rec->remote = remote != -1 ? remote : cmdrec->remote;
|
||||
rec->failure_signal = g_strdup(failure_signal);
|
||||
|
||||
default_signal = gslist_find_string(signals, "");
|
||||
if (default_signal != NULL) {
|
||||
default_signal_key = default_signal->data;
|
||||
rec->default_signal = default_signal->next->data;
|
||||
|
||||
signals = g_slist_remove(signals, default_signal_key);
|
||||
signals = g_slist_remove(signals, rec->default_signal);
|
||||
g_free(default_signal_key);
|
||||
}
|
||||
rec->signals = signals;
|
||||
|
||||
server->redirect_next = rec;
|
||||
}
|
||||
|
||||
void server_redirect_command(IRC_SERVER_REC *server, const char *command)
|
||||
{
|
||||
REDIRECT_CMD_REC *cmdrec;
|
||||
REDIRECT_REC *rec;
|
||||
|
||||
g_return_if_fail(IS_IRC_SERVER(server));
|
||||
g_return_if_fail(command != NULL);
|
||||
|
||||
if (server->redirect_next != NULL) {
|
||||
rec = server->redirect_next;
|
||||
server->redirect_next = NULL;
|
||||
} else {
|
||||
cmdrec = redirect_cmd_find(command);
|
||||
if (cmdrec == NULL)
|
||||
return;
|
||||
|
||||
/* no redirection wanted, but still register the command
|
||||
so future redirections wont get messed up. */
|
||||
redirect_cmd_ref(cmdrec);
|
||||
|
||||
rec = g_new0(REDIRECT_REC, 1);
|
||||
rec->created = time(NULL);
|
||||
rec->cmd = cmdrec;
|
||||
rec->remote = cmdrec->remote;
|
||||
}
|
||||
|
||||
server->redirects = g_slist_append(server->redirects, rec);
|
||||
}
|
||||
|
||||
static int redirect_args_match(const char *event_args,
|
||||
const char *arg, int pos)
|
||||
{
|
||||
const char *start;
|
||||
|
||||
if (pos == -1)
|
||||
return TRUE;
|
||||
|
||||
/* skip to the start of the wanted argument */
|
||||
while (pos > 0 && *event_args != '\0') {
|
||||
while (*event_args != ' ' && *event_args != '\0') event_args++;
|
||||
while (*event_args == ' ') event_args++;
|
||||
pos--;
|
||||
}
|
||||
|
||||
/* now compare the arguments */
|
||||
start = event_args;
|
||||
while (*arg != '\0') {
|
||||
while (*arg != '\0' && *arg != ' ' && *event_args != '\0') {
|
||||
if (*arg != *event_args)
|
||||
break;
|
||||
arg++; event_args++;
|
||||
}
|
||||
|
||||
if ((*arg == '\0' || *arg == ' ') &&
|
||||
(*event_args == '\0' || *event_args == ' '))
|
||||
return TRUE;
|
||||
|
||||
/* compare the next argument */
|
||||
while (*arg != ' ' && *arg != '\0') arg++;
|
||||
while (*arg == ' ') arg++;
|
||||
|
||||
event_args = start;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GSList *redirect_cmd_list_find(GSList *list, const char *event)
|
||||
{
|
||||
while (list != NULL) {
|
||||
const char *str = list->data;
|
||||
|
||||
if (strcmp(str, event) == 0)
|
||||
break;
|
||||
list = list->next->next;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static const char *redirect_match(REDIRECT_REC *redirect, const char *event,
|
||||
const char *args, int *match_stop)
|
||||
{
|
||||
GSList *tmp, *cmdpos;
|
||||
int stop_signal;
|
||||
|
||||
for (tmp = redirect->signals; tmp != NULL; tmp = tmp->next->next) {
|
||||
if (strcmp(tmp->data, event) != 0)
|
||||
continue;
|
||||
|
||||
/* find the argument position */
|
||||
cmdpos = redirect_cmd_list_find(redirect->cmd->start, event);
|
||||
if (cmdpos != NULL)
|
||||
stop_signal = FALSE;
|
||||
else {
|
||||
cmdpos = redirect_cmd_list_find(redirect->cmd->stop,
|
||||
event);
|
||||
stop_signal = cmdpos != NULL;
|
||||
}
|
||||
|
||||
/* check that arguments match */
|
||||
if (args != NULL && redirect->arg != NULL && cmdpos != NULL &&
|
||||
!redirect_args_match(args, redirect->arg,
|
||||
GPOINTER_TO_INT(cmdpos->next->data)))
|
||||
continue;
|
||||
|
||||
*match_stop = stop_signal;
|
||||
return tmp->next->data;
|
||||
}
|
||||
|
||||
*match_stop = redirect_cmd_list_find(redirect->cmd->stop,
|
||||
event) != NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static REDIRECT_REC *redirect_find(IRC_SERVER_REC *server, const char *event,
|
||||
const char *args, const char **signal,
|
||||
int *match_stop)
|
||||
{
|
||||
REDIRECT_REC *redirect;
|
||||
GSList *tmp, *next;
|
||||
time_t now;
|
||||
|
||||
/* find the redirection */
|
||||
*signal = NULL; redirect = NULL;
|
||||
for (tmp = server->redirects; tmp != NULL; tmp = tmp->next) {
|
||||
REDIRECT_REC *rec = tmp->data;
|
||||
|
||||
*signal = redirect_match(rec, event, args, match_stop);
|
||||
if (*signal != NULL) {
|
||||
redirect = rec;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* remove the destroyed, non-remote and timeouted remote
|
||||
redirections that should have happened before this redirection */
|
||||
now = time(NULL);
|
||||
for (tmp = server->redirects; tmp != NULL; tmp = next) {
|
||||
REDIRECT_REC *rec = tmp->data;
|
||||
|
||||
if (rec == redirect)
|
||||
break;
|
||||
|
||||
next = tmp->next;
|
||||
if (rec->destroyed ||
|
||||
(rec->remote && (now-rec->created) > rec->cmd->timeout) ||
|
||||
(redirect != NULL && !rec->remote)) {
|
||||
server->redirects =
|
||||
g_slist_remove(server->redirects, rec);
|
||||
if (!rec->destroyed && rec->failure_signal != NULL) {
|
||||
/* emit the failure signal */
|
||||
signal_emit(rec->failure_signal, 1, server);
|
||||
}
|
||||
redirect_destroy(rec);
|
||||
}
|
||||
}
|
||||
|
||||
return redirect;
|
||||
}
|
||||
|
||||
const char *server_redirect_get_signal(IRC_SERVER_REC *server,
|
||||
const char *event,
|
||||
const char *args)
|
||||
{
|
||||
REDIRECT_REC *redirect;
|
||||
const char *signal;
|
||||
int match_stop;
|
||||
|
||||
if (server->redirects == NULL)
|
||||
return NULL;
|
||||
|
||||
if (server->redirect_continue == NULL) {
|
||||
/* find the redirection */
|
||||
redirect = redirect_find(server, event, args,
|
||||
&signal, &match_stop);
|
||||
} else {
|
||||
/* redirection is already started, now we'll just need to
|
||||
keep redirecting until stop-event is found. */
|
||||
redirect = server->redirect_continue;
|
||||
signal = redirect_match(redirect, event, NULL, &match_stop);
|
||||
if (signal == NULL) {
|
||||
/* unknown event - redirect to the default signal.
|
||||
FIXME: if stop event isn't properly got, this
|
||||
could break everything. Add some checks that if
|
||||
we get eg. 10 different unknown events after this,
|
||||
or if one of them matches to another redirection,
|
||||
abort this. */
|
||||
signal = redirect->default_signal;
|
||||
}
|
||||
}
|
||||
|
||||
if (!match_stop || redirect == NULL)
|
||||
server->redirect_continue = redirect;
|
||||
else {
|
||||
/* stop event - remove this redirection next time this
|
||||
function is called (can't destroy now or our return
|
||||
value would be corrupted) */
|
||||
redirect->destroyed = TRUE;
|
||||
server->redirect_continue = NULL;
|
||||
}
|
||||
|
||||
return signal;
|
||||
}
|
||||
|
||||
static void sig_disconnected(IRC_SERVER_REC *server)
|
||||
{
|
||||
if (!IS_IRC_SERVER(server))
|
||||
return;
|
||||
|
||||
g_slist_foreach(server->redirects, (GFunc) redirect_destroy, NULL);
|
||||
g_slist_free(server->redirects);
|
||||
|
||||
if (server->redirect_next != NULL)
|
||||
redirect_destroy(server->redirect_next);
|
||||
}
|
||||
|
||||
static void cmd_redirect_destroy(char *key, REDIRECT_CMD_REC *cmd)
|
||||
{
|
||||
g_free(key);
|
||||
redirect_cmd_unref(cmd);
|
||||
}
|
||||
|
||||
void servers_redirect_init(void)
|
||||
{
|
||||
command_redirects = g_hash_table_new((GHashFunc) g_str_hash, (GCompareFunc) g_str_equal);
|
||||
|
||||
/* WHOIS - register as remote command by default
|
||||
with a timeout of one minute */
|
||||
server_redirect_register("whois", TRUE, 60,
|
||||
"event 311", 1, /* Begins the WHOIS */
|
||||
"event 401", 1, /* No such nick */
|
||||
NULL,
|
||||
"event 318", 1, /* End of WHOIS */
|
||||
"event 402", 1, /* No such server */
|
||||
NULL);
|
||||
|
||||
/* WHOWAS */
|
||||
server_redirect_register("whowas", FALSE, 0,
|
||||
"event 314", 1, /* Begins the WHOWAS */
|
||||
"event 406", 1, /* There was no such nick */
|
||||
NULL,
|
||||
"event 369", 1, /* End of WHOWAS */
|
||||
NULL);
|
||||
|
||||
/* WHO */
|
||||
server_redirect_register("who", FALSE, 0,
|
||||
"event 352", 1, /* Begins the WHO */
|
||||
"event 401", 1, /* No such nick/channel */
|
||||
NULL,
|
||||
"event 315", 1, /* End of WHO */
|
||||
"event 403", 1, /* no such channel */
|
||||
NULL);
|
||||
|
||||
/* LIST */
|
||||
server_redirect_register("list", FALSE, 0,
|
||||
"event 321", 1, /* Begins the LIST */
|
||||
NULL,
|
||||
"event 323", 1, /* End of LIST */
|
||||
NULL);
|
||||
|
||||
/* ISON */
|
||||
server_redirect_register("ison", FALSE, 0,
|
||||
NULL,
|
||||
"event 303", 1, /* ISON */
|
||||
NULL);
|
||||
|
||||
/* USERHOST */
|
||||
server_redirect_register("userhost", FALSE, 0,
|
||||
"event 401", 1, /* no such nick */
|
||||
NULL,
|
||||
"event 302", 1, /* Userhost */
|
||||
"event 461", 1, /* Not enough parameters */
|
||||
NULL);
|
||||
|
||||
/* MODE #channel */
|
||||
server_redirect_register("mode channel", FALSE, 0,
|
||||
NULL,
|
||||
"event 324", 1, /* MODE-reply */
|
||||
"event 403", 1, /* no such channel */
|
||||
"event 442", 1, /* "you're not on that channel" */
|
||||
"event 479", 1, /* "Cannot join channel (illegal name)" IMHO this is not a logical reply from server. */
|
||||
NULL);
|
||||
|
||||
/* MODE #channel b */
|
||||
server_redirect_register("mode b", FALSE, 0,
|
||||
"event 367", 1,
|
||||
NULL,
|
||||
"event 368", 1, /* End of Channel ban List */
|
||||
"event 403", 1, /* no such channel */
|
||||
"event 442", 1, /* "you're not on that channel" */
|
||||
"event 479", 1, /* "Cannot join channel (illegal name)" IMHO this is not a logical reply from server. */
|
||||
NULL);
|
||||
|
||||
/* MODE #channel e */
|
||||
server_redirect_register("mode e", FALSE, 0,
|
||||
"event 348", 1,
|
||||
NULL,
|
||||
"event 349", 1, /* End of ban exceptions */
|
||||
"event 482", 1, /* not channel operator - OPN's ircd doesn't want non-ops to see ban exceptions */
|
||||
"event 403", 1, /* no such channel */
|
||||
"event 442", 1, /* "you're not on that channel" */
|
||||
"event 479", 1, /* "Cannot join channel (illegal name)" IMHO this is not a logical reply from server. */
|
||||
"event 472", -1, /* unknown mode (you should check e-mode's existance from 004 event instead of relying on this) */
|
||||
NULL);
|
||||
|
||||
/* MODE #channel I */
|
||||
server_redirect_register("mode e", FALSE, 0,
|
||||
"event 346", 1,
|
||||
NULL,
|
||||
"event 347", 1, /* End of invite list */
|
||||
"event 403", 1, /* no such channel */
|
||||
"event 442", 1, /* "you're not on that channel" */
|
||||
"event 479", 1, /* "Cannot join channel (illegal name)" IMHO this is not a logical reply from server. */
|
||||
"event 472", -1, /* unknown mode (you should check I-mode's existance from 004 event instead of relying on this) */
|
||||
NULL);
|
||||
|
||||
/* PING */
|
||||
server_redirect_register("ping", TRUE, 60,
|
||||
NULL,
|
||||
"event 402", -1, /* no such server */
|
||||
"event pong", -1, /* PONG */
|
||||
NULL);
|
||||
|
||||
signal_add("server disconnected", (SIGNAL_FUNC) sig_disconnected);
|
||||
}
|
||||
|
||||
void servers_redirect_deinit(void)
|
||||
{
|
||||
g_hash_table_foreach(command_redirects,
|
||||
(GHFunc) cmd_redirect_destroy, NULL);
|
||||
g_hash_table_destroy(command_redirects);
|
||||
|
||||
signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected);
|
||||
}
|
66
src/irc/core/servers-redirect.h
Normal file
66
src/irc/core/servers-redirect.h
Normal file
@ -0,0 +1,66 @@
|
||||
#ifndef __SERVERS_REDIRECT_H
|
||||
#define __SERVERS_REDIRECT_H
|
||||
|
||||
/* Register new redirection command.
|
||||
|
||||
remote - Specifies if the command is by default a remote command
|
||||
(eg. sent to another server). server_redirect_event() may override this.
|
||||
|
||||
timeout - If remote is TRUE, specifies how many seconds to wait for
|
||||
reply before aborting.
|
||||
|
||||
... - char *start, int argpos, char *start, int argpos, ..., NULL,
|
||||
char *stop, int argpos, char *stop, int argpos, ..., NULL
|
||||
List of events that start and stop this redirection.
|
||||
Start event list may be just NULL, but there must be at least one
|
||||
stop event. `argpos' specifies the word number in event string which
|
||||
is compared to wanted argument, -1 = don't compare, TRUE always. */
|
||||
void server_redirect_register(const char *command,
|
||||
int remote, int timeout, ...);
|
||||
/* start/stop lists shouldn't be free'd after, and their strings
|
||||
should be dynamically allocated */
|
||||
void server_redirect_register_list(const char *command,
|
||||
int remote, int timeout,
|
||||
GSList *start, GSList *stop);
|
||||
|
||||
/* Specify that the next command sent to server will be redirected.
|
||||
NOTE: This command MUST be called before irc_send_cmd().
|
||||
|
||||
command - Specifies the registered command that should be used for this
|
||||
redirection.
|
||||
|
||||
arg - The argument to be compared in event strings. You can give multiple
|
||||
arguments separated with space.
|
||||
|
||||
remote - Specifies if the command is a remote command, -1 = use default.
|
||||
|
||||
failure_signal - If irssi can't find the stop signal for the redirection,
|
||||
this signal is called.
|
||||
|
||||
... - char *event, char *redirect_signal, ..., NULL
|
||||
If the `event' is "", all the events belonging to the redirection but not
|
||||
specified here, will be sent there. */
|
||||
void server_redirect_event(IRC_SERVER_REC *server, const char *command,
|
||||
const char *arg, int remote,
|
||||
const char *failure_signal, ...);
|
||||
/* Signals list shouldn't be free'd after, and it's strings should be
|
||||
dynamically allocated */
|
||||
void server_redirect_event_list(IRC_SERVER_REC *server, const char *command,
|
||||
const char *arg, int remote,
|
||||
const char *failure_signal, GSList *signals);
|
||||
|
||||
/* INTERNAL: */
|
||||
|
||||
/* irc_send_cmd() calls this to make sure redirecting knows
|
||||
what's sent to server */
|
||||
void server_redirect_command(IRC_SERVER_REC *server, const char *command);
|
||||
/* Returns the redirection signal for specified event.
|
||||
This is the function that contains the real redirecting logic. */
|
||||
const char *server_redirect_get_signal(IRC_SERVER_REC *server,
|
||||
const char *event,
|
||||
const char *args);
|
||||
|
||||
void servers_redirect_init(void);
|
||||
void servers_redirect_deinit(void);
|
||||
|
||||
#endif
|
@ -3,8 +3,6 @@
|
||||
|
||||
#define MODULE_NAME "irc/notifylist"
|
||||
|
||||
#define ISON_EVENT "event 303"
|
||||
|
||||
typedef struct {
|
||||
char *nick;
|
||||
char *user, *host, *realname, *awaymsg;
|
||||
@ -22,6 +20,8 @@ typedef struct {
|
||||
} NOTIFY_NICK_REC;
|
||||
|
||||
typedef struct {
|
||||
int ison_count; /* number of ISON requests sent */
|
||||
|
||||
GSList *notify_users; /* NOTIFY_NICK_REC's of notifylist people who are in IRC */
|
||||
GSList *ison_tempusers; /* Temporary list for saving /ISON events.. */
|
||||
} MODULE_SERVER_REC;
|
||||
|
@ -81,28 +81,19 @@ NOTIFY_NICK_REC *notify_nick_find(IRC_SERVER_REC *server, const char *nick)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int is_ison_queue_empty(IRC_SERVER_REC *server)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
tmp = server_redirect_getqueue((SERVER_REC *) server, ISON_EVENT, NULL);
|
||||
for (; tmp != NULL; tmp = tmp->next) {
|
||||
REDIRECT_REC *rec = tmp->data;
|
||||
|
||||
if (strcmp(rec->name, "notifylist event") == 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void ison_send(IRC_SERVER_REC *server, GString *cmd)
|
||||
{
|
||||
MODULE_SERVER_REC *mserver;
|
||||
|
||||
mserver = MODULE_DATA(server);
|
||||
mserver->ison_count++;
|
||||
|
||||
g_string_truncate(cmd, cmd->len-1);
|
||||
g_string_prepend(cmd, "ISON :");
|
||||
|
||||
server_redirect_event(server, "ison", NULL, -1, NULL,
|
||||
"event 303", "notifylist event", NULL);
|
||||
irc_send_cmd(server, cmd->str);
|
||||
server_redirect_event((SERVER_REC *) server, NULL, 1, ISON_EVENT, "notifylist event", -1, NULL);
|
||||
|
||||
g_string_truncate(cmd, 0);
|
||||
}
|
||||
@ -111,6 +102,7 @@ static void ison_send(IRC_SERVER_REC *server, GString *cmd)
|
||||
notify list is in IRC */
|
||||
static void notifylist_timeout_server(IRC_SERVER_REC *server)
|
||||
{
|
||||
MODULE_SERVER_REC *mserver;
|
||||
GSList *tmp;
|
||||
GString *cmd;
|
||||
char *nick, *ptr;
|
||||
@ -121,7 +113,8 @@ static void notifylist_timeout_server(IRC_SERVER_REC *server)
|
||||
if (!IS_IRC_SERVER(server))
|
||||
return;
|
||||
|
||||
if (!is_ison_queue_empty(server)) {
|
||||
mserver = MODULE_DATA(server);
|
||||
if (mserver->ison_count > 0) {
|
||||
/* still not received all replies to previous /ISON commands.. */
|
||||
return;
|
||||
}
|
||||
@ -184,16 +177,13 @@ static void whois_send(IRC_SERVER_REC *server, char *nicks)
|
||||
for (p = str+strlen(nicks)+1; *p != '\0'; p++)
|
||||
if (*p == ',') *p = ' ';
|
||||
|
||||
server_redirect_event((SERVER_REC *) server, str, 2,
|
||||
"event 318", "notifylist event whois end", 1,
|
||||
"event 402", "event empty", 1,
|
||||
"event 401", "event empty", 1,
|
||||
"event 311", "notifylist event whois", 1,
|
||||
"event 301", "notifylist event whois away", 1,
|
||||
"event 312", "event empty", 1,
|
||||
"event 313", "event empty", 1,
|
||||
"event 317", "notifylist event whois idle", 1,
|
||||
"event 319", "event empty", 1, NULL);
|
||||
server_redirect_event(server, "whois", str, FALSE,
|
||||
"notifylist event whois end",
|
||||
"event 318", "notifylist event whois end",
|
||||
"event 311", "notifylist event whois",
|
||||
"event 301", "notifylist event whois away",
|
||||
"event 317", "notifylist event whois idle",
|
||||
"", "event empty", NULL);
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
@ -311,7 +301,7 @@ static void event_ison(IRC_SERVER_REC *server, const char *data)
|
||||
mserver = MODULE_DATA(server);
|
||||
ison_save_users(mserver, online);
|
||||
|
||||
if (!is_ison_queue_empty(server)) {
|
||||
if (--mserver->ison_count > 0) {
|
||||
/* wait for the rest of the /ISON replies */
|
||||
g_free(params);
|
||||
return;
|
||||
|
@ -144,8 +144,10 @@ static void event_whois_end(IRC_SERVER_REC *server, const char *data)
|
||||
|
||||
if (event != NULL) {
|
||||
signal_emit(event, 6, server, rec->nick,
|
||||
rec->user, rec->host,
|
||||
rec->realname, rec->awaymsg);
|
||||
rec->user != NULL ? rec->user : "??",
|
||||
rec->host != NULL ? rec->host : "??",
|
||||
rec->realname != NULL ? rec->realname : "??",
|
||||
rec->awaymsg);
|
||||
}
|
||||
rec->idle_ok = notify->idle_check_time <= 0 ||
|
||||
rec->idle_time <= notify->idle_check_time;
|
||||
|
@ -196,8 +196,6 @@ static void notifylist_init_server(IRC_SERVER_REC *server)
|
||||
|
||||
rec = g_new0(MODULE_SERVER_REC,1 );
|
||||
MODULE_DATA_SET(server, rec);
|
||||
|
||||
server_redirect_init((SERVER_REC *) server, "command ison", 1, ISON_EVENT, NULL);
|
||||
}
|
||||
|
||||
static void notifylist_deinit_server(IRC_SERVER_REC *server)
|
||||
|
@ -46,47 +46,6 @@ void
|
||||
server_disconnect(server)
|
||||
Irssi::Server server
|
||||
|
||||
void
|
||||
server_redirect_init(server, command, last, ...)
|
||||
Irssi::Server server
|
||||
char *command
|
||||
int last
|
||||
PREINIT:
|
||||
STRLEN n_a;
|
||||
GSList *list;
|
||||
int n;
|
||||
CODE:
|
||||
list = NULL;
|
||||
for (n = 3; n < items; n++) {
|
||||
list = g_slist_append(list, SvPV(ST(n), n_a));
|
||||
}
|
||||
server_redirect_initv(server, command, last, list);
|
||||
|
||||
int
|
||||
server_redirect_single_event(server, arg, last, group, event, signal, argpos)
|
||||
Irssi::Server server
|
||||
char *arg
|
||||
int last
|
||||
int group
|
||||
char *event
|
||||
char *signal
|
||||
int argpos
|
||||
|
||||
void
|
||||
server_redirect_event(server, arg, last, ...)
|
||||
Irssi::Server server
|
||||
char *arg
|
||||
int last
|
||||
PREINIT:
|
||||
STRLEN n_a;
|
||||
int n, group;
|
||||
CODE:
|
||||
group = 0;
|
||||
for (n = 3; n+3 <= items; n += 3, last--) {
|
||||
group = server_redirect_single_event(server, arg, last > 0, group,
|
||||
(char *) SvPV(ST(n), n_a), (char *) SvPV(ST(n+1), n_a), (int) SvIV(ST(n+2)));
|
||||
}
|
||||
|
||||
int
|
||||
isnickflag(server, flag)
|
||||
Irssi::Server server
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "chatnets.h"
|
||||
#include "servers.h"
|
||||
#include "servers-reconnect.h"
|
||||
#include "servers-redirect.h"
|
||||
#include "servers-setup.h"
|
||||
#include "channels.h"
|
||||
#include "queries.h"
|
||||
|
@ -35,6 +35,44 @@ ctcp_send_reply(server, data)
|
||||
Irssi::Irc::Server server
|
||||
char *data
|
||||
|
||||
MODULE = Irssi::Irc::Server PACKAGE = Irssi::Irc::Server PREFIX = server_
|
||||
|
||||
void
|
||||
server_redirect_register(command, remote, timeout, ...)
|
||||
char *command
|
||||
int remote
|
||||
int timeout
|
||||
PREINIT:
|
||||
STRLEN n_a;
|
||||
GSList *start, *stop, **list;
|
||||
int n;
|
||||
CODE:
|
||||
start = stop = NULL; list = &start;
|
||||
for (n = 3; n < items; n++) {
|
||||
if (ST(n) == &PL_sv_undef) list = &stop;
|
||||
if (SvPOK(ST(n)))
|
||||
*list = g_slist_append(*list, SvPV(ST(n), n_a));
|
||||
}
|
||||
server_redirect_register_list(command, remote, timeout, start, stop);
|
||||
|
||||
void
|
||||
server_redirect_event(server, command, arg, remote, failure_signal, ...)
|
||||
Irssi::Irc::Server server
|
||||
char *command
|
||||
char *arg
|
||||
int remote
|
||||
char *failure_signal
|
||||
PREINIT:
|
||||
STRLEN n_a;
|
||||
GSList *list;
|
||||
int n;
|
||||
CODE:
|
||||
list = NULL;
|
||||
for (n = 5; n < items; n++) {
|
||||
list = g_slist_append(list, SvPV(ST(n), n_a));
|
||||
}
|
||||
server_redirect_event_list(server, command, arg, remote, failure_signal, list);
|
||||
|
||||
MODULE = Irssi::Irc::Server PACKAGE = Irssi::Irc::Connect PREFIX = irc_server_
|
||||
|
||||
Irssi::Irc::Server
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "modes.h"
|
||||
#include "mode-lists.h"
|
||||
#include "netsplit.h"
|
||||
#include "servers-redirect.h"
|
||||
|
||||
#include "dcc/dcc.h"
|
||||
#include "dcc/dcc-file.h"
|
||||
|
Loading…
Reference in New Issue
Block a user