X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fconnection.cpp;h=384f626e2f2f59f0cbefa57ec3fa6d9bc5d29897;hb=d5fed3976bba0f1082522da9b79b6b1cc93d4c56;hp=cd994ea652870b469d6474a617ea01feb4b70e21;hpb=b6f5d703b010fa5e4cd1d082ea70fe0cc27fb9e9;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/connection.cpp b/src/connection.cpp index cd994ea65..384f626e2 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -24,9 +24,11 @@ #include #include #include +#include #include "inspircd.h" #include "modules.h" #include "inspstring.h" +#include "helperfuncs.h" using namespace std; @@ -34,10 +36,42 @@ using namespace std; extern std::vector modules; extern std::vector factory; +std::deque xsums; + extern int MODCOUNT; extern time_t TIME; + +/** + * The InspIRCd mesh network is maintained by a tree of objects which reference *themselves*. + * Every local server has an array of 32 *serverrecs, known as me[]. Each of these represents + * a local listening port, and is not null if the user has opened a listening port on the server. + * It is assumed nobody will ever want to open more than 32 listening server ports at any one + * time (i mean come on, why would you want more, the ircd works fine with ONE). + * Each me[] entry has multiple classes within it of type ircd_connector. These are stored in a vector + * and each represents a server linked via this socket. If the connection was created outbound, + * the connection is bound to the default ip address by using me[defaultRoute] (defaultRoute being + * a global variable which indicates the default server to make connections on). If the connection + * was created inbound, it is attached to the port the connection came in on. There may be as many + * ircd_connector objects as needed in each me[] entry. Each ircd_connector implements the specifics + * of an ircd connection in the mesh, however each ircd may have multiple ircd_connector connections + * to it, to maintain the mesh link. + */ + +char* xsumtable = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +// creates a random id for a line for detection of duplicate messages +std::string CreateSum() +{ + char sum[9]; + sum[0] = ':'; + sum[8] = '\0'; + for(int q = 1; q < 8; q++) + sum[q] = xsumtable[rand()%52]; + return sum; +} + connection::connection() { fd = 0; @@ -139,9 +173,15 @@ void ircd_connector::SetServerPort(int p) void ircd_connector::AddBuffer(std::string a) { + std::string b = ""; for (int i = 0; i < a.length(); i++) if (a[i] != '\r') - ircdbuffer = ircdbuffer + a[i]; + b = b + a[i]; + + std::stringstream stream(ircdbuffer); + stream << b; + log(DEBUG,"AddBuffer: %s",b.c_str()); + ircdbuffer = stream.str(); } bool ircd_connector::BufferIsComplete() @@ -154,24 +194,26 @@ bool ircd_connector::BufferIsComplete() void ircd_connector::ClearBuffer() { - while ((ircdbuffer != "") && (ircdbuffer[0] != '\n')) - { - ircdbuffer.erase(ircdbuffer.begin()); - } - if (ircdbuffer != "") - ircdbuffer.erase(ircdbuffer.begin()); + ircdbuffer = ""; } std::string ircd_connector::GetBuffer() { - std::string z = ""; - long t = 0; - while (ircdbuffer[t] != '\n') - { - z = z + ircdbuffer[t]; - t++; - } - return z; + // Fix by Brain 28th Apr 2005 + // seems my stringstream code isnt liked by linux + // EVEN THOUGH IT IS CORRECT! Fixed by using a different + // (SLOWER) algorithm... + char* line = (char*)ircdbuffer.c_str(); + std::string ret = ""; + while ((*line != '\n') && (strlen(line))) + { + ret = ret + *line; + line++; + } + if ((*line == '\n') || (*line == '\r')) + line++; + ircdbuffer = line; + return ret; } bool ircd_connector::MakeOutboundConnection(char* newhost, int newport) @@ -257,6 +299,17 @@ bool connection::BeginLink(char* targethost, int newport, char* password, char* return false; } +void ircd_connector::SetVersionString(std::string newversion) +{ + log(DEBUG,"Set version of %s to %s",this->servername.c_str(),newversion.c_str()); + this->version = newversion; +} + +std::string ircd_connector::GetVersionString() +{ + return this->version; +} + bool connection::MeshCookie(char* targethost, int newport, unsigned long cookie, char* servername) { char connect[MAXBUF]; @@ -404,16 +457,19 @@ bool connection::SendPacket(char *message, const char* sendhost) if (cn->GetState() == STATE_DISCONNECTED) { - log(DEBUG,"Main route to %s is down, seeking alternative",host); + log(DEBUG,"\n\n\n\nMain route to %s is down, seeking alternative\n\n\n\n",sendhost); // fix: can only route one hop to avoid a loop if (strncmp(message,"R ",2)) { + log(DEBUG,"Not a double reroute"); // this route is down, we must re-route the packet through an available point in the mesh. for (int k = 0; k < this->connectors.size(); k++) { + log(DEBUG,"Check connector %d: %s",k,this->connectors[k].GetServerName().c_str()); // search for another point in the mesh which can 'reach' where we want to go for (int m = 0; m < this->connectors[k].routes.size(); m++) { + log(DEBUG,"Check connector %d: %s route %s",k,this->connectors[k].GetServerName().c_str(),this->connectors[k].routes[m].c_str()); if (!strcasecmp(this->connectors[k].routes[m].c_str(),sendhost)) { log(DEBUG,"Found alternative route for packet: %s",this->connectors[k].GetServerName().c_str()); @@ -428,7 +484,7 @@ bool connection::SendPacket(char *message, const char* sendhost) char buffer[MAXBUF]; snprintf(buffer,MAXBUF,"& %s",sendhost); NetSendToAllExcept(sendhost,buffer); - log(DEBUG,"There are no routes to %s, we're gonna boot the server off!",sendhost); + log(DEBUG,"\n\nThere are no routes to %s, we're gonna boot the server off!\n\n",sendhost); DoSplit(sendhost); return false; } @@ -447,20 +503,46 @@ bool connection::SendPacket(char *message, const char* sendhost) } } +bool already_have_sum(std::string sum) +{ + for (int i = 0; i < xsums.size(); i++) + { + if (xsums[i] == sum) + { + return true; + } + } + if (xsums.size() >= 128) + { + xsums.pop_front(); + } + xsums.push_back(sum); + return false; +} + // receives a packet from any where there is data waiting, first come, first served // fills the message and host values with the host where the data came from. -bool connection::RecvPacket(std::deque &messages, char* recvhost) +bool connection::RecvPacket(std::deque &messages, char* recvhost,std::deque &sums) { - char data[4096]; - memset(data, 0, 4096); + char data[65536]; + memset(data, 0, 65536); for (int i = 0; i < this->connectors.size(); i++) { if (this->connectors[i].GetState() != STATE_DISCONNECTED) { // returns false if the packet could not be sent (e.g. target host down) int rcvsize = 0; - rcvsize = recv(this->connectors[i].GetDescriptor(),data,32,0); + + // check if theres any data on this socket + // if not, continue onwards to the next. + pollfd polls; + polls.fd = this->connectors[i].GetDescriptor(); + polls.events = POLLIN; + int ret = poll(&polls,1,1); + if (ret <= 0) continue; + + rcvsize = recv(this->connectors[i].GetDescriptor(),data,65000,0); data[rcvsize] = '\0'; if (rcvsize == -1) { @@ -472,15 +554,48 @@ bool connection::RecvPacket(std::deque &messages, char* recvhost) this->connectors[i].SetState(STATE_DISCONNECTED); } } + int pushed = 0; if (rcvsize > 0) { this->connectors[i].AddBuffer(data); if (this->connectors[i].BufferIsComplete()) { - messages.push_back(this->connectors[i].GetBuffer().c_str()); - strlcpy(host,this->connectors[i].GetServerName().c_str(),160); - log(DEBUG,"main: Connection::RecvPacket() got '%s' from %s",this->connectors[i].GetBuffer().c_str(),recvhost); - this->connectors[i].ClearBuffer(); + while (this->connectors[i].BufferIsComplete()) + { + std::string text = this->connectors[i].GetBuffer(); + if (text != "") + { + if ((text[0] == ':') && (text.find(" ") != std::string::npos)) + { + std::string orig = text; + log(DEBUG,"Original: %s",text.c_str()); + std::string sum = text.substr(1,text.find(" ")-1); + text = text.substr(text.find(" ")+1,text.length()); + std::string possible_token = text.substr(1,text.find(" ")-1); + if (possible_token.length() > 1) + { + sums.push_back("*"); + text = orig; + log(DEBUG,"Non-mesh, non-tokenized string passed up the chain"); + } + else + { + log(DEBUG,"Packet sum: '%s'",sum.c_str()); + if ((already_have_sum(sum)) && (sum != "*")) + { + // we don't accept dupes + log(DEBUG,"Duplicate packet sum %s from server %s dropped",sum.c_str(),this->connectors[i].GetServerName().c_str()); + continue; + } + sums.push_back(sum.c_str()); + } + } + else sums.push_back("*"); + messages.push_back(text.c_str()); + strlcpy(recvhost,this->connectors[i].GetServerName().c_str(),160); + log(DEBUG,"Connection::RecvPacket() %d:%s->%s",pushed++,recvhost,text.c_str()); + } + } return true; } } @@ -490,8 +605,3 @@ bool connection::RecvPacket(std::deque &messages, char* recvhost) return false; } -long connection::GenKey() -{ - return (random()*time(NULL)); -} -