/* * servers.C: Server and network state tracking. * Rights to this code are documented in doc/pod/license.pod. * * Copyright © 2005-2007 Atheme Project (http://www.atheme.org) */ static char const rcsid[] = "$Id: servers.C,v 1.5 2007/09/09 20:05:52 pippijn Exp $"; #include "atheme.h" #include "servers.h" #include typedef std::pair server_pair; typedef std::map server_map; server_map sidlist; server_map servlist; list_t tldlist; server_t::callbacks server_t::callback; /* * init_servers() * * Initializes the server heap and server/sid DTree structures. * * Inputs: * - nothing * * Outputs: * - nothing * * Side Effects: * - if the heap or dtrees fail to initialize, the program * will abort. */ void init_servers (void) { #if 0 serv_heap = BlockHeapCreate (sizeof (server_t), HEAP_SERVER); tld_heap = BlockHeapCreate (sizeof (tld_t), 4); #endif } /* * server_add(char const * const name, unsigned int hops, char const * const uplink, * char const * const id, char const * const desc) * * Server object factory. * * Inputs: * - name of server object to create * - amount of hops server has from services * - name of server's uplink or NULL if it's us * - SID of uplink if applicable otherwise NULL * - server's description * * Outputs: * - on success, a new server object * * Side Effects: * - the new server object is added to the server and sid DTree. */ server_t * server_add (char const * const name, unsigned int hops, char const * const uplink, char const * const id, char const * const description) { server_t *s, *u = NULL; char const *tld; char const *desc = description; if (uplink) { if (id != NULL) slog (LG_NETWORK, "server_add(): %s (%s), uplink %s", name, id, uplink); else slog (LG_NETWORK, "server_add(): %s, uplink %s", name, uplink); u = server_find (uplink); } else slog (LG_DEBUG, "server_add(): %s, root", name); s = new server_t; if (id != NULL) { s->sid = sstrdup (id); sidlist[s->sid] = s; } /* check to see if it's hidden */ if (!strncmp (desc, "(H)", 3)) { s->flags |= SF_HIDE; desc += 3; if (*desc == ' ') desc++; } s->name = sstrdup (name); s->desc = sstrdup (desc); s->hops = hops; s->connected_since = NOW; servlist[s->name] = s; if (u) { s->uplink = u; node_add (s, node_create (), &u->children); } /* tld list for global noticer */ tld = strrchr (name, '.'); if (tld != NULL) { if (!tld_find (tld)) tld_add (tld); } cnt.server++; return s; } void server_delete (char const * const name) { server_t *s = server_find (name); server_delete (s); if (!s) { slog (LG_DEBUG, "server_delete(): called for nonexistant server: %s", name); return; } } /* * server_delete(char const * const name) * * Finds and recursively destroys a server object. * * Inputs: * - name of server to find and destroy * * Outputs: * - nothing * * Side Effects: * - all users and servers attached to the target are recursively deleted */ void server_delete (server_t *s, bool force) { server_t *child; user_t *u; node_t *n, *tn; if (!force && s == me.me) { /* Deleting this would cause confusion, so let's not do it. * Some ircds send SQUIT when we are squitted. * -- jilles */ slog (LG_DEBUG, "server_delete(): tried to delete myself"); return; } slog (me.connected ? LG_NETWORK : LG_DEBUG, "server_delete(): %s, uplink %s (%d users)", s->name, s->uplink != NULL ? s->uplink->name : "", s->users); /* first go through it's users and kill all of them */ LIST_FOREACH_SAFE (n, tn, s->userlist.head) { u = (user_t *) n->data; /* This user split, allow bursted logins for the account. * XXX should we do this here? * -- jilles */ if (u->myuser != NULL) u->myuser->flags &= ~MU_NOBURSTLOGIN; user_delete (u); } LIST_FOREACH_SAFE (n, tn, s->children.head) { child = static_cast (n->data); server_delete (child->name); } /* now remove the server */ servlist.erase (s->name); if (s->sid) sidlist.erase (s->sid); if (s->uplink) { n = node_find (s, &s->uplink->children); node_del (n, &s->uplink->children); node_free (n); } /* If unconnect semantics SQUIT was confirmed, introduce the jupe * now. This must be after removing the server from the dtrees. * -- jilles */ if (s->flags & SF_JUPE_PENDING) phandler->jupe (s->name, "Juped"); sfree (s->name); sfree (s->desc); if (s->sid) sfree (s->sid); delete s; cnt.server--; } /* * server_find(char const * const name) * * Finds a server object. * * Inputs: * - name of server to find * * Outputs: * - on success, the server object * - on failure, NULL. * * Side Effects: * - none */ server_t * server_find (char const * const name) { server_map::iterator it; if (ircd->uses_uid) { it = sidlist.find (name); if (it != sidlist.end ()) return it->second; } return ((it = servlist.find (name)) == servlist.end () ? NULL : it->second); } /* * tld_add(char const * const name) * * TLD object factory. * * Inputs: * - name of TLD to cache as an object * * Outputs: * - on success, a TLD object * - on failure, NULL * * Side Effects: * - the TLD object is registered with the TLD list. */ tld_t * tld_add (char const * const name) { tld_t *tld; node_t *n = node_create (); slog (LG_DEBUG, "tld_add(): %s", name); tld = new tld_t; node_add (tld, n, &tldlist); tld->name = sstrdup (name); cnt.tld++; return tld; } /* * tld_delete(char const * const name) * * Destroys a TLD object. * * Inputs: * - name of TLD object to destroy * * Outputs: * - nothing * * Side Effects: * - the TLD object is removed and deregistered from the TLD list. */ void tld_delete (char const * const name) { tld_t *tld = tld_find (name); node_t *n; if (!tld) { slog (LG_DEBUG, "tld_delete(): called for nonexistant tld: %s", name); return; } slog (LG_DEBUG, "tld_delete(): %s", tld->name); n = node_find (tld, &tldlist); node_del (n, &tldlist); node_free (n); sfree (tld->name); delete tld; cnt.tld--; } /* * tld_find(char const * const name) * * Looks up a TLD object. * * Inputs: * - name of TLD object to look up * * Outputs: * - on success, the TLD object * - on failure, NULL * * Side Effects: * - none */ tld_t * tld_find (char const * const name) { tld_t *tld; node_t *n; if (name == NULL) return NULL; LIST_FOREACH (n, tldlist.head) { tld = (tld_t *) n->data; if (!strcasecmp (name, tld->name)) return tld; } return NULL; } /* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs * vim:ts=8 * vim:sw=8 * vim:noexpandtab */