Anope IRC Services  Version 2.0
uplink.cpp
Go to the documentation of this file.
1 /*
2  *
3  * (C) 2003-2014 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 
13 #include "uplink.h"
14 #include "logger.h"
15 #include "config.h"
16 #include "protocol.h"
17 #include "servers.h"
18 
20 
21 class ReconnectTimer : public Timer
22 {
23  public:
24  ReconnectTimer(int wait) : Timer(wait) { }
25 
26  void Tick(time_t)
27  {
28  try
29  {
31  }
32  catch (const SocketException &ex)
33  {
34  Log(LOG_TERMINAL) << "Unable to connect to uplink #" << (Anope::CurrentUplink + 1) << " (" << Config->Uplinks[Anope::CurrentUplink].host << ":" << Config->Uplinks[Anope::CurrentUplink].port << "): " << ex.GetReason();
35  }
36  }
37 };
38 
40 {
41  if (Config->Uplinks.empty())
42  {
43  Log() << "Warning: There are no configured uplinks.";
44  return;
45  }
46 
47  if (static_cast<unsigned>(++Anope::CurrentUplink) >= Config->Uplinks.size())
49 
51 
52  new UplinkSocket();
53  if (!Config->GetBlock("serverinfo")->Get<const Anope::string>("localhost").empty())
54  UplinkSock->Bind(Config->GetBlock("serverinfo")->Get<const Anope::string>("localhost"));
55  FOREACH_MOD(OnPreServerConnect, ());
56  Anope::string ip = Anope::Resolve(u.host, u.ipv6 ? AF_INET6 : AF_INET);
57  Log(LOG_TERMINAL) << "Attempting to connect to uplink #" << (Anope::CurrentUplink + 1) << " " << u.host << " (" << ip << "), port " << u.port;
58  UplinkSock->Connect(ip, u.port);
59 }
60 
62 {
63  UplinkSock = this;
64 }
65 
67 {
68  if (IRCD && Servers::GetUplink() && Servers::GetUplink()->IsSynced())
69  {
70  FOREACH_MOD(OnServerDisconnect, ());
71 
72  for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
73  {
74  User *u = it->second;
75 
76  if (u->server == Me)
77  {
78  /* Don't use quitmsg here, it may contain information you don't want people to see */
79  IRCD->SendQuit(u, "Shutting down");
80  BotInfo* bi = BotInfo::Find(u->GetUID());
81  if (bi != NULL)
82  bi->introduced = false;
83  }
84  }
85 
87 
88  this->ProcessWrite(); // Write out the last bit
89  }
90 
91  for (unsigned i = Me->GetLinks().size(); i > 0; --i)
92  if (!Me->GetLinks()[i - 1]->IsJuped())
93  Me->GetLinks()[i - 1]->Delete(Me->GetName() + " " + Me->GetLinks()[i - 1]->GetName());
94 
95  UplinkSock = NULL;
96 
97  Me->Unsync();
98 
99  if (Anope::AtTerm())
100  {
101  if (static_cast<unsigned>(Anope::CurrentUplink + 1) == Config->Uplinks.size())
102  {
103  Anope::QuitReason = "Unable to connect to any uplink";
104  Anope::Quitting = true;
105  Anope::ReturnValue = -1;
106  }
107  else
108  {
109  new ReconnectTimer(1);
110  }
111  }
112  else if (!Anope::Quitting)
113  {
114  time_t retry = Config->GetBlock("options")->Get<time_t>("retrywait");
115 
116  Log() << "Disconnected, retrying in " << retry << " seconds";
117  new ReconnectTimer(retry);
118  }
119 }
120 
122 {
123  bool b = BufferedSocket::ProcessRead();
124  for (Anope::string buf; (buf = this->GetLine()).empty() == false;)
125  {
126  Anope::Process(buf);
127  User::QuitUsers();
128  }
129  return b;
130 }
131 
133 {
134  Log(LOG_TERMINAL) << "Successfully connected to uplink #" << (Anope::CurrentUplink + 1) << " " << Config->Uplinks[Anope::CurrentUplink].host << ":" << Config->Uplinks[Anope::CurrentUplink].port;
135  IRCD->SendConnect();
136  FOREACH_MOD(OnServerConnect, ());
137 }
138 
140 {
141  Anope::string what = !this->flags[SF_CONNECTED] ? "Unable to connect to" : "Lost connection from";
142  Log(LOG_TERMINAL) << what << " uplink #" << (Anope::CurrentUplink + 1) << " (" << Config->Uplinks[Anope::CurrentUplink].host << ":" << Config->Uplinks[Anope::CurrentUplink].port << ")" << (!error.empty() ? (": " + error) : "");
143 }
144 
146 {
147 }
148 
150 {
151 }
152 
154 {
155  Anope::string message_source;
156 
157  if (this->source.GetServer() != NULL)
158  {
159  const Server *s = this->source.GetServer();
160 
161  if (s != Me && !s->IsJuped())
162  {
163  Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << s->GetName() << " who is not from me?";
164  return;
165  }
166 
167  message_source = s->GetSID();
168  }
169  else if (this->source.GetUser() != NULL)
170  {
171  const User *u = this->source.GetUser();
172 
173  if (u->server != Me && !u->server->IsJuped())
174  {
175  Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << u->nick << " who is not from me?";
176  return;
177  }
178 
179  const BotInfo *bi = this->source.GetBot();
180  if (bi != NULL && bi->introduced == false)
181  {
182  Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << bi->nick << " when not introduced";
183  return;
184  }
185 
186  message_source = u->GetUID();
187  }
188 
189  if (!UplinkSock)
190  {
191  if (!message_source.empty())
192  Log(LOG_DEBUG) << "Attempted to send \"" << message_source << " " << this->buffer.str() << "\" with UplinkSock NULL";
193  else
194  Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" with UplinkSock NULL";
195  return;
196  }
197 
198  Anope::string sent = IRCD->Format(message_source, this->buffer.str());
199  UplinkSock->Write(sent);
200  Log(LOG_RAWIO) << "Sent: " << sent;
201 }
Definition: bots.h:24
static void QuitUsers()
Definition: users.cpp:834
Definition: servers.h:42
std::bitset< SF_SIZE > flags
Definition: sockets.h:203
Definition: timers.h:18
std::string & str()
Definition: anope.h:119
const Anope::string GetLine()
void Tick(time_t)
Definition: uplink.cpp:26
const Anope::string & GetSID() const
Definition: servers.cpp:203
int ReturnValue
Definition: main.cpp:32
Definition: users.h:34
bool AtTerm()
Definition: init.cpp:98
bool introduced
Definition: bots.h:39
bool IsJuped() const
Definition: servers.cpp:319
ReconnectTimer(int wait)
Definition: uplink.cpp:24
virtual void SendQuit(User *u, const char *fmt,...)
Definition: protocol.cpp:252
CoreExport Server * GetUplink()
Definition: servers.cpp:355
#define FOREACH_MOD(ename, args)
Definition: modules.h:62
void Connect(const Anope::string &TargetHost, int Port)
bool ProcessRead() anope_override
CoreExport bool Quitting
Definition: main.cpp:34
Definition: Config.cs:26
const Anope::string & GetUID() const
Definition: users.cpp:230
virtual void Write(const char *buffer, size_t l)
bool empty() const
Definition: anope.h:126
bool ProcessWrite() anope_override
virtual void SendSquit(Server *, const Anope::string &message)
Definition: protocol.cpp:314
CoreExport IRCDProto * IRCD
Definition: protocol.cpp:23
Server * server
Definition: users.h:77
const std::vector< Server * > & GetLinks() const
Definition: servers.cpp:216
CoreExport int CurrentUplink
Definition: main.cpp:43
virtual void SendConnect()=0
void Unsync()
Definition: servers.cpp:303
Anope::string nick
Definition: users.h:62
const Anope::string & GetName() const
Definition: servers.cpp:175
Anope::string Resolve(const Anope::string &host, int type)
Definition: misc.cpp:730
void Bind(const Anope::string &ip, int port=0)
Definition: sockets.cpp:493
virtual Anope::string Format(const Anope::string &source, const Anope::string &message)
Definition: process.cpp:103
CoreExport Server * Me
Definition: servers.cpp:24
virtual const Anope::string & GetReason() const
Definition: anope.h:672
CoreExport user_map UserListByNick
Definition: users.cpp:28
Definition: logger.h:53
void Process(const Anope::string &)
Definition: process.cpp:19
CoreExport Anope::string QuitReason
Definition: main.cpp:36
static BotInfo * Find(const Anope::string &nick, bool nick_only=false)
Definition: bots.cpp:249
Definition: anope.h:20