X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fconnection.cpp;h=384f626e2f2f59f0cbefa57ec3fa6d9bc5d29897;hb=d5fed3976bba0f1082522da9b79b6b1cc93d4c56;hp=7a92afcd66293a1330f1008d39fc1c1b7aad3d9c;hpb=43e8ea4f5d54146d8b5fdf49d10fd3778dbdd3c0;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/connection.cpp b/src/connection.cpp index 7a92afcd6..384f626e2 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -1,40 +1,84 @@ +/* +------------------------------------+ + * | Inspire Internet Relay Chat Daemon | + * +------------------------------------+ + * + * Inspire is copyright (C) 2002-2004 ChatSpike-Dev. + * E-mail: + * + * + * + * Written by Craig Edwards, Craig McLure, and others. + * This program is free but copyrighted software; see + * the file COPYING for details. + * + * --------------------------------------------------- + */ + #include #include #include +#include #include #include #include -#include +#include +#include +#include +#include #include "inspircd.h" #include "modules.h" +#include "inspstring.h" +#include "helperfuncs.h" + +using namespace std; + extern std::vector modules; extern std::vector factory; -extern int MODCOUNT; - -#define STATE_CLEAR 1 -#define STATE_WAIT_FOR_ACK 2 +std::deque xsums; -packet::packet() -{ - srand(time(NULL)); - id = random(); -} +extern int MODCOUNT; -packet::~packet() +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() { - key = GenKey(); fd = 0; - state = STATE_CLEAR; } -bool connection::CreateListener(char* host, int p) +bool connection::CreateListener(char* newhost, int p) { sockaddr_in host_address; int flags; @@ -42,23 +86,37 @@ bool connection::CreateListener(char* host, int p) int on = 0; struct linger linger = { 0 }; - fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + this->port = p; + + fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (fd <= 0) { return false; } + setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(const char*)&on,sizeof(on)); + linger.l_onoff = 1; + linger.l_linger = 1; + setsockopt(fd,SOL_SOCKET,SO_LINGER,(const char*)&linger,sizeof(linger)); + + // attempt to increase socket sendq and recvq as high as its possible + // to get them on linux. + int sendbuf = 32768; + int recvbuf = 32768; + setsockopt(fd,SOL_SOCKET,SO_SNDBUF,(const void *)&sendbuf,sizeof(sendbuf)); + setsockopt(fd,SOL_SOCKET,SO_RCVBUF,(const void *)&recvbuf,sizeof(sendbuf)); + memset((void*)&host_address, 0, sizeof(host_address)); host_address.sin_family = AF_INET; - if (!strcmp(host,"")) + if (!strcmp(newhost,"")) { host_address.sin_addr.s_addr = htonl(INADDR_ANY); } else { - inet_aton(host,&addy); + inet_aton(newhost,&addy); host_address.sin_addr = addy; } @@ -75,262 +133,475 @@ bool connection::CreateListener(char* host, int p) this->port = p; - setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(const char*)&on,sizeof(on)); - linger.l_onoff = 1; - linger.l_linger = 0; - setsockopt(fd,SOL_SOCKET,SO_LINGER,(const char*)&linger,sizeof(linger)); + listen(this->fd,5); return true; } -bool connection::BeginLink(char* targethost, int port, char* password) +char* ircd_connector::GetServerIP() { - char connect[MAXBUF]; - - if (this->fd) - { - sprintf(connect,"S %s %s :%s",getservername().c_str(),password,getserverdesc().c_str()); - this->haspassed = false; - return this->SendPacket(connect, targethost, port, 0); - } - return false; + return this->host; } -// targethost: in dot notation a.b.c.d -void connection::TerminateLink(char* targethost) +int ircd_connector::GetServerPort() { + return this->port; } -// host: in dot notation a.b.c.d -// port: host byte order -bool connection::SendPacket(char *message, char* host, int port, long ourkey) +bool ircd_connector::SetHostAndPort(char* newhost, int newport) { - sockaddr_in host_address; - in_addr addy; - packet p; + strncpy(this->host,newhost,160); + this->port = newport; + return true; +} - memset((void*)&host_address, 0, sizeof(host_address)); +bool ircd_connector::SetHostAddress(char* newhost, int newport) +{ + strncpy(this->host,newhost,160); + this->port = newport; + memset((void*)&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + inet_aton(host,&addr.sin_addr); + addr.sin_port = htons(port); + return true; +} - host_address.sin_family = AF_INET; - inet_aton(host,&addy); - host_address.sin_addr = addy; +void ircd_connector::SetServerPort(int p) +{ + this->port = p; +} - host_address.sin_port = htons(port); +void ircd_connector::AddBuffer(std::string a) +{ + std::string b = ""; + for (int i = 0; i < a.length(); i++) + if (a[i] != '\r') + b = b + a[i]; + + std::stringstream stream(ircdbuffer); + stream << b; + log(DEBUG,"AddBuffer: %s",b.c_str()); + ircdbuffer = stream.str(); +} - strcpy(p.data,message); - p.type = PT_SYN_WITH_DATA; - p.key = ourkey; +bool ircd_connector::BufferIsComplete() +{ + for (int i = 0; i < ircdbuffer.length(); i++) + if (ircdbuffer[i] == '\n') + return true; + return false; +} +void ircd_connector::ClearBuffer() +{ + ircdbuffer = ""; +} - FOREACH_MOD OnPacketTransmit(p.data); +std::string ircd_connector::GetBuffer() +{ + // 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; +} - log(DEBUG,"main: Connection::SendPacket() sent '%s' to %s:%d",p.data,host,port); +bool ircd_connector::MakeOutboundConnection(char* newhost, int newport) +{ + log(DEBUG,"MakeOutboundConnection: Original param: %s",newhost); + ClearBuffer(); + hostent* hoste = gethostbyname(newhost); + if (!hoste) + { + log(DEBUG,"MakeOutboundConnection: gethostbyname was NULL, setting %s",newhost); + this->SetHostAddress(newhost,newport); + SetHostAndPort(newhost,newport); + } + else + { + struct in_addr* ia = (in_addr*)hoste->h_addr; + log(DEBUG,"MakeOutboundConnection: gethostbyname was valid, setting %s",inet_ntoa(*ia)); + this->SetHostAddress(inet_ntoa(*ia),newport); + SetHostAndPort(inet_ntoa(*ia),newport); + } - // returns false if the packet could not be sent (e.g. target host down) - if (sendto(this->fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0) + this->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (this->fd >= 0) { - log(DEBUG,"sendto() failed for Connection::SendPacket() with a packet of size %d: %s",sizeof(p),strerror(errno)); - return false; + if(connect(this->fd, (sockaddr*)&this->addr,sizeof(this->addr))) + { + WriteOpers("connect() failed for %s",host); + RemoveServer(this->servername.c_str()); + return false; + } + int flags = fcntl(this->fd, F_GETFL, 0); + fcntl(this->fd, F_SETFL, flags | O_NONBLOCK); + int sendbuf = 32768; + int recvbuf = 32768; + setsockopt(this->fd,SOL_SOCKET,SO_SNDBUF,(const void *)&sendbuf,sizeof(sendbuf)); + setsockopt(this->fd,SOL_SOCKET,SO_RCVBUF,(const void *)&recvbuf,sizeof(sendbuf)); + return true; } - this->state = STATE_WAIT_FOR_ACK; + else + { + WriteOpers("socket() failed!"); + RemoveServer(this->servername.c_str()); + } + + return false; +} - // host_address remains unchanged. we only want to receive from where we just sent the packet to. +bool connection::BeginLink(char* targethost, int newport, char* password, char* servername, int myport) +{ + char connect[MAXBUF]; - // retry the packet up to 5 times - for (int retries = 0; retries < 5; retries++) + ircd_connector connector; + ircd_connector *cn = this->FindHost(servername); + + + if (cn) { - socklen_t host_address_size; - host_address.sin_family=AF_INET; - host_address_size=sizeof(host_address); + WriteOpers("CONNECT aborted: Server %s already exists",servername); + return false; + } + - // wait for ack, or timeout. - // if reached a timeout, send again. - // the packet id in the ack must match that in the original packet - // this MUST operate in lock/step fashion!!! - int cycles = 0; - packet p2; - do - { - fd_set sfd; - timeval tval; - tval.tv_usec = 100; - tval.tv_sec = 0; - FD_ZERO(&sfd); - FD_SET(fd,&sfd); - int res = select(65535, &sfd, NULL, NULL, &tval); - cycles++; - } - while ((recvfrom(fd,&p2,sizeof(p2),MSG_PEEK,(sockaddr*)&host_address,&host_address_size)<0) && (cycles < 10)); - - if (cycles >= 10) + if (this->fd) + { + if (connector.MakeOutboundConnection(targethost,newport)) { - log(DEFAULT,"ERROR! connection::SendPacket() waited >10000 nanosecs for an ACK. Will resend up to 5 times"); + // targethost has been turned into an ip... + // we dont want this as the server name. + connector.SetServerName(servername); + snprintf(connect,MAXBUF,"S %s %s %lu %lu :%s",getservername().c_str(),password,(unsigned long)myport,(unsigned long)GetRevision(),getserverdesc().c_str()); + connector.SetState(STATE_NOAUTH_OUTBOUND); + connector.SetHostAndPort(targethost, newport); + this->connectors.push_back(connector); + return this->SendPacket(connect, servername); } else { - if (p2.type != PT_ACK_ONLY) - { - log(DEFAULT,"ERROR! connection::SendPacket() received a data response and was expecting a syn!!!"); - this->state = STATE_CLEAR; - return true; - } - - if (p2.id != p.id) - { - recvfrom(fd,&p2,sizeof(p2),0,(sockaddr*)&host_address,&host_address_size); - log(DEFAULT,"ERROR! connection::SendPacket() received an ack for a packet it didnt send!"); - this->state = STATE_CLEAR; - return false; - } - else - { - recvfrom(fd,&p2,sizeof(p2),0,(sockaddr*)&host_address,&host_address_size); - log(DEFAULT,"Successfully received ACK"); - this->state = STATE_CLEAR; - return true; - break; - } + connector.SetState(STATE_DISCONNECTED); + WriteOpers("Could not create outbound connection to %s:%d",targethost,newport); } } - log(DEFAULT,"We never received an ack. Something fishy going on, host is dead."); - this->state = STATE_CLEAR; 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; } -bool connection::SendSYN(char* host, int port) +std::string ircd_connector::GetVersionString() { - sockaddr_in host_address; - in_addr addy; - packet p; + return this->version; +} - memset((void*)&host_address, 0, sizeof(host_address)); +bool connection::MeshCookie(char* targethost, int newport, unsigned long cookie, char* servername) +{ + char connect[MAXBUF]; + + ircd_connector connector; + + WriteOpers("Establishing meshed link to %s:%d",servername,newport); - host_address.sin_family = AF_INET; - inet_aton(host,&addy); - host_address.sin_addr = addy; + if (this->fd) + { + if (connector.MakeOutboundConnection(targethost,newport)) + { + // targethost has been turned into an ip... + // we dont want this as the server name. + connector.SetServerName(servername); + snprintf(connect,MAXBUF,"- %lu %s :%s",cookie,getservername().c_str(),getserverdesc().c_str()); + connector.SetState(STATE_NOAUTH_OUTBOUND); + connector.SetHostAndPort(targethost, newport); + connector.SetState(STATE_CONNECTED); + this->connectors.push_back(connector); + return this->SendPacket(connect, servername); + } + else + { + connector.SetState(STATE_DISCONNECTED); + WriteOpers("Could not create outbound connection to %s:%d",targethost,newport); + } + } + return false; +} + +bool connection::AddIncoming(int newfd, char* targethost, int sourceport) +{ + ircd_connector connector; + + // targethost has been turned into an ip... + // we dont want this as the server name. + connector.SetServerName(targethost); + connector.SetDescriptor(newfd); + connector.SetState(STATE_NOAUTH_INBOUND); + int flags = fcntl(newfd, F_GETFL, 0); + fcntl(newfd, F_SETFL, flags | O_NONBLOCK); + int sendbuf = 32768; + int recvbuf = 32768; + setsockopt(newfd,SOL_SOCKET,SO_SNDBUF,(const void *)&sendbuf,sizeof(sendbuf)); + setsockopt(newfd,SOL_SOCKET,SO_RCVBUF,(const void *)&recvbuf,sizeof(sendbuf)); + connector.SetHostAndPort(targethost, sourceport); + connector.SetState(STATE_NOAUTH_INBOUND); + log(DEBUG,"connection::AddIncoming() Added connection: %s:%d",targethost,sourceport); + this->connectors.push_back(connector); + return true; +} - host_address.sin_port = htons(port); +void connection::TerminateLink(char* targethost) +{ + // this locates the targethost in the connection::connectors vector of the class, + // and terminates it by sending it an SQUIT token and closing its descriptor. + // TerminateLink with a null string causes a terminate of ALL links +} - p.type = PT_SYN_ONLY; - p.key = key; - strcpy(p.data,""); - if (sendto(fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0) +// Returns a pointer to the connector for 'host' +ircd_connector* connection::FindHost(std::string findhost) +{ + for (int i = 0; i < this->connectors.size(); i++) { - return false; + if (this->connectors[i].GetServerName() == findhost) + { + return &this->connectors[i]; + } } - return true; - + return NULL; } -bool connection::SendACK(char* host, int port, int reply_id) +std::string ircd_connector::GetServerName() { - sockaddr_in host_address; - in_addr addy; - packet p; + return this->servername; +} - memset((void*)&host_address, 0, sizeof(host_address)); +std::string ircd_connector::GetDescription() +{ + return this->description; +} - host_address.sin_family = AF_INET; - inet_aton(host,&addy); - host_address.sin_addr = addy; +void ircd_connector::SetServerName(std::string serv) +{ + this->servername = serv; +} - host_address.sin_port = htons(port); +void ircd_connector::SetDescription(std::string desc) +{ + this->description = desc; +} - p.type = PT_ACK_ONLY; - p.key = key; - p.id = reply_id; - strcpy(p.data,""); - if (sendto(fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0) - { - return false; - } +int ircd_connector::GetDescriptor() +{ + return this->fd; +} +int ircd_connector::GetState() +{ + return this->state; } -// Generates a server key. This is pseudo-random. -// the server always uses the same server-key in all communications -// across the network. All other servers must remember the server key -// of servers in the network, e.g.: -// -// ServerA: key=5555555555 -// ServerB: key=6666666666 -// I am ServerC: key=77777777777 -// -// If ServerC sees a packet from ServerA, and the key stored for ServerA -// is 0, then cache the key as the servers key. -// after this point, any packet from ServerA which does not contain its key, -// 555555555, will be silently dropped. -// This should prevent blind spoofing, as to fake a server you must know its -// assigned key, and to do that you must receive messages that are origintated -// from it or hack the running executable. -// -// During the AUTH phase (when server passwords are checked, the key in any -// packet MUST be 0). Only the initial SERVER/PASS packets may have a key -// of 0 (and any ACK responses to them). -// +void ircd_connector::SetState(int newstate) +{ + this->state = newstate; + if (state == STATE_DISCONNECTED) + { + NetSendMyRoutingTable(); + } +} -long connection::GenKey() +void ircd_connector::CloseConnection() { - srand(time(NULL)); - return (random()*time(NULL)); + int flags = fcntl(this->fd, F_GETFL, 0); + fcntl(this->fd, F_SETFL, flags ^ O_NONBLOCK); + close(this->fd); + flags = fcntl(this->fd, F_GETFL, 0); + fcntl(this->fd, F_SETFL, flags | O_NONBLOCK); } -// host: in dot notation a.b.c.d -// port: host byte order -bool connection::RecvPacket(char *message, char* host, int &prt, long &theirkey) +void ircd_connector::SetDescriptor(int newfd) { - // returns false if no packet waiting for receive, e.g. EAGAIN or ECONNRESET - sockaddr_in host_address; - socklen_t host_address_size; - packet p; - - memset((void*)&host_address, 0, sizeof(host_address)); + this->fd = newfd; +} - host_address.sin_family=AF_INET; - host_address_size=sizeof(host_address); +bool connection::SendPacket(char *message, const char* sendhost) +{ + if ((!message) || (!sendhost)) + return true; - //int recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); - if (recvfrom(fd,&p,sizeof(p),0,(sockaddr*)&host_address,&host_address_size)<0) + ircd_connector* cn = this->FindHost(sendhost); + + if (!strchr(message,'\n')) { - return false; + strlcat(message,"\n",MAXBUF); } - log(DEBUG,"connection::RecvPacket(): received packet type %d '%s' from '%s'",p.type,p.data,inet_ntoa(host_address.sin_addr)); - - if (p.type == PT_SYN_ONLY) + if (cn) { - strcpy(message,p.data); - strcpy(host,inet_ntoa(host_address.sin_addr)); - prt = ntohs(host_address.sin_port); - SendACK(host,this->port,p.id); - return false; + log(DEBUG,"main: Connection::SendPacket() sent '%s' to %s",message,cn->GetServerName().c_str()); + + if (cn->GetState() == STATE_DISCONNECTED) + { + 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()); + char buffer[MAXBUF]; + snprintf(buffer,MAXBUF,"R %s %s",sendhost,message); + this->SendPacket(buffer,this->connectors[k].GetServerName().c_str()); + return true; + } + } + } + } + char buffer[MAXBUF]; + snprintf(buffer,MAXBUF,"& %s",sendhost); + NetSendToAllExcept(sendhost,buffer); + log(DEBUG,"\n\nThere are no routes to %s, we're gonna boot the server off!\n\n",sendhost); + DoSplit(sendhost); + return false; + } + + // returns false if the packet could not be sent (e.g. target host down) + if (send(cn->GetDescriptor(),message,strlen(message),0)<0) + { + log(DEBUG,"send() failed for Connection::SendPacket(): %s",strerror(errno)); + log(DEBUG,"Disabling connector: %s",cn->GetServerName().c_str()); + cn->CloseConnection(); + cn->SetState(STATE_DISCONNECTED); + // retry the packet along a new route so either arrival OR failure are gauranteed (bugfix) + return this->SendPacket(message,sendhost); + } + return true; } +} - if (p.type == PT_ACK_ONLY) +bool already_have_sum(std::string sum) +{ + for (int i = 0; i < xsums.size(); i++) { - strcpy(message,p.data); - strcpy(host,inet_ntoa(host_address.sin_addr)); - prt = ntohs(host_address.sin_port); - this->state = STATE_CLEAR; - return false; + if (xsums[i] == sum) + { + return true; + } } - - if (p.type == PT_SYN_WITH_DATA) + if (xsums.size() >= 128) { - strcpy(message,p.data); - strcpy(host,inet_ntoa(host_address.sin_addr)); - theirkey = p.key; - prt = ntohs(host_address.sin_port); // the port we received it on - SendACK(host,prt,p.id); - return true; + xsums.pop_front(); } + xsums.push_back(sum); + return false; +} - log(DEBUG,"connection::RecvPacket(): Invalid packet type %d (protocol error)",p.type); - return true; +// 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,std::deque &sums) +{ + 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; + + // 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) + { + if (errno != EAGAIN) + { + log(DEBUG,"recv() failed for Connection::RecvPacket(): %s",strerror(errno)); + log(DEBUG,"Disabling connector: %s",this->connectors[i].GetServerName().c_str()); + this->connectors[i].CloseConnection(); + this->connectors[i].SetState(STATE_DISCONNECTED); + } + } + int pushed = 0; + if (rcvsize > 0) + { + this->connectors[i].AddBuffer(data); + if (this->connectors[i].BufferIsComplete()) + { + 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; + } + } + } + } + // nothing new yet -- message and host will be undefined + return false; }