mirror of
https://github.com/irssi/irssi.git
synced 2026-08-11 21:00:40 +02:00
..adding new files..
git-svn-id: http://svn.irssi.org/repos/irssi/trunk@171 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
parent
d01b094151
commit
c95034c6de
206 changed files with 31247 additions and 0 deletions
270
src/irc/core/netsplit.c
Normal file
270
src/irc/core/netsplit.c
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
netsplit.c : irssi
|
||||
|
||||
Copyright (C) 1999 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 "commands.h"
|
||||
#include "misc.h"
|
||||
#include "common-setup.h"
|
||||
|
||||
#include "irc-server.h"
|
||||
#include "netsplit.h"
|
||||
|
||||
static int split_tag;
|
||||
|
||||
static NETSPLIT_REC *netsplit_add(IRC_SERVER_REC *server, const char *nick, const char *address, const char *servers)
|
||||
{
|
||||
NETSPLIT_REC *rec;
|
||||
NETSPLIT_CHAN_REC *splitchan;
|
||||
NICK_REC *nickrec;
|
||||
GSList *tmp;
|
||||
char *p, *dupservers;
|
||||
|
||||
g_return_val_if_fail(server != NULL, NULL);
|
||||
g_return_val_if_fail(nick != NULL, NULL);
|
||||
g_return_val_if_fail(address != NULL, NULL);
|
||||
|
||||
dupservers = g_strdup(servers);
|
||||
p = strchr(dupservers, ' ');
|
||||
if (p == NULL) {
|
||||
g_free(dupservers);
|
||||
g_return_val_if_fail(p != NULL, NULL);
|
||||
}
|
||||
*p++ = '\0';
|
||||
|
||||
rec = g_new0(NETSPLIT_REC, 1);
|
||||
rec->nick = g_strdup(nick);
|
||||
rec->address = g_strdup(address);
|
||||
rec->destroy = time(NULL)+NETSPLIT_MAX_REMEMBER;
|
||||
|
||||
/* get splitted servers */
|
||||
rec->server = g_strdup(dupservers);
|
||||
rec->destserver = g_strdup(p);
|
||||
g_free(dupservers);
|
||||
|
||||
/* copy the channel nick records.. */
|
||||
for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
|
||||
CHANNEL_REC *channel = tmp->data;
|
||||
|
||||
nickrec = nicklist_find(channel, nick);
|
||||
if (nickrec == NULL)
|
||||
continue;
|
||||
|
||||
splitchan = g_new0(NETSPLIT_CHAN_REC, 1);
|
||||
splitchan->name = g_strdup(channel->name);
|
||||
memcpy(&splitchan->nick, nickrec, sizeof(NICK_REC));
|
||||
|
||||
rec->channels = g_slist_append(rec->channels, splitchan);
|
||||
}
|
||||
|
||||
g_hash_table_insert(server->splits, rec->nick, rec);
|
||||
signal_emit("netsplit add", 1, rec);
|
||||
return rec;
|
||||
}
|
||||
|
||||
static void netsplit_destroy(NETSPLIT_REC *rec)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
g_return_if_fail(rec != NULL);
|
||||
|
||||
signal_emit("netsplit remove", 1, rec);
|
||||
for (tmp = rec->channels; tmp != NULL; tmp = tmp->next) {
|
||||
NETSPLIT_CHAN_REC *rec = tmp->data;
|
||||
|
||||
g_free(rec->name);
|
||||
g_free(rec);
|
||||
}
|
||||
|
||||
g_free(rec->server);
|
||||
g_free(rec->destserver);
|
||||
g_free(rec->nick);
|
||||
g_free(rec->address);
|
||||
g_free(rec);
|
||||
}
|
||||
|
||||
static void netsplit_destroy_hash(gpointer key, NETSPLIT_REC *rec)
|
||||
{
|
||||
netsplit_destroy(rec);
|
||||
}
|
||||
|
||||
NETSPLIT_REC *netsplit_find(IRC_SERVER_REC *server, const char *nick, const char *address)
|
||||
{
|
||||
NETSPLIT_REC *rec;
|
||||
|
||||
g_return_val_if_fail(server != NULL, NULL);
|
||||
g_return_val_if_fail(nick != NULL, NULL);
|
||||
|
||||
rec = g_hash_table_lookup(server->splits, nick);
|
||||
if (rec == NULL) return NULL;
|
||||
|
||||
return (address == NULL || g_strcasecmp(rec->address, address) == 0) ? rec : NULL;
|
||||
}
|
||||
|
||||
NICK_REC *netsplit_find_channel(IRC_SERVER_REC *server, const char *nick, const char *address, const char *channel)
|
||||
{
|
||||
NETSPLIT_REC *rec;
|
||||
GSList *tmp;
|
||||
|
||||
rec = netsplit_find(server, nick, address);
|
||||
if (rec == NULL) return NULL;
|
||||
|
||||
for (tmp = rec->channels; tmp != NULL; tmp = tmp->next) {
|
||||
NETSPLIT_CHAN_REC *rec = tmp->data;
|
||||
|
||||
if (g_strcasecmp(rec->name, channel) == 0)
|
||||
return &rec->nick;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int is_split(const char *msg)
|
||||
{
|
||||
char *params, *host1, *host2, *p;
|
||||
int ok;
|
||||
|
||||
g_return_val_if_fail(msg != NULL, FALSE);
|
||||
|
||||
/* must have only two words */
|
||||
p = strchr(msg, ' ');
|
||||
if (p == NULL || strchr(p+1, ' ') != NULL) return FALSE;
|
||||
|
||||
/* check that it looks ok.. */
|
||||
if (!match_wildcards("*.* *.*", msg) ||
|
||||
match_wildcards("*..*", msg) || strstr(msg, "))") != NULL)
|
||||
return FALSE;
|
||||
|
||||
/* get the two hosts */
|
||||
ok = FALSE;
|
||||
params = cmd_get_params(msg, 2, &host1, &host2);
|
||||
if (g_strcasecmp(host1, host2) != 0) { /* hosts can't be same.. */
|
||||
/* check that domain length is 2 or 3 */
|
||||
p = strrchr(host1, '.');
|
||||
if (p != NULL && (strlen(p+1) == 2 || strlen(p+1) == 3)) {
|
||||
p = strrchr(host2, '.');
|
||||
if (p != NULL && (strlen(p+1) == 2 || strlen(p+1) == 3)) {
|
||||
/* it looks just like a netsplit to me. */
|
||||
ok = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_free(params);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
static void split_set_timeout(gpointer key, NETSPLIT_REC *rec, NETSPLIT_REC *orig)
|
||||
{
|
||||
if (rec == orig) {
|
||||
/* original nick, destroy it in a few seconds.. */
|
||||
rec->destroy = time(NULL)+4;
|
||||
} else if (g_strcasecmp(rec->server, orig->server) == 0 &&
|
||||
g_strcasecmp(rec->destserver, orig->destserver) == 0) {
|
||||
/* same servers -> split over -> destroy old records sooner.. */
|
||||
rec->destroy = time(NULL)+60;
|
||||
}
|
||||
}
|
||||
|
||||
static void event_join(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *address)
|
||||
{
|
||||
NETSPLIT_REC *rec;
|
||||
|
||||
/* check if split is over */
|
||||
rec = g_hash_table_lookup(server->splits, nick);
|
||||
if (rec == NULL) return;
|
||||
|
||||
if (g_strcasecmp(rec->address, address) == 0) {
|
||||
/* yep, looks like it is. for same people that had the same
|
||||
splitted servers set the timeout to one minute.
|
||||
|
||||
.. if the user just changed server, he/she can't use the
|
||||
same nick (unless the server is broken) so don't bother
|
||||
checking that the nick's server matches the split. */
|
||||
g_hash_table_foreach(server->splits, (GHFunc) split_set_timeout, rec);
|
||||
} else {
|
||||
/* back from different address.. just destroy it. */
|
||||
g_hash_table_remove(server->splits, rec->nick);
|
||||
netsplit_destroy(rec);
|
||||
}
|
||||
}
|
||||
|
||||
static void event_quit(const char *data, IRC_SERVER_REC *server, const char *nick, const char *address)
|
||||
{
|
||||
g_return_if_fail(data != NULL);
|
||||
|
||||
if (*data == ':') data++;
|
||||
if (g_strcasecmp(nick, server->nick) != 0 && is_split(data)) {
|
||||
/* netsplit! */
|
||||
netsplit_add(server, nick, address, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void sig_disconnected(IRC_SERVER_REC *server)
|
||||
{
|
||||
g_return_if_fail(server != NULL);
|
||||
|
||||
g_hash_table_foreach(server->splits, (GHFunc) netsplit_destroy_hash, NULL);
|
||||
g_hash_table_destroy(server->splits);
|
||||
}
|
||||
|
||||
static int split_server_check(gpointer key, NETSPLIT_REC *rec, IRC_SERVER_REC *server)
|
||||
{
|
||||
/* Check if this split record is too old.. */
|
||||
if (rec->destroy > time(NULL))
|
||||
return FALSE;
|
||||
|
||||
netsplit_destroy(rec);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int split_check_old(void)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
for (tmp = servers; tmp != NULL; tmp = tmp->next) {
|
||||
IRC_SERVER_REC *server = tmp->data;
|
||||
|
||||
g_hash_table_foreach_remove(server->splits, (GHRFunc) split_server_check, server);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void netsplit_init(void)
|
||||
{
|
||||
split_tag = g_timeout_add(1000, (GSourceFunc) split_check_old, NULL);
|
||||
signal_add_first("event join", (SIGNAL_FUNC) event_join);
|
||||
signal_add_first("event quit", (SIGNAL_FUNC) event_quit);
|
||||
signal_add("server disconnected", (SIGNAL_FUNC) sig_disconnected);
|
||||
}
|
||||
|
||||
void netsplit_deinit(void)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
for (tmp = servers; tmp != NULL; tmp = tmp->next)
|
||||
sig_disconnected(tmp->data);
|
||||
|
||||
g_source_remove(split_tag);
|
||||
signal_remove("event join", (SIGNAL_FUNC) event_join);
|
||||
signal_remove("event quit", (SIGNAL_FUNC) event_quit);
|
||||
signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue