summaryrefslogtreecommitdiff
path: root/servers.c
diff options
context:
space:
mode:
Diffstat (limited to 'servers.c')
-rw-r--r--servers.c259
1 files changed, 259 insertions, 0 deletions
diff --git a/servers.c b/servers.c
new file mode 100644
index 000000000..71e6ce92a
--- /dev/null
+++ b/servers.c
@@ -0,0 +1,259 @@
+/* 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 */