summaryrefslogtreecommitdiff
path: root/src/uplink.cpp
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2012-11-22 00:50:33 -0500
committerAdam <Adam@anope.org>2012-11-22 00:50:33 -0500
commitd33a0f75a5c0c584fbb7cc0076da36d494f39494 (patch)
tree7b2274cc833c793c0f5595660cbd4d715de52ffd /src/uplink.cpp
parent368d469631763e9c8bf399980d0ac7c5b5664d39 (diff)
Pretty large coding style cleanup, in source doc
cleanup, and allow protocol mods to depend on each other
Diffstat (limited to 'src/uplink.cpp')
-rw-r--r--src/uplink.cpp204
1 files changed, 204 insertions, 0 deletions
diff --git a/src/uplink.cpp b/src/uplink.cpp
new file mode 100644
index 000000000..ac77672b2
--- /dev/null
+++ b/src/uplink.cpp
@@ -0,0 +1,204 @@
+/*
+ *
+ * (C) 2003-2012 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ *
+ * Based on the original code of Epona by Lara.
+ * Based on the original code of Services by Andy Church.
+ *
+ */
+
+#include "uplink.h"
+#include "logger.h"
+#include "config.h"
+#include "protocol.h"
+#include "servers.h"
+#include "dns.h"
+
+UplinkSocket *UplinkSock = NULL;
+
+class ReconnectTimer : public Timer
+{
+ public:
+ ReconnectTimer(int wait) : Timer(wait) { }
+
+ void Tick(time_t)
+ {
+ try
+ {
+ Uplink::Connect();
+ }
+ catch (const SocketException &ex)
+ {
+ Log(LOG_TERMINAL) << "Unable to connect to uplink #" << (Anope::CurrentUplink + 1) << " (" << Config->Uplinks[Anope::CurrentUplink]->host << ":" << Config->Uplinks[Anope::CurrentUplink]->port << "): " << ex.GetReason();
+ }
+ }
+};
+
+void Uplink::Connect()
+{
+ if (static_cast<unsigned>(++Anope::CurrentUplink) >= Config->Uplinks.size())
+ Anope::CurrentUplink = 0;
+
+ ServerConfig::Uplink *u = Config->Uplinks[Anope::CurrentUplink];
+
+ new UplinkSocket();
+ if (!Config->LocalHost.empty())
+ UplinkSock->Bind(Config->LocalHost);
+ FOREACH_MOD(I_OnPreServerConnect, OnPreServerConnect());
+ DNS::Query rep = DNS::Manager::BlockingQuery(u->host, u->ipv6 ? DNS::QUERY_AAAA : DNS::QUERY_A);
+ Anope::string reply_ip = !rep.answers.empty() ? rep.answers.front().rdata : u->host;
+ Log(LOG_TERMINAL) << "Attempting to connect to uplink #" << (Anope::CurrentUplink + 1) << " " << u->host << " (" << reply_ip << "), port " << u->port;
+ UplinkSock->Connect(reply_ip, u->port);
+}
+
+
+UplinkSocket::UplinkSocket() : Socket(-1, Config->Uplinks[Anope::CurrentUplink]->ipv6), ConnectionSocket(), BufferedSocket()
+{
+ UplinkSock = this;
+}
+
+UplinkSocket::~UplinkSocket()
+{
+ if (IRCD && Servers::GetUplink() && Servers::GetUplink()->IsSynced())
+ {
+ FOREACH_MOD(I_OnServerDisconnect, OnServerDisconnect());
+
+ for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
+ {
+ User *u = it->second;
+
+ if (u->server == Me)
+ {
+ /* Don't use quitmsg here, it may contain information you don't want people to see */
+ IRCD->SendQuit(u, "Shutting down");
+ BotInfo* bi = BotInfo::Find(u->nick);
+ if (bi != NULL)
+ bi->introduced = false;
+ }
+ }
+
+ IRCD->SendSquit(Me, Anope::QuitReason);
+
+ this->ProcessWrite(); // Write out the last bit
+ }
+
+ if (Me)
+ for (unsigned i = Me->GetLinks().size(); i > 0; --i)
+ if (!Me->GetLinks()[i - 1]->HasFlag(SERVER_JUPED))
+ Me->GetLinks()[i - 1]->Delete(Me->GetName() + " " + Me->GetLinks()[i - 1]->GetName());
+
+ UplinkSock = NULL;
+
+ Me->SetFlag(SERVER_SYNCING);
+
+ if (Anope::AtTerm())
+ {
+ if (static_cast<unsigned>(Anope::CurrentUplink + 1) == Config->Uplinks.size())
+ {
+ Anope::QuitReason = "Unable to connect to any uplink";
+ Anope::Quitting = true;
+ Anope::ReturnValue = -1;
+ }
+ else
+ {
+ new ReconnectTimer(1);
+ }
+ }
+ else if (!Anope::Quitting)
+ {
+ int retry = Config->RetryWait;
+ if (retry <= 0)
+ retry = 60;
+
+ Log() << "Disconnected, retrying in " << retry << " seconds";
+ new ReconnectTimer(retry);
+ }
+}
+
+bool UplinkSocket::Read(const Anope::string &buf)
+{
+ Anope::Process(buf);
+ return true;
+}
+
+void UplinkSocket::OnConnect()
+{
+ Log(LOG_TERMINAL) << "Successfully connected to uplink #" << (Anope::CurrentUplink + 1) << " " << Config->Uplinks[Anope::CurrentUplink]->host << ":" << Config->Uplinks[Anope::CurrentUplink]->port;
+ IRCD->SendConnect();
+ FOREACH_MOD(I_OnServerConnect, OnServerConnect());
+}
+
+void UplinkSocket::OnError(const Anope::string &error)
+{
+ Log(LOG_TERMINAL) << "Unable to connect to uplink #" << (Anope::CurrentUplink + 1) << " (" << Config->Uplinks[Anope::CurrentUplink]->host << ":" << Config->Uplinks[Anope::CurrentUplink]->port << ")" << (!error.empty() ? (": " + error) : "");
+}
+
+UplinkSocket::Message::Message() : server(NULL), user(NULL)
+{
+}
+
+UplinkSocket::Message::Message(const Server *s) : server(s), user(NULL)
+{
+}
+
+UplinkSocket::Message::Message(const User *u) : server(NULL), user(u)
+{
+ if (!u)
+ server = Me;
+}
+
+UplinkSocket::Message::~Message()
+{
+ Anope::string message_source = "";
+
+ if (this->server != NULL)
+ {
+ if (this->server != Me && !this->server->HasFlag(SERVER_JUPED))
+ {
+ Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << this->server->GetName() << " who is not from me?";
+ return;
+ }
+
+ message_source = this->server->GetSID();
+ }
+ else if (this->user != NULL)
+ {
+ if (this->user->server != Me && !this->user->server->HasFlag(SERVER_JUPED))
+ {
+ Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << this->user->nick << " who is not from me?";
+ return;
+ }
+
+ const BotInfo *bi = BotInfo::Find(this->user->nick);
+ if (bi != NULL && bi->introduced == false)
+ {
+ Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << bi->nick << " when not introduced";
+ return;
+ }
+
+ message_source = this->user->GetUID();
+ }
+
+ if (!UplinkSock)
+ {
+ if (!message_source.empty())
+ Log(LOG_DEBUG) << "Attempted to send \"" << message_source << " " << this->buffer.str() << "\" with UplinkSock NULL";
+ else
+ Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" with UplinkSock NULL";
+ return;
+ }
+
+ if (!message_source.empty())
+ {
+ UplinkSock->Write(":" + message_source + " " + this->buffer.str());
+ Log(LOG_RAWIO) << "Sent: :" << message_source << " " << this->buffer.str();
+ }
+ else
+ {
+ UplinkSock->Write(this->buffer.str());
+ Log(LOG_RAWIO) << "Sent: " << this->buffer.str();
+ }
+}