/* * uplink.C: Uplink management. * * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team * Rights to this code are as documented in COPYING. * * * Portions of this file were derived from sources bearing the following license: * 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: uplink.C,v 1.9 2007/09/22 14:27:30 pippijn Exp $"; #include #include "atheme.h" #include "servers.h" #include "datastream.h" #include "uplink.h" #include "connection.h" uplink_t::list_type uplinks; uplink_t *curr_uplink; static void uplink_close (connection_t *cptr); void init_uplinks (void) { #if 0 uplink_heap = BlockHeapCreate (sizeof (uplink_t), 4); #endif } uplink_t * uplink_add (char *name, char *host, char *password, char *vhost, int port) { uplink_t *u; slog (LG_DEBUG, "uplink_add(): %s -> %s:%d", me.name, name, port); if ((u = uplink_find (name))) { if (u->flags & UPF_ILLEGAL) { u->flags &= ~UPF_ILLEGAL; sfree (u->name); sfree (u->host); sfree (u->pass); sfree (u->vhost); } else { slog (LG_INFO, "Duplicate uplink %s.", name); return NULL; } } else { u = new uplink_t; uplinks.insert (u); cnt.uplink++; } u->name = sstrdup (name); u->host = sstrdup (host); u->pass = sstrdup (password); if (vhost) u->vhost = sstrdup (vhost); else u->vhost = sstrdup ("0.0.0.0"); u->port = port; return u; } void uplink_delete (uplink_t *u) { sfree (u->name); sfree (u->host); sfree (u->pass); sfree (u->vhost); uplinks.erase (u); delete u; cnt.uplink--; } uplink_t * uplink_find (char *name) { foreach (uplink_t *u, uplinks) if (!strcasecmp (u->name, name)) return u; return NULL; } void uplink_connect (void) { uplink_t *u; if (curr_uplink == NULL) { if (uplinks.empty ()) { slog (LG_ERROR, "uplink_connect(): no uplinks configured, exiting. Make sure to have at least one uplink{} block in your configuration file."); exit (EXIT_FAILURE); } curr_uplink = uplinks.front (); slog (LG_INFO, "uplink_connect(): connecting to first entry %s[%s]:%d.", curr_uplink->name, curr_uplink->host, curr_uplink->port); } else if (curr_uplink != uplinks.back ()) { u = uplinks[curr_uplink->index + 1]; curr_uplink = u; slog (LG_INFO, "uplink_connect(): trying alternate uplink %s[%s]:%d", curr_uplink->name, curr_uplink->host, curr_uplink->port); } else { curr_uplink = uplinks.front (); slog (LG_INFO, "uplink_connect(): trying again first entry %s[%s]:%d", curr_uplink->name, curr_uplink->host, curr_uplink->port); } u = curr_uplink; curr_uplink->conn = connection_t::open_tcp (u->host, u->vhost, u->port, recvq_put, sendq_flush); if (curr_uplink->conn != NULL) curr_uplink->conn->close_handler = uplink_close; else event_add_once ("reconn", reconn, NULL, me.recontime); } void uplink_cleanup () { while (!uplinks.empty ()) uplink_delete (uplinks.back ()); } /* * uplink_close() * * inputs: * connection pointer of current uplink * triggered by callback close_handler * * outputs: * none * * side effects: * reconnection is scheduled * uplink marked dead * uplink deleted if it had been removed from configuration */ static void uplink_close (connection_t *cptr) { event_add_once ("reconn", reconn, NULL, me.recontime); me.connected = false; if (curr_uplink->flags & UPF_ILLEGAL) { slog (LG_INFO, "uplink_close(): %s was removed from configuration, deleting", curr_uplink->name); uplink_delete (curr_uplink); if (uplinks.empty ()) { slog (LG_ERROR, "uplink_close(): last uplink deleted, exiting."); exit (EXIT_FAILURE); } curr_uplink = uplinks.front (); } curr_uplink->conn = NULL; slog (LG_DEBUG, "uplink_close(): ----------------------- clearing -----------------------"); /* we have to kill everything. * we do not clear users here because when you delete a server, * it deletes its users */ if (me.actual != NULL) server_delete (me.actual); me.actual = NULL; /* remove all the channels left */ foreach (channel_pair &cp, chanlist) channel_delete (cp.second); /* this leaves me.me and all users on it (i.e. services) */ slog (LG_DEBUG, "uplink_close(): ------------------------- done -------------------------"); }