The InspIRCd Project
Home | Developers | Wiki | Forums | Bug Tracker | SVN | Download
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

treesocket2.cpp

Go to the documentation of this file.
00001 /*       +------------------------------------+
00002  *       | Inspire Internet Relay Chat Daemon |
00003  *       +------------------------------------+
00004  *
00005  *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
00006  * See: http://www.inspircd.org/wiki/index.php/Credits
00007  *
00008  * This program is free but copyrighted software; see
00009  *            the file COPYING for details.
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 "socketengine.h"
00021 
00022 #include "m_spanningtree/main.h"
00023 #include "m_spanningtree/utils.h"
00024 #include "m_spanningtree/treeserver.h"
00025 #include "m_spanningtree/link.h"
00026 #include "m_spanningtree/treesocket.h"
00027 #include "m_spanningtree/resolvers.h"
00028 #include "m_spanningtree/handshaketimer.h"
00029 
00030 /* $ModDep: m_spanningtree/resolvers.h m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/link.h m_spanningtree/treesocket.h m_spanningtree/handshaketimer.h */
00031 
00032 void TreeSocket::WriteLine(std::string line)
00033 {
00034         Instance->Logs->Log("m_spanningtree",DEBUG, "S[%d] O %s", this->GetFd(), line.c_str());
00035         line.append("\r\n");
00036         this->Write(line);
00037 }
00038 
00039 
00040 /* Handle ERROR command */
00041 bool TreeSocket::Error(std::deque<std::string> &params)
00042 {
00043         if (params.size() < 1)
00044                 return false;
00045         this->Instance->SNO->WriteToSnoMask('l',"ERROR from %s: %s",(!InboundServerName.empty() ? InboundServerName.c_str() : myhost.c_str()),params[0].c_str());
00046         /* we will return false to cause the socket to close. */
00047         return false;
00048 }
00049 
00050 void TreeSocket::Split(const std::string &line, std::deque<std::string> &n)
00051 {
00052         n.clear();
00053         irc::tokenstream tokens(line);
00054         std::string param;
00055         while (tokens.GetToken(param))
00056         {
00057                 n.push_back(param);
00058         }
00059         return;
00060 }
00061 
00062 bool TreeSocket::ProcessLine(std::string &line)
00063 {
00064         std::deque<std::string> params;
00065         irc::string command;
00066         std::string prefix;
00067 
00068         line = line.substr(0, line.find_first_of("\r\n"));
00069 
00070         if (line.empty())
00071                 return true;
00072 
00073         Instance->Logs->Log("m_spanningtree",DEBUG, "S[%d] I %s", this->GetFd(), line.c_str());
00074 
00075         this->Split(line.c_str(),params);
00076 
00077         if (params.empty())
00078                 return true;
00079 
00080         if ((params[0][0] == ':') && (params.size() > 1))
00081         {
00082                 prefix = params[0].substr(1);
00083                 params.pop_front();
00084 
00085                 if (prefix.empty())
00086                 {
00087                         this->SendError("BUG (?) Empty prefix recieved.");
00088                         return false;
00089                 }
00090         }
00091 
00092         command = params[0].c_str();
00093         params.pop_front();
00094 
00095         switch (this->LinkState)
00096         {
00097                 TreeServer* Node;
00098 
00099                 case WAIT_AUTH_1:
00100                         /*
00101                          * State WAIT_AUTH_1:
00102                          *  Waiting for SERVER command from remote server. Server initiating
00103                          *  the connection sends the first SERVER command, listening server
00104                          *  replies with theirs if its happy, then if the initiator is happy,
00105                          *  it starts to send its net sync, which starts the merge, otherwise
00106                          *  it sends an ERROR.
00107                          */
00108                         if (command == "PASS")
00109                         {
00110                                 /*
00111                                  * Ignore this silently. Some services packages insist on sending PASS, even
00112                                  * when it is not required (i.e. by us). We have to ignore this here, otherwise
00113                                  * as it's an unknown command (effectively), it will cause the connection to be
00114                                  * closed, which probably isn't what people want. -- w00t
00115                                  */
00116                         }
00117                         else if (command == "SERVER")
00118                         {
00119                                 return this->Inbound_Server(params);
00120                         }
00121                         else if (command == "ERROR")
00122                         {
00123                                 return this->Error(params);
00124                         }
00125                         else if (command == "USER")
00126                         {
00127                                 this->SendError("Client connections to this port are prohibited.");
00128                                 return false;
00129                         }
00130                         else if (command == "CAPAB")
00131                         {
00132                                 return this->Capab(params);
00133                         }
00134                         else
00135                         {
00136                                 // XXX ...wtf.
00137                                 irc::string error = "Invalid command in negotiation phase: " + command;
00138                                 this->SendError(assign(error));
00139                                 return false;
00140                         }
00141                 break;
00142                 case WAIT_AUTH_2:
00143                         /*
00144                          * State WAIT_AUTH_2:
00145                          *  We have sent SERVER to the other side of the connection. Now we're waiting for them to start BURST.
00146                          *  The other option at this stage of things, of course, is for them to close our connection thanks
00147                          *  to invalid credentials.. -- w
00148                          */
00149                         if (command == "SERVER")
00150                         {
00151                                 /*
00152                                  * Connection is either attempting to re-auth itself (stupid) or sending netburst without sending BURST.
00153                                  * Both of these aren't allowable, so block them here. -- w
00154                                  */
00155                                 this->SendError("You may not re-authenticate or commence netburst without sending BURST.");
00156                                 return true;
00157                         }
00158                         else if (command == "BURST")
00159                         {
00160                                 if (params.size())
00161                                 {
00162                                         time_t them = atoi(params[0].c_str());
00163                                         time_t delta = them - Instance->Time();
00164                                         if ((delta < -600) || (delta > 600))
00165                                         {
00166                                                 Instance->SNO->WriteToSnoMask('l',"\2ERROR\2: Your clocks are out by %d seconds (this is more than five minutes). Link aborted, \2PLEASE SYNC YOUR CLOCKS!\2",abs((long)delta));
00167                                                 SendError("Your clocks are out by "+ConvToStr(abs((long)delta))+" seconds (this is more than five minutes). Link aborted, PLEASE SYNC YOUR CLOCKS!");
00168                                                 return false;
00169                                         }
00170                                         else if ((delta < -30) || (delta > 30))
00171                                         {
00172                                                 Instance->SNO->WriteToSnoMask('l',"\2WARNING\2: Your clocks are out by %d seconds. Please consider synching your clocks.", abs((long)delta));
00173                                         }
00174                                 }
00175                                 this->LinkState = CONNECTED;
00176                                 Link* lnk = Utils->FindLink(InboundServerName);
00177 
00178                                 Node = new TreeServer(this->Utils, this->Instance, InboundServerName, InboundDescription, InboundSID, Utils->TreeRoot, this, lnk ? lnk->Hidden : false);
00179 
00180                                 if (Node->DuplicateID())
00181                                 {
00182                                         this->SendError("Server ID "+InboundSID+" already exists on the network!");
00183                                         this->Instance->SNO->WriteToSnoMask('l',"Server \2"+InboundServerName+"\2 being introduced from \2" + prefix + "\2 denied, server ID already exists on the network. Closing link.");
00184                                         return false;
00185                                 }
00186 
00187                                 Utils->TreeRoot->AddChild(Node);
00188                                 params.clear();
00189                                 params.push_back(InboundServerName);
00190                                 params.push_back("*");
00191                                 params.push_back("1");
00192                                 params.push_back(InboundSID);
00193                                 params.push_back(":"+InboundDescription);
00194                                 Utils->DoOneToAllButSender(Instance->Config->GetSID(),"SERVER",params,InboundServerName);
00195                                 Node->bursting = true;
00196                                 this->DoBurst(Node);
00197                         }
00198                         else if (command == "ERROR")
00199                         {
00200                                 return this->Error(params);
00201                         }
00202                         else if (command == "CAPAB")
00203                         {
00204                                 return this->Capab(params);
00205                         }
00206 
00207                 break;
00208                 case LISTENER:
00209                         /*
00210                          * This really shouldn't happen.
00211                          */
00212                         this->SendError("Internal error -- listening socket accepted its own descriptor!!!");
00213                         return false;
00214                 break;
00215                 case CONNECTING:
00216                         /*
00217                          * State CONNECTING:
00218                          *  We're connecting (OUTGOING) to another server. They are in state WAIT_AUTH_1 until they verify
00219                          *  our credentials, when they proceed into WAIT_AUTH_2 and send SERVER to us. We then send BURST
00220                          *  + our netburst, which will put them into CONNECTED state. -- w
00221                          */
00222                         if (command == "SERVER")
00223                         {
00224                                 // Our credentials have been accepted, send netburst. (this puts US into the CONNECTED state)
00225                                 return this->Outbound_Reply_Server(params);
00226                         }
00227                         else if (command == "ERROR")
00228                         {
00229                                 return this->Error(params);
00230                         }
00231                         else if (command == "CAPAB")
00232                         {
00233                                 return this->Capab(params);
00234                         }
00235                 break;
00236                 case CONNECTED:
00237                         /*
00238                         * State CONNECTED:
00239                          *  Credentials have been exchanged, we've gotten their 'BURST' (or sent ours).
00240                          *  Anything from here on should be accepted a little more reasonably.
00241                          */
00242                         if (!prefix.empty())
00243                         {
00244                                 /*
00245                                  * Check for fake direction here, and drop any instances that are found.
00246                                  * What is fake direction? Imagine the following server setup:
00247                                  *    0AA <-> 0AB <-> 0AC
00248                                  * Fake direction would be 0AC sending a message to 0AB claiming to be from
00249                                  * 0AA, or something similar. Basically, a message taking a path that *cannot*
00250                                  * be correct.
00251                                  *
00252                                  * When would this be seen?
00253                                  * Well, hopefully never. It could be caused by race conditions, bugs, or
00254                                  * "miscreant" servers, though, so let's check anyway. -- w
00255                                  */
00256                                 std::string direction = prefix;
00257 
00258                                 User *t = this->Instance->FindUUID(prefix);
00259                                 if (t)
00260                                 {
00261                                         direction = t->server;
00262                                 }
00263 
00264                                 TreeServer* route_back_again = Utils->BestRouteTo(direction);
00265                                 if ((!route_back_again) || (route_back_again->GetSocket() != this))
00266                                 {
00267                                         if (route_back_again)
00268                                                 Instance->Logs->Log("m_spanningtree",DEBUG,"Protocol violation: Fake direction in command '%s' from connection '%s'",line.c_str(),this->GetName().c_str());
00269                                         return true;
00270                                 }
00271                                 /* Fix by brain:
00272                                  * When there is activity on the socket, reset the ping counter so
00273                                  * that we're not wasting bandwidth pinging an active server.
00274                                  */
00275                                 route_back_again->SetNextPingTime(Instance->Time() + Utils->PingFreq);
00276                                 route_back_again->SetPingFlag();
00277                         }
00278                         else
00279                         {
00280                                 /*
00281                                  * Empty prefix from a server to server link:
00282                                  *  This is somewhat bad/naughty, so let's set the prefix
00283                                  *  to be the link that we got it from, so we don't break anything. -- w
00284                                  */
00285                                 TreeServer* n = Utils->FindServer(GetName());
00286                                 if (n)
00287                                         prefix = n->GetID();
00288                                 else
00289                                         prefix = GetName();
00290                         }
00291 
00292                         /*
00293                          * First up, check for any malformed commands (e.g. MODE without a timestamp)
00294                          * and rewrite commands where necessary (SVSMODE -> MODE for services). -- w
00295                          */
00296                         if (command == "SVSMODE") // This isn't in an "else if" so we still force FMODE for changes on channels.
00297                                 command = "MODE";
00298 
00299                         /*
00300                          * Now, check for (and parse) commands as appropriate. -- w
00301                          */
00302 
00303                         /* Find the server that this command originated from, used in the handlers below */
00304                         TreeServer *ServerSource = Utils->FindServer(prefix);
00305 
00306                         /* Find the link we just got this from so we don't bounce it back incorrectly */
00307                         std::string sourceserv = this->myhost;
00308                         if (!this->InboundServerName.empty())
00309                         {
00310                                 sourceserv = this->InboundServerName;
00311                         }
00312 
00313                         /*
00314                          * XXX one of these days, this needs to be moved into class Commands.
00315                          */
00316                         if (command == "UID")
00317                         {
00318                                 return this->ParseUID(prefix, params);
00319                         }
00320                         else if (command == "FJOIN")
00321                         {
00322                                 return this->ForceJoin(prefix,params);
00323                         }
00324                         else if ((command == "NOTICE" || command == "PRIVMSG") && (Utils->IsServer(prefix)))
00325                         {
00326                                 return this->ServerMessage(assign(command), prefix, params, sourceserv);
00327                         }
00328                         else if (command == "STATS")
00329                         {
00330                                 return this->Stats(prefix, params);
00331                         }
00332                         else if (command == "MOTD")
00333                         {
00334                                 return this->Motd(prefix, params);
00335                         }
00336                         else if (command == "KILL" && ServerSource)
00337                         {
00338                                 // Kill from a server
00339                                 return this->RemoteKill(prefix,params);
00340                         }
00341                         else if (command == "MODULES")
00342                         {
00343                                 return this->Modules(prefix, params);
00344                         }
00345                         else if (command == "ADMIN")
00346                         {
00347                                 return this->Admin(prefix, params);
00348                         }
00349                         else if (command == "MAP")
00350                         {
00351                                 User* user = Instance->FindNick(prefix);
00352                                 if (user)
00353                                 {
00354                                         std::vector<std::string> p(params.begin(), params.end());
00355                                         return Utils->Creator->HandleMap(p, user);
00356                                 }
00357                         }
00358                         else if (command == "SERVER")
00359                         {
00360                                 return this->RemoteServer(prefix,params);
00361                         }
00362                         else if (command == "ERROR")
00363                         {
00364                                 return this->Error(params);
00365                         }
00366                         else if (command == "OPERTYPE")
00367                         {
00368                                 return this->OperType(prefix,params);
00369                         }
00370                         else if (command == "FMODE")
00371                         {
00372                                 return this->ForceMode(prefix,params);
00373                         }
00374                         else if (command == "FTOPIC")
00375                         {
00376                                 return this->ForceTopic(prefix,params);
00377                         }
00378                         else if (command == "METADATA")
00379                         {
00380                                 return this->MetaData(prefix,params);
00381                         }
00382                         else if (command == "PING")
00383                         {
00384                                 return this->LocalPing(prefix,params);
00385                         }
00386                         else if (command == "PONG")
00387                         {
00388                                 TreeServer *s = Utils->FindServer(prefix);
00389                                 if (s && s->bursting)
00390                                 {
00391                                         Instance->SNO->WriteToSnoMask('l',"Server \002%s\002 has not finished burst, forcing end of burst (send ENDBURST!)", prefix.c_str());
00392                                         s->FinishBurst();
00393                                 }
00394                                 return this->LocalPong(prefix,params);
00395                         }
00396                         else if (command == "VERSION")
00397                         {
00398                                 return this->ServerVersion(prefix,params);
00399                         }
00400                         else if (command == "FHOST")
00401                         {
00402                                 return this->ChangeHost(prefix,params);
00403                         }
00404                         else if (command == "FNAME")
00405                         {
00406                                 return this->ChangeName(prefix,params);
00407                         }
00408                         else if (command == "ADDLINE")
00409                         {
00410                                 return this->AddLine(prefix,params);
00411                         }
00412                         else if (command == "DELLINE")
00413                         {
00414                                 return this->DelLine(prefix,params);
00415                         }
00416                         else if (command == "SVSNICK")
00417                         {
00418                                 return this->ForceNick(prefix,params);
00419                         }
00420                         else if (command == "OPERQUIT")
00421                         {
00422                                 return this->OperQuit(prefix,params);
00423                         }
00424                         else if (command == "IDLE")
00425                         {
00426                                 return this->Whois(prefix,params);
00427                         }
00428                         else if (command == "PUSH")
00429                         {
00430                                 return this->Push(prefix,params);
00431                         }
00432                         else if (command == "TIME")
00433                         {
00434                                 return this->Time(prefix,params);
00435                         }
00436                         else if ((command == "KICK") && (Utils->IsServer(prefix)))
00437                         {
00438                                 if (params.size() == 3)
00439                                 {
00440                                         TreeServer* pf = Utils->FindServer(prefix);
00441                                         User* user = this->Instance->FindNick(params[1]);
00442                                         Channel* chan = this->Instance->FindChan(params[0]);
00443                                         if (pf && user && chan)
00444                                         {
00445                                                 if (!chan->ServerKickUser(user, params[2].c_str(), false, pf->GetName().c_str()))
00446                                                         /* Yikes, the channels gone! */
00447                                                         delete chan;
00448                                         }
00449                                 }
00450 
00451                                 return Utils->DoOneToAllButSenderRaw(line,sourceserv,prefix,command,params);
00452                         }
00453                         else if (command == "SVSJOIN")
00454                         {
00455                                 return this->ServiceJoin(prefix,params);
00456                         }
00457                         else if (command == "SVSPART")
00458                         {
00459                                 return this->ServicePart(prefix,params);
00460                         }
00461                         else if (command == "SQUIT")
00462                         {
00463                                 if (params.size() == 2)
00464                                 {
00465                                         this->Squit(Utils->FindServer(params[0]),params[1]);
00466                                 }
00467                                 return true;
00468                         }
00469                         else if (command == "MODENOTICE")
00470                         {
00471                                 if (params.size() >= 2)
00472                                 {
00473                                         if (ServerSource)
00474                                                 Instance->Users->WriteMode(params[0].c_str(), WM_AND, "*** From %s: %s", (ServerSource ? ServerSource->GetName().c_str() : prefix.c_str()), params[1].c_str());
00475                                 }
00476                                 return Utils->DoOneToAllButSenderRaw(line, sourceserv, prefix, command, params);
00477                         }
00478                         else if (command == "SNONOTICE")
00479                         {
00480                                 if (params.size() >= 2)
00481                                 {
00482                                         Instance->SNO->WriteToSnoMask(*(params[0].c_str()), "From " + (ServerSource ? ServerSource->GetName().c_str() : prefix) + ": "+ params[1]);
00483                                         return Utils->DoOneToAllButSenderRaw(line, sourceserv, prefix, command, params);
00484                                 }
00485 
00486                         }
00487                         else if (command == "BURST")
00488                         {
00489                                 // Set prefix server as bursting
00490                                 if (!ServerSource)
00491                                 {
00492                                         this->Instance->SNO->WriteToSnoMask('l', "WTF: Got BURST from a nonexistant server(?): %s", (ServerSource ? ServerSource->GetName().c_str() : prefix.c_str()));
00493                                         return false;
00494                                 }
00495 
00496                                 ServerSource->bursting = true;
00497                                 return Utils->DoOneToAllButSenderRaw(line, sourceserv, prefix, command, params);
00498                         }
00499                         else if (command == "ENDBURST")
00500                         {
00501                                 if (!ServerSource)
00502                                 {
00503                                         this->Instance->SNO->WriteToSnoMask('l', "WTF: Got ENDBURST from a nonexistant server(?): %s", (ServerSource ? ServerSource->GetName().c_str() : prefix.c_str()));
00504                                         return false;
00505                                 }
00506 
00507                                 ServerSource->FinishBurst();
00508                                 return Utils->DoOneToAllButSenderRaw(line, sourceserv, prefix, command, params);
00509                         }
00510                         else if (command == "ENCAP")
00511                         {
00512                                 return this->Encap(prefix, params);
00513                         }
00514                         else if (command == "MODE" && !this->Instance->FindUUID(prefix)) // XXX we should check for no such serv?
00515                         {
00516                                 // Server-prefix MODE.
00517                                 std::vector<std::string> modelist(params.begin(), params.end());
00518 
00519                                 /* We don't support this for channel mode changes any more! */
00520                                 if (params.size() >= 1)
00521                                 {
00522                                         if (Instance->FindChan(params[0]))
00523                                         {
00524                                                 this->SendError("Protocol violation by '"+(ServerSource ? ServerSource->GetName().c_str() : prefix)+"'! MODE for channel mode changes is not supported by the InspIRCd 1.2 protocol. You must use FMODE to preserve channel timestamps.");
00525                                                 return false;
00526                                         }
00527                                 }
00528 
00529                                 // Insert into the parser
00530                                 this->Instance->SendMode(modelist, this->Instance->FakeClient);
00531 
00532                                 // Pass out to the network
00533                                 return Utils->DoOneToAllButSenderRaw(line,sourceserv,prefix,command,params);
00534                         }
00535                         else
00536                         {
00537                                 /*
00538                                  * Not a special s2s command. Emulate the user doing it.
00539                                  * This saves us having a huge ugly command parser again.
00540                                  */
00541                                 User *who = this->Instance->FindUUID(prefix);
00542 
00543                                 if (!who)
00544                                 {
00545                                         // this looks ugly because command is an irc::string
00546                                         this->SendError("Command (" + std::string(command.c_str()) + ") from unknown prefix (" + prefix + ")! Dropping link.");
00547                                         return false;
00548                                 }
00549 
00550                                 if (command == "NICK")
00551                                 {
00552                                         if (params.size() != 2)
00553                                         {
00554                                                 SendError("Protocol violation: NICK message without TS - :"+std::string(who->uuid)+" NICK "+params[0]);
00555                                                 return false;
00556                                         }
00557                                         /* Update timestamp on user when they change nicks */
00558                                         who->age = atoi(params[1].c_str());
00559 
00560                                         /*
00561                                          * On nick messages, check that the nick doesnt already exist here.
00562                                          * If it does, perform collision logic.
00563                                          */
00564                                         User* x = this->Instance->FindNickOnly(params[0]);
00565                                         if ((x) && (x != who))
00566                                         {
00567                                                 int collideret = 0;
00568                                                 /* x is local, who is remote */
00569                                                 collideret = this->DoCollision(x, who->age, who->ident, who->GetIPString(), who->uuid);
00570                                                 if (collideret != 1)
00571                                                 {
00572                                                         /*
00573                                                          * Remote client lost, or both lost, parsing this nickchange would be
00574                                                          * pointless, as the incoming client's server will soon recieve SVSNICK to
00575                                                          * change its nick to its UID. :) -- w00t
00576                                                          */
00577                                                         return true;
00578                                                 }
00579                                         }
00580                                 }
00581 
00582                                 // its a user
00583                                 std::vector<std::string> strparams(params.begin(), params.end());
00584 
00585                                 switch (this->Instance->CallCommandHandler(command.c_str(), strparams, who))
00586                                 {
00587                                         case CMD_INVALID:
00588                                                 /*
00589                                                  * XXX: command is irc::string, hence ugliness
00590                                                  */
00591                                                 this->SendError("Unrecognised or malformed command '" + std::string(command.c_str()) + "' -- possibly loaded mismatched modules");
00592                                                 return false;
00593                                                 break;
00594                                         case CMD_FAILURE:
00595                                                 /*
00596                                                  * CMD_LOCALONLY is aliased to CMD_FAILURE, so this won't go out onto the network.
00597                                                  */
00598                                                 return true;
00599                                                 break;
00600                                         default:
00601                                                 /* CMD_SUCCESS falls through here */
00602                                                 break;
00603                                 }
00604 
00605                                 return Utils->DoOneToAllButSenderRaw(line,sourceserv,prefix,command,params);
00606 
00607                         }
00608                         return true;
00609                         break; // end of state CONNECTED (phew).
00610         }
00611         return true;
00612 }
00613 
00614 std::string TreeSocket::GetName()
00615 {
00616         std::string sourceserv = this->myhost;
00617         if (!this->InboundServerName.empty())
00618         {
00619                 sourceserv = this->InboundServerName;
00620         }
00621         return sourceserv;
00622 }
00623 
00624 void TreeSocket::OnTimeout()
00625 {
00626         if (this->LinkState == CONNECTING)
00627         {
00628                 Utils->Creator->RemoteMessage(NULL, "CONNECT: Connection to \002%s\002 timed out.", myhost.c_str());
00629                 Link* MyLink = Utils->FindLink(myhost);
00630                 if (MyLink)
00631                         Utils->DoFailOver(MyLink);
00632         }
00633 }
00634 
00635 void TreeSocket::OnClose()
00636 {
00637         // Test fix for big fuckup
00638         if (this->LinkState != CONNECTED)
00639                 return;
00640 
00641         // Connection closed.
00642         // If the connection is fully up (state CONNECTED)
00643         // then propogate a netsplit to all peers.
00644         std::string quitserver = this->myhost;
00645         if (!this->InboundServerName.empty())
00646         {
00647                 quitserver = this->InboundServerName;
00648         }
00649         TreeServer* s = Utils->FindServer(quitserver);
00650         if (s)
00651         {
00652                 Squit(s,"Remote host closed the connection");
00653         }
00654 
00655         if (!quitserver.empty())
00656         {
00657                 Utils->Creator->RemoteMessage(NULL,"Connection to '\2%s\2' failed.",quitserver.c_str());
00658                 time_t server_uptime = Instance->Time() - this->age;
00659                 if (server_uptime)
00660                         Utils->Creator->RemoteMessage(NULL,"Connection to '\2%s\2' was established for %s", quitserver.c_str(), Utils->Creator->TimeToStr(server_uptime).c_str());
00661         }
00662 }
00663 
00664 int TreeSocket::OnIncomingConnection(int newsock, char* ip)
00665 {
00666         bool found = false;
00667 
00668         found = (std::find(Utils->ValidIPs.begin(), Utils->ValidIPs.end(), ip) != Utils->ValidIPs.end());
00669         if (!found)
00670         {
00671                 for (std::vector<std::string>::iterator i = Utils->ValidIPs.begin(); i != Utils->ValidIPs.end(); i++)
00672                 {
00673                         if (*i == "*" || irc::sockets::MatchCIDR(ip, *i))
00674                         {
00675                                 found = true;
00676                                 break;
00677                         }
00678                 }
00679 
00680                 if (!found)
00681                 {
00682                         Utils->Creator->RemoteMessage(NULL,"Server connection from %s denied (no link blocks with that IP address)", ip);
00683                         Instance->SE->Close(newsock);
00684                         return false;
00685                 }
00686         }
00687 
00688         /* we don't need a pointer to this, creating it stores it in the necessary places */
00689         new TreeSocket(this->Utils, this->Instance, newsock, ip, this->Hook);
00690         return true;
00691 }