1
0
mirror of https://github.com/anope/anope.git synced 2026-06-29 18:16:38 +02:00
Files
anope/servers.c
T
dane dane@31f1291d-b8d6-0310-a050-a5561fc1590b 1d1c478e4f BUILD : 1.7.4 (206) BUGS : 55 NOTES : Added proper Bahamut1.8 support. Merged r132:195 from branch branches/proto/anope-bahamut18 which should now be obsolete.
git-svn-id: svn://svn.anope.org/anope/trunk@206 31f1291d-b8d6-0310-a050-a5561fc1590b


git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@148 5417fbe8-f217-4b02-8779-1006273d7864
2004-06-18 16:38:43 +00:00

260 lines
6.5 KiB
C

/* Routines to maintain a list of connected servers
*
* (C) 2004 Anope Team / GeniusDex
* Contact us at info@anope.org
*
* Please read COPYING and README for furhter details.
*
* Based on the original code of Epona by Lara.
* Based on the original code of Services by Andy Church.
*
* $Id$
*
*/
#include "services.h"
Server *servlist = NULL;
Server *me_server = NULL;
#ifdef IRC_BAHAMUT
uint16 uplink_capab;
#endif
/* For first_server / next_server */
static Server *server_cur;
/*************************************************************************/
/* Walk through the servers list */
Server *first_server(int flags)
{
server_cur = servlist;
if (flags > -1) {
while (server_cur && (server_cur->flags != flags))
server_cur = next_server(flags);
}
return server_cur;
}
Server *next_server(int flags)
{
if (!server_cur)
return NULL;
do {
if (server_cur->links) {
server_cur = server_cur->links;
} else if (server_cur->next) {
server_cur = server_cur->next;
} else {
do {
server_cur = server_cur->uplink;
if (server_cur && server_cur->next) {
server_cur = server_cur->next;
break;
}
} while (server_cur);
}
} while (server_cur && ((flags > -1) || (server_cur->flags != flags)));
return server_cur;
}
/*************************************************************************/
/* This function makes a new Server structure and links it in the right
* places in the linked list if a Server struct to it's uplink if provided.
* It can also be NULL to indicate it's the uplink and should be first in
* the server list.
*/
Server *new_server(Server * uplink, const char *name, const char *desc,
uint16 flags)
{
Server *serv;
serv = scalloc(sizeof(Server), 1);
if (!name)
name = "";
serv->name = sstrdup(name);
serv->desc = sstrdup(desc);
serv->flags = flags;
serv->uplink = uplink;
serv->links = NULL;
serv->prev = NULL;
if (!uplink) {
serv->hops = 0;
serv->next = servlist;
if (servlist)
servlist->prev = serv;
servlist = serv;
} else {
serv->hops = uplink->hops + 1;
serv->next = uplink->links;
if (uplink->links)
uplink->links->prev = serv;
uplink->links = serv;
}
return serv;
}
/*************************************************************************/
/* Remove and free a Server structure. This function is the most complete
* remove treatment a server can get, as it first quits all clients which
* still pretend to be on this server, then it walks through all connected
* servers and disconnects them too. If all mess is cleared, the server
* itself will be too.
*/
static void delete_server(Server * serv, const char *quitreason)
{
Server *s, *snext;
#ifdef IRC_BAHAMUT
User *u, *unext;
NickAlias *na;
#endif
if (!serv) {
alog("delete_server() called with NULL arg!");
return;
}
if (debug)
alog("delete_server() called for %s", serv->name);
#ifdef IRC_BAHAMUT
if (uplink_capab & CAPAB_NOQUIT) {
u = firstuser();
while (u) {
unext = nextuser();
if (u->server == serv) {
if ((na = u->na) && !(na->status & NS_VERBOTEN)
&& (na->status & (NS_IDENTIFIED | NS_RECOGNIZED))) {
na->last_seen = time(NULL);
if (na->last_quit)
free(na->last_quit);
na->last_quit =
(quitreason ? sstrdup(quitreason) : NULL);
}
#ifndef STREAMLINED
if (LimitSessions)
del_session(u->host);
#endif
delete_user(u);
}
u = unext;
}
if (debug >= 2)
alog("delete_server() cleared all users");
}
#endif
s = serv->links;
while (s) {
snext = s->next;
delete_server(s, quitreason);
s = snext;
}
if (debug >= 2)
alog("delete_server() cleared all servers");
free(serv->name);
free(serv->desc);
if (serv->prev)
serv->prev->next = serv->next;
if (serv->next)
serv->next->prev = serv->prev;
if (serv->uplink->links == serv)
serv->uplink->links = serv->next;
if (debug)
alog("delete_server() completed");
}
/*************************************************************************/
/* Find a server by name, returns NULL if not found */
Server *findserver(Server * s, const char *name)
{
Server *sl;
if (debug >= 3)
alog("debug: findserver(%p)", name);
while (s && (stricmp(s->name, name) != 0)) {
if (s->links) {
sl = findserver(s->links, name);
if (sl)
s = sl;
else
s = s->next;
} else {
s = s->next;
}
}
if (debug >= 3)
alog("debug: findserver(%s) -> %p", name, s);
return s;
}
/*************************************************************************/
/* :<introducing server> SERVER <servername> <hops> :<description>
*/
void do_server(const char *source, int ac, char **av)
{
Server *s;
if (debug)
alog("debug: Server introduced (%s) from %s", av[0], source);
if (source[0] == '\0')
s = me_server;
else
s = findserver(servlist, source);
#ifdef IRC_PTLINK
if (ac < 4)
alog("Malformed SERVER received (less than 4 params)");
else
new_server(s, av[0], av[3], 0);
#else
if (ac < 3)
alog("Malformed SERVER received (less than 3 params)");
else
new_server(s, av[0], av[2], 0);
#endif
}
/*************************************************************************/
/* SQUIT <server> :<comment>
*/
void do_squit(const char *source, int ac, char **av)
{
char buf[BUFSIZE];
Server *s;
s = findserver(servlist, av[0]);
if (!s) {
alog("SQUIT for nonexistent server (%s)!!", av[0]);
return;
}
snprintf(buf, sizeof(buf), "%s %s", s->name,
(s->uplink ? s->uplink->name : ""));
#ifdef IRC_BAHAMUT
if ((s->uplink == me_server) && (uplink_capab & CAPAB_UNCONNECT)) {
if (debug)
alog("debuf: Sending UNCONNECT SQUIT for %s", s->name);
send_cmd(ServerName, "SQUIT %s :%s", s->name, buf);
}
#endif
delete_server(s, buf);
}
/* EOF */