diff options
author | Adam <Adam@anope.org> | 2012-11-22 00:50:33 -0500 |
---|---|---|
committer | Adam <Adam@anope.org> | 2012-11-22 00:50:33 -0500 |
commit | d33a0f75a5c0c584fbb7cc0076da36d494f39494 (patch) | |
tree | 7b2274cc833c793c0f5595660cbd4d715de52ffd /src/uplink.cpp | |
parent | 368d469631763e9c8bf399980d0ac7c5b5664d39 (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.cpp | 204 |
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(); + } +} |