1
0
mirror of https://github.com/irssi/irssi.git synced 2024-12-04 14:46:39 -05:00

Rework redirections to deal with multiple concurrent redirects better.

These mostly happen when doing remote whois and the
target server is slow.
The code uses the source server but will try to do what it
can if servers think they need to mask it.


git-svn-id: http://svn.irssi.org/repos/irssi/trunk@4638 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Jilles Tjoelker 2007-11-14 23:02:40 +00:00 committed by jilles
parent fabecae6e6
commit 90b66dbe6c
6 changed files with 80 additions and 39 deletions

View File

@ -42,7 +42,7 @@ struct _IRC_SERVER_REC {
GSList *redirects;
GSList *redirect_queue; /* should be updated from redirect_next each time cmdqueue is updated */
REDIRECT_REC *redirect_next;
REDIRECT_REC *redirect_continue;
GSList *redirect_active; /* redirects start event has been received for, must have unique prefix */
char *last_nick; /* last /NICK, kept even if it resulted as not valid change */

View File

@ -303,7 +303,7 @@ static void irc_server_event(IRC_SERVER_REC *server, const char *line,
g_strdown(event);
/* check if event needs to be redirected */
signal = server_redirect_get_signal(server, event, args);
signal = server_redirect_get_signal(server, recoded_nick, event, args);
if (signal == NULL)
signal = event;
else

View File

@ -46,6 +46,7 @@ struct _REDIRECT_REC {
REDIRECT_CMD_REC *cmd;
time_t created;
int failures;
char *prefix;
unsigned int destroyed:1;
unsigned int aborted:1;
@ -110,6 +111,7 @@ void server_redirect_destroy(REDIRECT_REC *rec)
{
redirect_cmd_unref(rec->cmd);
g_free_not_null(rec->prefix);
g_free_not_null(rec->arg);
g_free_not_null(rec->failure_signal);
g_free_not_null(rec->default_signal);
@ -386,13 +388,29 @@ static const char *redirect_match(REDIRECT_REC *redirect, const char *event,
else {
cmdpos = redirect_cmd_list_find(redirect->cmd->stop,
event);
match_list = cmdpos != NULL ? MATCH_STOP : MATCH_NONE;
if (cmdpos != NULL)
match_list = MATCH_STOP;
else if (redirect->default_signal != NULL &&
args == NULL &&
strncmp(event, "event ", 6) == 0 &&
i_isdigit(event[6])) {
/* If there is a default signal, the
* redirection has already started and
* this is a numeric, use it */
/* XXX this should depend on the
* REDIRECT_CMD_REC, not REDIRECT_REC */
if (signal == NULL)
signal = redirect->default_signal;
match_list = MATCH_START;
} else {
match_list = MATCH_NONE;
}
}
}
if (signal == NULL && cmdpos == NULL) {
/* event not found from specified redirection events nor
registered command events */
registered command events, and no default signal */
return NULL;
}
@ -428,8 +446,7 @@ static void redirect_abort(IRC_SERVER_REC *server, REDIRECT_REC *rec)
signal_emit(rec->last_signal, 1, server);
}
if (server->redirect_continue == rec)
server->redirect_continue = NULL;
server->redirect_active = g_slist_remove(server->redirect_active, rec);
server_redirect_destroy(rec);
}
@ -452,6 +469,10 @@ static REDIRECT_REC *redirect_find(IRC_SERVER_REC *server, const char *event,
for (tmp = server->redirects; tmp != NULL; tmp = tmp->next) {
REDIRECT_REC *rec = tmp->data;
/* already active, don't try to start it again */
if (g_slist_find(server->redirect_active, rec) != NULL)
continue;
match_signal = redirect_match(rec, event, args, match);
if (match_signal != NULL && *match != MATCH_NONE) {
redirect = rec;
@ -488,10 +509,13 @@ static REDIRECT_REC *redirect_find(IRC_SERVER_REC *server, const char *event,
}
static const char *
server_redirect_get(IRC_SERVER_REC *server, const char *event,
const char *args, REDIRECT_REC **redirect, int *match)
server_redirect_get(IRC_SERVER_REC *server, const char *prefix,
const char *event, const char *args,
REDIRECT_REC **redirect, int *match)
{
const char *signal;
GSList *ptr, *next;
REDIRECT_REC *r;
*redirect = NULL;
*match = MATCH_NONE;
@ -499,33 +523,39 @@ server_redirect_get(IRC_SERVER_REC *server, const char *event,
if (server->redirects == NULL)
return NULL;
if (server->redirect_continue == NULL) {
/* find the redirection */
*redirect = redirect_find(server, event, args, &signal, match);
} else {
for (ptr = server->redirect_active; ptr != NULL; ptr = next) {
next = ptr->next;
r = ptr->data;
if (prefix != NULL && r->prefix != NULL &&
strcmp(prefix, r->prefix)) {
/* not from this server */
continue;
}
/* redirection is already started, now we'll just need to
keep redirecting until stop-event is found. */
*redirect = server->redirect_continue;
*redirect = r;
signal = redirect_match(*redirect, event, NULL, match);
if (signal == NULL) {
/* unknown event - redirect to the default signal. */
if (strncmp(event, "event ", 6) == 0 &&
i_isdigit(event[6])) {
signal = (*redirect)->default_signal;
if (*match == MATCH_NONE)
*match = MATCH_START;
} else {
/* not a numeric, so we've lost the
stop event.. */
(*redirect)->aborted = TRUE;
redirect_abort(server, *redirect);
/* not a numeric, so we've lost the
stop event.. */
(*redirect)->aborted = TRUE;
redirect_abort(server, *redirect);
*redirect = NULL;
signal = NULL;
}
*redirect = NULL;
}
if (*redirect != NULL)
break;
}
if (*redirect == NULL) {
/* find the redirection */
*redirect = redirect_find(server, event, args, &signal, match);
}
/* remember which server is replying to our request */
if (*redirect != NULL && prefix != NULL && (*redirect)->prefix == NULL)
(*redirect)->prefix = g_strdup(prefix);
if (*redirect != NULL && (*redirect)->first_signal != NULL &&
!(*redirect)->first_signal_sent) {
/* emit the first_signal */
@ -537,6 +567,7 @@ server_redirect_get(IRC_SERVER_REC *server, const char *event,
}
const char *server_redirect_get_signal(IRC_SERVER_REC *server,
const char *prefix,
const char *event,
const char *args)
{
@ -544,22 +575,26 @@ const char *server_redirect_get_signal(IRC_SERVER_REC *server,
const char *signal;
int match;
signal = server_redirect_get(server, event, args, &redirect, &match);
if (match != MATCH_STOP || redirect == NULL)
server->redirect_continue = redirect;
else {
signal = server_redirect_get(server, prefix, event, args, &redirect, &match);
if (redirect == NULL)
;
else if (match != MATCH_STOP) {
if (g_slist_find(server->redirect_active, redirect) == NULL)
server->redirect_active = g_slist_prepend(server->redirect_active, redirect);
} else {
/* stop event - remove this redirection next time this
function is called (can't destroy now or our return
value would be corrupted) */
if (--redirect->count <= 0)
redirect->destroyed = TRUE;
server->redirect_continue = NULL;
server->redirect_active = g_slist_remove(server->redirect_active, redirect);
}
return signal;
}
const char *server_redirect_peek_signal(IRC_SERVER_REC *server,
const char *prefix,
const char *event,
const char *args,
int *redirected)
@ -568,7 +603,7 @@ const char *server_redirect_peek_signal(IRC_SERVER_REC *server,
const char *signal;
int match;
signal = server_redirect_get(server, event, args, &redirect, &match);
signal = server_redirect_get(server, prefix, event, args, &redirect, &match);
*redirected = match != MATCH_NONE;
return signal;
}
@ -578,6 +613,8 @@ static void sig_disconnected(IRC_SERVER_REC *server)
if (!IS_IRC_SERVER(server))
return;
g_slist_free(server->redirect_active);
server->redirect_active = NULL;
g_slist_foreach(server->redirects,
(GFunc) server_redirect_destroy, NULL);
g_slist_free(server->redirects);

View File

@ -64,6 +64,7 @@ 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 *prefix,
const char *event,
const char *args);
/* Returns the redirection signal for specified event.
@ -72,6 +73,7 @@ const char *server_redirect_get_signal(IRC_SERVER_REC *server,
`redirected' is set to TRUE, if this event belongs to redirection even
while there might be no redirection signal. */
const char *server_redirect_peek_signal(IRC_SERVER_REC *server,
const char *prefix,
const char *event,
const char *args,
int *redirected);

View File

@ -391,7 +391,7 @@ static void sig_server_event(IRC_SERVER_REC *server, const char *line,
while (*args == ' ') args++;
g_strdown(event);
signal = server_redirect_peek_signal(server, event, args, &redirected);
signal = server_redirect_peek_signal(server, nick, event, args, &redirected);
if ((signal != NULL && strncmp(signal, "proxy ", 6) != 0) ||
(signal == NULL && redirected)) {
/* we want to send this to one client (or proxy itself) only */
@ -401,7 +401,7 @@ static void sig_server_event(IRC_SERVER_REC *server, const char *line,
}
if (signal != NULL) {
server_redirect_get_signal(server, event, args);
server_redirect_get_signal(server, nick, event, args);
if (sscanf(signal+6, "%p", &client) == 1) {
/* send it to specific client only */
if (g_slist_find(proxy_clients, client) != NULL)

View File

@ -116,24 +116,26 @@ CODE:
event_hash2list(hvref(signals)));
char *
server_redirect_get_signal(server, event, args)
server_redirect_get_signal(server, prefix, event, args)
Irssi::Irc::Server server
char *prefix
char *event
char *args
CODE:
RETVAL = (char *) server_redirect_get_signal(server, event, args);
RETVAL = (char *) server_redirect_get_signal(server, prefix, event, args);
OUTPUT:
RETVAL
char *
server_redirect_peek_signal(server, event, args)
server_redirect_peek_signal(server, prefix, event, args)
Irssi::Irc::Server server
char *prefix
char *event
char *args
PREINIT:
int redirection;
CODE:
RETVAL = (char *) server_redirect_peek_signal(server, event, args, &redirection);
RETVAL = (char *) server_redirect_peek_signal(server, prefix, event, args, &redirection);
OUTPUT:
RETVAL