anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
uplink.cpp (6021B)
1 /* 2 * 3 * (C) 2003-2022 Anope Team 4 * Contact us at team@anope.org 5 * 6 * Please read COPYING and README for further details. 7 * 8 * Based on the original code of Epona by Lara. 9 * Based on the original code of Services by Andy Church. 10 */ 11 12 #include "uplink.h" 13 #include "logger.h" 14 #include "config.h" 15 #include "protocol.h" 16 #include "servers.h" 17 18 UplinkSocket *UplinkSock = NULL; 19 20 class ReconnectTimer : public Timer 21 { 22 public: 23 ReconnectTimer(int wait) : Timer(wait) { } 24 25 void Tick(time_t) 26 { 27 try 28 { 29 Uplink::Connect(); 30 } 31 catch (const SocketException &ex) 32 { 33 Log(LOG_TERMINAL) << "Unable to connect to uplink #" << (Anope::CurrentUplink + 1) << " (" << Config->Uplinks[Anope::CurrentUplink].host << ":" << Config->Uplinks[Anope::CurrentUplink].port << "): " << ex.GetReason(); 34 } 35 } 36 }; 37 38 void Uplink::Connect() 39 { 40 if (Config->Uplinks.empty()) 41 { 42 Log() << "Warning: There are no configured uplinks."; 43 return; 44 } 45 46 if (static_cast<unsigned>(++Anope::CurrentUplink) >= Config->Uplinks.size()) 47 Anope::CurrentUplink = 0; 48 49 Configuration::Uplink &u = Config->Uplinks[Anope::CurrentUplink]; 50 51 new UplinkSocket(); 52 if (!Config->GetBlock("serverinfo")->Get<const Anope::string>("localhost").empty()) 53 UplinkSock->Bind(Config->GetBlock("serverinfo")->Get<const Anope::string>("localhost")); 54 FOREACH_MOD(OnPreServerConnect, ()); 55 Anope::string ip = Anope::Resolve(u.host, u.ipv6 ? AF_INET6 : AF_INET); 56 Log(LOG_TERMINAL) << "Attempting to connect to uplink #" << (Anope::CurrentUplink + 1) << " " << u.host << " (" << ip << '/' << u.port << ") with protocol " << IRCD->GetProtocolName(); 57 UplinkSock->Connect(ip, u.port); 58 } 59 60 UplinkSocket::UplinkSocket() : Socket(-1, Config->Uplinks[Anope::CurrentUplink].ipv6), ConnectionSocket(), BufferedSocket() 61 { 62 error = false; 63 UplinkSock = this; 64 } 65 66 UplinkSocket::~UplinkSocket() 67 { 68 if (!error && !Anope::Quitting) 69 { 70 this->OnError(""); 71 Module *protocol = ModuleManager::FindFirstOf(PROTOCOL); 72 if (protocol && !protocol->name.find("inspircd")) 73 Log(LOG_TERMINAL) << "Check that you have loaded m_spanningtree.so on InspIRCd, and are not connecting Anope to an SSL enabled port without configuring SSL in Anope (or vice versa)"; 74 else 75 Log(LOG_TERMINAL) << "Check that you are not connecting Anope to an SSL enabled port without configuring SSL in Anope (or vice versa)"; 76 } 77 78 if (IRCD && Servers::GetUplink() && Servers::GetUplink()->IsSynced()) 79 { 80 FOREACH_MOD(OnServerDisconnect, ()); 81 82 for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) 83 { 84 User *u = it->second; 85 86 if (u->server == Me) 87 { 88 /* Don't use quitmsg here, it may contain information you don't want people to see */ 89 IRCD->SendQuit(u, "Shutting down"); 90 BotInfo* bi = BotInfo::Find(u->GetUID()); 91 if (bi != NULL) 92 bi->introduced = false; 93 } 94 } 95 96 IRCD->SendSquit(Me, Anope::QuitReason); 97 } 98 99 for (unsigned i = Me->GetLinks().size(); i > 0; --i) 100 if (!Me->GetLinks()[i - 1]->IsJuped()) 101 Me->GetLinks()[i - 1]->Delete(Me->GetName() + " " + Me->GetLinks()[i - 1]->GetName()); 102 103 this->ProcessWrite(); // Write out the last bit 104 UplinkSock = NULL; 105 106 Me->Unsync(); 107 108 if (Anope::AtTerm()) 109 { 110 if (static_cast<unsigned>(Anope::CurrentUplink + 1) == Config->Uplinks.size()) 111 { 112 Anope::QuitReason = "Unable to connect to any uplink"; 113 Anope::Quitting = true; 114 Anope::ReturnValue = -1; 115 } 116 else 117 { 118 new ReconnectTimer(1); 119 } 120 } 121 else if (!Anope::Quitting) 122 { 123 time_t retry = Config->GetBlock("options")->Get<time_t>("retrywait"); 124 125 Log() << "Disconnected, retrying in " << retry << " seconds"; 126 new ReconnectTimer(retry); 127 } 128 } 129 130 bool UplinkSocket::ProcessRead() 131 { 132 bool b = BufferedSocket::ProcessRead(); 133 for (Anope::string buf; (buf = this->GetLine()).empty() == false;) 134 { 135 Anope::Process(buf); 136 User::QuitUsers(); 137 Channel::DeleteChannels(); 138 } 139 return b; 140 } 141 142 void UplinkSocket::OnConnect() 143 { 144 Log(LOG_TERMINAL) << "Successfully connected to uplink #" << (Anope::CurrentUplink + 1) << " " << Config->Uplinks[Anope::CurrentUplink].host << ":" << Config->Uplinks[Anope::CurrentUplink].port; 145 IRCD->SendConnect(); 146 FOREACH_MOD(OnServerConnect, ()); 147 } 148 149 void UplinkSocket::OnError(const Anope::string &err) 150 { 151 Anope::string what = !this->flags[SF_CONNECTED] ? "Unable to connect to" : "Lost connection from"; 152 Log(LOG_TERMINAL) << what << " uplink #" << (Anope::CurrentUplink + 1) << " (" << Config->Uplinks[Anope::CurrentUplink].host << ":" << Config->Uplinks[Anope::CurrentUplink].port << ")" << (!err.empty() ? (": " + err) : ""); 153 error |= !err.empty(); 154 } 155 156 UplinkSocket::Message::Message() : source(Me) 157 { 158 } 159 160 UplinkSocket::Message::Message(const MessageSource &src) : source(src) 161 { 162 } 163 164 UplinkSocket::Message::~Message() 165 { 166 Anope::string message_source; 167 168 if (this->source.GetServer() != NULL) 169 { 170 const Server *s = this->source.GetServer(); 171 172 if (s != Me && !s->IsJuped()) 173 { 174 Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << s->GetName() << " who is not from me?"; 175 return; 176 } 177 178 message_source = s->GetSID(); 179 } 180 else if (this->source.GetUser() != NULL) 181 { 182 const User *u = this->source.GetUser(); 183 184 if (u->server != Me && !u->server->IsJuped()) 185 { 186 Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << u->nick << " who is not from me?"; 187 return; 188 } 189 190 const BotInfo *bi = this->source.GetBot(); 191 if (bi != NULL && bi->introduced == false) 192 { 193 Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << bi->nick << " when not introduced"; 194 return; 195 } 196 197 message_source = u->GetUID(); 198 } 199 200 if (!UplinkSock) 201 { 202 if (!message_source.empty()) 203 Log(LOG_DEBUG) << "Attempted to send \"" << message_source << " " << this->buffer.str() << "\" with UplinkSock NULL"; 204 else 205 Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" with UplinkSock NULL"; 206 return; 207 } 208 209 Anope::string sent = IRCD->Format(message_source, this->buffer.str()); 210 UplinkSock->Write(sent); 211 Log(LOG_RAWIO) << "Sent: " << sent; 212 }