00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "inspircd.h"
00015 #include "commands/cmd_whois.h"
00016 #include "commands/cmd_stats.h"
00017 #include "socket.h"
00018 #include "xline.h"
00019 #include "transport.h"
00020 #include "m_hash.h"
00021 #include "socketengine.h"
00022
00023 #include "m_spanningtree/main.h"
00024 #include "m_spanningtree/utils.h"
00025 #include "m_spanningtree/treeserver.h"
00026 #include "m_spanningtree/link.h"
00027 #include "m_spanningtree/treesocket.h"
00028 #include "m_spanningtree/resolvers.h"
00029 #include "m_spanningtree/handshaketimer.h"
00030
00031
00032
00033
00039 TreeSocket::TreeSocket(SpanningTreeUtilities* Util, InspIRCd* SI, std::string shost, int iport, unsigned long maxtime, const std::string &ServerName, const std::string &bindto, Module* HookMod)
00040 : BufferedSocket(SI, shost, iport, maxtime, bindto), Utils(Util), Hook(HookMod)
00041 {
00042 myhost = ServerName;
00043 theirchallenge.clear();
00044 ourchallenge.clear();
00045 this->LinkState = CONNECTING;
00046 Utils->timeoutlist[this] = std::pair<std::string, int>(ServerName, maxtime);
00047 if (Hook)
00048 BufferedSocketHookRequest(this, (Module*)Utils->Creator, Hook).Send();
00049 }
00050
00055 TreeSocket::TreeSocket(SpanningTreeUtilities* Util, InspIRCd* SI, int newfd, char* ip, Module* HookMod)
00056 : BufferedSocket(SI, newfd, ip), Utils(Util), Hook(HookMod)
00057 {
00058 this->LinkState = WAIT_AUTH_1;
00059 theirchallenge.clear();
00060 ourchallenge.clear();
00061 sentcapab = false;
00062
00063
00064
00065 if (Hook)
00066 BufferedSocketHookRequest(this, (Module*)Utils->Creator, Hook).Send();
00067
00068 ServerInstance->Timers->AddTimer(new HandshakeTimer(ServerInstance, this, &(Utils->LinkBlocks[0]), this->Utils, 1));
00069
00070
00071 Utils->timeoutlist[this] = std::pair<std::string, int>("<unknown>", 30);
00072 }
00073
00074 ServerState TreeSocket::GetLinkState()
00075 {
00076 return this->LinkState;
00077 }
00078
00079 Module* TreeSocket::GetHook()
00080 {
00081 return this->Hook;
00082 }
00083
00084 TreeSocket::~TreeSocket()
00085 {
00086 if (Hook)
00087 BufferedSocketUnhookRequest(this, (Module*)Utils->Creator, Hook).Send();
00088 Utils->timeoutlist.erase(this);
00089 }
00090
00097 bool TreeSocket::OnConnected()
00098 {
00099 if (this->LinkState == CONNECTING)
00100 {
00101
00102 for (std::vector<Link>::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++)
00103 {
00104 if (x->Name == this->myhost)
00105 {
00106 Utils->Creator->RemoteMessage(NULL,"Connection to \2%s\2[%s] started.", myhost.c_str(), (x->HiddenFromStats ? "<hidden>" : this->GetIP().c_str()));
00107 if (Hook)
00108 {
00109 BufferedSocketHookRequest(this, (Module*)Utils->Creator, Hook).Send();
00110 Utils->Creator->RemoteMessage(NULL,"Connection to \2%s\2[%s] using transport \2%s\2", myhost.c_str(), (x->HiddenFromStats ? "<hidden>" : this->GetIP().c_str()),
00111 x->Hook.c_str());
00112 }
00113 this->OutboundPass = x->SendPass;
00114 sentcapab = false;
00115
00116
00117 if (this->GetHook())
00118 ServerInstance->Timers->AddTimer(new HandshakeTimer(ServerInstance, this, &(*x), this->Utils, 1));
00119 else
00120 this->SendCapabilities();
00121
00122 return true;
00123 }
00124 }
00125 }
00126
00127
00128
00129
00130
00131 this->Utils->Creator->RemoteMessage(NULL,"Connection to \2%s\2 lost link tag(!)", myhost.c_str());
00132 return true;
00133 }
00134
00135 void TreeSocket::OnError(BufferedSocketError e)
00136 {
00137 Link* MyLink;
00138
00139 switch (e)
00140 {
00141 case I_ERR_CONNECT:
00142 Utils->Creator->RemoteMessage(NULL,"Connection failed: Connection to \002%s\002 refused", myhost.c_str());
00143 MyLink = Utils->FindLink(myhost);
00144 if (MyLink)
00145 Utils->DoFailOver(MyLink);
00146 break;
00147 case I_ERR_SOCKET:
00148 Utils->Creator->RemoteMessage(NULL,"Connection failed: Could not create socket (%s)", strerror(errno));
00149 break;
00150 case I_ERR_BIND:
00151 Utils->Creator->RemoteMessage(NULL,"Connection failed: Error binding socket to address or port (%s)", strerror(errno));
00152 break;
00153 case I_ERR_WRITE:
00154 Utils->Creator->RemoteMessage(NULL,"Connection failed: I/O error on connection (%s)", errno ? strerror(errno) : "Connection closed unexpectedly");
00155 break;
00156 case I_ERR_NOMOREFDS:
00157 Utils->Creator->RemoteMessage(NULL,"Connection failed: Operating system is out of file descriptors!");
00158 break;
00159 default:
00160 if ((errno) && (errno != EINPROGRESS) && (errno != EAGAIN))
00161 Utils->Creator->RemoteMessage(NULL,"Connection to \002%s\002 failed with OS error: %s", myhost.c_str(), strerror(errno));
00162 break;
00163 }
00164 }
00165
00166 int TreeSocket::OnDisconnect()
00167 {
00168
00169
00170
00171 return true;
00172 }
00173
00174 void TreeSocket::SendError(const std::string &errormessage)
00175 {
00176
00177 Utils->Creator->RemoteMessage(NULL, "Sent \2ERROR\2 to %s: %s", (this->InboundServerName.empty() ? this->GetIP().c_str() : this->InboundServerName.c_str()), errormessage.c_str());
00178 this->WriteLine("ERROR :"+errormessage);
00179
00180 this->FlushWriteBuffer();
00181 }
00182
00189 void TreeSocket::SquitServer(std::string &from, TreeServer* Current)
00190 {
00191
00192
00193
00194
00195 for (unsigned int q = 0; q < Current->ChildCount(); q++)
00196 {
00197 TreeServer* recursive_server = Current->GetChild(q);
00198 this->SquitServer(from,recursive_server);
00199 }
00200
00201 num_lost_servers++;
00202 num_lost_users += Current->QuitUsers(from);
00203 }
00204
00209 void TreeSocket::Squit(TreeServer* Current, const std::string &reason)
00210 {
00211 if ((Current) && (Current != Utils->TreeRoot))
00212 {
00213 Event rmode((char*)Current->GetName().c_str(), (Module*)Utils->Creator, "lost_server");
00214 rmode.Send(ServerInstance);
00215
00216 std::deque<std::string> params;
00217 params.push_back(Current->GetName());
00218 params.push_back(":"+reason);
00219 Utils->DoOneToAllButSender(Current->GetParent()->GetName(),"SQUIT",params,Current->GetName());
00220 if (Current->GetParent() == Utils->TreeRoot)
00221 {
00222 this->ServerInstance->SNO->WriteToSnoMask('l',"Server \002"+Current->GetName()+"\002 split: "+reason);
00223 }
00224 else
00225 {
00226 this->ServerInstance->SNO->WriteToSnoMask('l',"Server \002"+Current->GetName()+"\002 split from server \002"+Current->GetParent()->GetName()+"\002 with reason: "+reason);
00227 }
00228 num_lost_servers = 0;
00229 num_lost_users = 0;
00230 std::string from = Current->GetParent()->GetName()+" "+Current->GetName();
00231 SquitServer(from, Current);
00232 Current->Tidy();
00233 Current->GetParent()->DelChild(Current);
00234 delete Current;
00235 this->ServerInstance->SNO->WriteToSnoMask('l',"Netsplit complete, lost \002%d\002 users on \002%d\002 servers.", num_lost_users, num_lost_servers);
00236 }
00237 else
00238 ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Squit from unknown server");
00239 }
00240
00249 bool TreeSocket::OnDataReady()
00250 {
00251 const char* data = this->Read();
00252
00253 if (data && *data)
00254 {
00255 this->in_buffer.append(data);
00256
00257
00258
00259 while (in_buffer.find("\n") != std::string::npos)
00260 {
00261 std::string ret = in_buffer.substr(0,in_buffer.find("\n")-1);
00262 in_buffer = in_buffer.substr(in_buffer.find("\n")+1,in_buffer.length()-in_buffer.find("\n"));
00263
00264
00265
00266
00267 if (ret.find("\r") != std::string::npos)
00268 ret = in_buffer.substr(0,in_buffer.find("\r")-1);
00269
00270
00271
00272 if (!this->ProcessLine(ret))
00273 {
00274 return false;
00275 }
00276 }
00277 return true;
00278 }
00279
00280
00281
00282 return (data && !*data);
00283 }