]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Moved a load of servers-only stuff into serverrec out of the way of userrec
authorbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>
Tue, 17 May 2005 16:29:45 +0000 (16:29 +0000)
committerbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>
Tue, 17 May 2005 16:29:45 +0000 (16:29 +0000)
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@1417 e03df62e-2008-0410-955e-edbf42e46eb7

include/connection.h
include/servers.h
src/Makefile
src/connection.cpp
src/inspircd.cpp
src/servers.cpp

index b84d39df9b42b623270980d91dfd2601eae94696..6f33663af82c99ade2842350594df1a51d85a163 100644 (file)
@@ -270,51 +270,9 @@ class connection : public Extensible
         */
        time_t nping;
        
-       /** With a serverrec, this is a list of all established server connections.
-        * With a userrec this is unused.
-        */
-       std::vector<ircd_connector> connectors;
-       
        /** Default constructor
         */
        connection();
-       
-       /** Create a listening socket on 'host' using port number 'p'
-        */
-       bool CreateListener(char* host, int p);
-       
-       /** Begin an outbound link to another ircd at targethost.
-        */
-       bool BeginLink(char* targethost, int port, char* password, char* servername, int myport);
-       
-       /** Begin an outbound mesh link to another ircd on a network you are already an authenticated member of
-        */
-       bool MeshCookie(char* targethost, int port, unsigned long cookie, char* servername);
-       
-       /** Terminate a link to 'targethost' by calling the ircd_connector::CloseConnection method.
-        */
-       void TerminateLink(char* targethost);
-       
-       /** Send a message to a server by name, if the server is unavailable directly route the packet via another server
-        * If the server still cannot be reached after attempting to route the message remotely, returns false.
-        */
-       bool SendPacket(char *message, const char* host);
-       
-       /** Returns the next available packet and returns true if data is available. Writes the servername the data came from to 'host'.
-        * If no data is available this function returns false.
-        * This function will automatically close broken links and reroute pathways, generating split messages on the network.
-        */
-       bool RecvPacket(std::deque<std::string> &messages, char* host, std::deque<std::string> &sums);
-       
-       /** Find the ircd_connector oject related to a certain servername given in 'host'
-        */
-       ircd_connector* FindHost(std::string host);
-       
-       /** Add an incoming connection to the connection pool.
-        * (reserved for core use)
-        */
-       bool AddIncoming(int fd,char* targethost, int sourceport);
-       
 };
 
 
index 09e6ad1c687e321c4c38977d2e2d3b20afb0d9a7..e7d7f254760769a48dc953e271880ebda0504fdd 100644 (file)
@@ -75,10 +75,48 @@ class serverrec : public connection
        /** Destructor
         */
        ~serverrec();
-       
-};
 
+        /** With a serverrec, this is a list of all established server connections.
+         */
+        std::vector<ircd_connector> connectors;
+
+
+        /** Create a listening socket on 'host' using port number 'p'
+         */
+        bool CreateListener(char* host, int p);
+
+        /** Begin an outbound link to another ircd at targethost.
+         */
+        bool BeginLink(char* targethost, int port, char* password, char* servername, int myport);
+
+        /** Begin an outbound mesh link to another ircd on a network you are already an authenticated member of
+         */
+        bool MeshCookie(char* targethost, int port, unsigned long cookie, char* servername);
 
+        /** Terminate a link to 'targethost' by calling the ircd_connector::CloseConnection method.
+         */
+        void TerminateLink(char* targethost);
+
+        /** Send a message to a server by name, if the server is unavailable directly route the packet via another server
+         * If the server still cannot be reached after attempting to route the message remotely, returns false.
+         */
+        bool SendPacket(char *message, const char* host);
+
+        /** Returns the next available packet and returns true if data is available. Writes the servername the data came from to 'host'.
+         * If no data is available this function returns false.
+         * This function will automatically close broken links and reroute pathways, generating split messages on the network.
+         */
+        bool RecvPacket(std::deque<std::string> &messages, char* host, std::deque<std::string> &sums);
+
+        /** Find the ircd_connector oject related to a certain servername given in 'host'
+         */
+        ircd_connector* FindHost(std::string host);
+
+        /** Add an incoming connection to the connection pool.
+         * (reserved for core use)
+         */
+        bool AddIncoming(int fd,char* targethost, int sourceport);     
+};
 
 #endif
 
index 7404fea5a7323cd2c787c5e30db3838fa6b7e416..aeb1a9dd3fbd68c11c5c3b4baf58959b70d61c65 100644 (file)
@@ -74,7 +74,7 @@ libIRCDdynamic.so: dynamic.cpp ../include/base.h ../include/dynamic.h ../include
        $(CC) -pipe -I../include $(FLAGS) -export-dynamic -c dynamic.cpp
        $(CC) -shared -o libIRCDdynamic.so dynamic.o
 
-libIRCDusers.so: users.cpp ../include/base.h ../include/users.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
+libIRCDusers.so: users.cpp ../include/base.h ../include/users.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h ../include/connection.h
        $(CC) -pipe -I../include $(FLAGS) -export-dynamic -c users.cpp
        $(CC) -shared -o libIRCDusers.so users.o
 
@@ -86,7 +86,7 @@ libIRCDwildcard.so: wildcard.cpp ../include/base.h ../include/wildcard.h ../incl
        $(CC) -pipe -I../include $(FLAGS) -export-dynamic -c wildcard.cpp
        $(CC) -shared -o libIRCDwildcard.so wildcard.o
 
-libIRCDservers.so: servers.cpp ../include/base.h ../include/servers.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h
+libIRCDservers.so: servers.cpp ../include/base.h ../include/servers.h ../include/inspircd.h ../include/channels.h ../include/users.h ../include/globals.h ../include/inspircd_config.h ../include/connection.h
        $(CC) -pipe -I../include $(FLAGS) -export-dynamic -c servers.cpp
        $(CC) -shared -o libIRCDservers.so servers.o
 
index c902c2d223fa2852e8cc8a523f1626df41ba88b5..222251bb446db23b244743679e01224fad1cfb72 100644 (file)
@@ -36,8 +36,6 @@ using namespace std;
 extern std::vector<Module*> modules;
 extern std::vector<ircd_module*> factory;
 
-std::deque<std::string> xsums;
-
 extern int MODCOUNT;
 
 extern time_t TIME;
@@ -78,66 +76,6 @@ connection::connection()
 }
 
 
-bool connection::CreateListener(char* newhost, int p)
-{
-       sockaddr_in host_address;
-       int flags;
-       in_addr addy;
-       int on = 0;
-       struct linger linger = { 0 };
-       
-       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(newhost,""))
-       {
-               host_address.sin_addr.s_addr = htonl(INADDR_ANY);
-       }
-       else
-       {
-               inet_aton(newhost,&addy);
-               host_address.sin_addr = addy;
-       }
-
-       host_address.sin_port = htons(p);
-
-       if (bind(fd,(sockaddr*)&host_address,sizeof(host_address))<0)
-       {
-               return false;
-       }
-
-       // make the socket non-blocking
-       flags = fcntl(fd, F_GETFL, 0);
-       fcntl(fd, F_SETFL, flags | O_NONBLOCK);
-
-       this->port = p;
-
-       listen(this->fd,32);
-
-       return true;
-}
-
 char* ircd_connector::GetServerIP()
 {
        return this->host;
@@ -262,43 +200,6 @@ bool ircd_connector::MakeOutboundConnection(char* newhost, int newport)
 }
 
 
-bool connection::BeginLink(char* targethost, int newport, char* password, char* servername, int myport)
-{
-       char connect[MAXBUF];
-       
-       ircd_connector connector;
-       ircd_connector *cn = this->FindHost(servername);
-
-
-       if (cn)
-       {
-               WriteOpers("CONNECT aborted: Server %s already exists",servername);
-               return false;
-       }
-
-       
-       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,"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
-               {
-                       connector.SetState(STATE_DISCONNECTED);
-                       WriteOpers("Could not create outbound connection to %s:%d",targethost,newport);
-               }
-       }
-       return false;
-}
-
 void ircd_connector::SetVersionString(std::string newversion)
 {
        log(DEBUG,"Set version of %s to %s",this->servername.c_str(),newversion.c_str());
@@ -310,79 +211,6 @@ std::string ircd_connector::GetVersionString()
        return this->version;
 }
 
-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);
-
-       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;
-}
-
-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
-}
-
-
-// Returns a pointer to the connector for 'host'
-ircd_connector* connection::FindHost(std::string findhost)
-{
-       for (int i = 0; i < this->connectors.size(); i++)
-       {
-               if (this->connectors[i].GetServerName() == findhost)
-               {
-                       return &this->connectors[i];
-               }
-       }
-       return NULL;
-}
 
 std::string ircd_connector::GetServerName()
 {
@@ -438,170 +266,3 @@ void ircd_connector::SetDescriptor(int newfd)
 {
        this->fd = newfd;
 }
-
-bool connection::SendPacket(char *message, const char* sendhost)
-{
-       if ((!message) || (!sendhost))
-               return true;
-
-       ircd_connector* cn = this->FindHost(sendhost);
-       
-       if (!strchr(message,'\n'))
-       {
-               strlcat(message,"\n",MAXBUF);
-       }
-
-       if (cn)
-       {
-               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;
-       }
-}
-
-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<std::string> &messages, char* recvhost,std::deque<std::string> &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;
-}
-
index 701b953819c2f1497d080a8c655fbe5dbae2a788..d5156117a17983c6d088d63e574648aebe01a95e 100644 (file)
@@ -2855,49 +2855,45 @@ int InspIRCd(char** argv, int argc)
                        }
                }
      
+               std::deque<std::string> msgs;
+               std::deque<std::string> sums;
                for (int x = 0; x < SERVERportCount; x++)
                {
-                       std::deque<std::string> msgs;
-                       std::deque<std::string> sums;
-                       msgs.clear();
                        sums.clear();
-                       if (me[x])
+                       msgs.clear();
+                       while ((me[x]) && (me[x]->RecvPacket(msgs, tcp_host, sums))) // returns 0 or more lines (can be multiple lines!)
                        {
-                               sums.clear();
-                               msgs.clear();
-                               while (me[x]->RecvPacket(msgs, tcp_host, sums))
+                               for (int ctr = 0; ctr < msgs.size(); ctr++)
                                {
-                                       for (int ctr = 0; ctr < msgs.size(); ctr++)
+                                       strlcpy(tcp_msg,msgs[ctr].c_str(),MAXBUF);
+                                       strlcpy(tcp_sum,msgs[ctr].c_str(),MAXBUF);
+                                       log(DEBUG,"Processing: %s",tcp_msg);
+                                       if (!tcp_msg[0])
+                                       {
+                                               log(DEBUG,"Invalid string from %s [route%lu]",tcp_host,(unsigned long)x);
+                                               break;
+                                       }
+                                       // during a netburst, send all data to all other linked servers
+                                       if ((((nb_start>0) && (tcp_msg[0] != 'Y') && (tcp_msg[0] != 'X') && (tcp_msg[0] != 'F'))) || (is_uline(tcp_host)))
                                        {
-                                               strlcpy(tcp_msg,msgs[ctr].c_str(),MAXBUF);
-                                               strlcpy(tcp_sum,msgs[ctr].c_str(),MAXBUF);
-                                               log(DEBUG,"Processing: %s",tcp_msg);
-                                               if (!tcp_msg[0])
-                                               {
-                                                       log(DEBUG,"Invalid string from %s [route%lu]",tcp_host,(unsigned long)x);
-                                                       break;
-                                               }
-                                               // during a netburst, send all data to all other linked servers
-                                               if ((((nb_start>0) && (tcp_msg[0] != 'Y') && (tcp_msg[0] != 'X') && (tcp_msg[0] != 'F'))) || (is_uline(tcp_host)))
+                                               if (is_uline(tcp_host))
                                                {
-                                                       if (is_uline(tcp_host))
+                                                       if ((tcp_msg[0] != 'Y') && (tcp_msg[0] != 'X') && (tcp_msg[0] != 'F'))
                                                        {
-                                                               if ((tcp_msg[0] != 'Y') && (tcp_msg[0] != 'X') && (tcp_msg[0] != 'F'))
-                                                               {
-                                                                       NetSendToAllExcept_WithSum(tcp_host,tcp_msg,tcp_sum);
-                                                               }
-                                                       }
-                                                       else
                                                                NetSendToAllExcept_WithSum(tcp_host,tcp_msg,tcp_sum);
+                                                       }
                                                }
-                                               std::string msg = tcp_msg;
-                                               FOREACH_MOD OnPacketReceive(msg,tcp_host);
-                                               strlcpy(tcp_msg,msg.c_str(),MAXBUF);
-                                               if (me[x])
-                                                       handle_link_packet(tcp_msg, tcp_host, me[x], tcp_sum);
+                                               else
+                                                       NetSendToAllExcept_WithSum(tcp_host,tcp_msg,tcp_sum);
                                        }
-                                       //goto label;
+                                       std::string msg = tcp_msg;
+                                       FOREACH_MOD OnPacketReceive(msg,tcp_host);
+                                       strlcpy(tcp_msg,msg.c_str(),MAXBUF);
+                                       if (me[x])
+                                               handle_link_packet(tcp_msg, tcp_host, me[x], tcp_sum);
                                }
+                                       sums.clear();   // we're done, clear the list for the next operation
+                                       msgs.clear();
                        }
                }
        
index 45ec5b00ec2e16869534cf71b9625cc076c8ef6c..56e0d0c41e430e85d9c4ff9c70b52144d9052623 100644 (file)
@@ -19,13 +19,25 @@ using namespace std;
 #include "inspircd_config.h" 
 #include "servers.h"
 #include "inspircd.h"
-#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/utsname.h>
+#include <vector>
+#include <string>
+#include <deque>
+#include <sstream>
 #include <map>
 #include "inspstring.h"
 #include "helperfuncs.h"
+#include "connection.h"
 
 extern time_t TIME;
 
+std::deque<std::string> xsums;
+
 serverrec::serverrec()
 {
        strlcpy(name,"",256);
@@ -38,6 +50,7 @@ serverrec::serverrec()
        fd = 0;
        sync_soon = false;
        strlcpy(nickserv,"",NICKMAX);
+       connectors.clear();
 }
 
  
@@ -57,5 +70,342 @@ serverrec::serverrec(char* n, long ver, bool jupe)
        fd = 0;
        sync_soon = false;
        strlcpy(nickserv,"",NICKMAX);
+       connectors.clear();
+}
+
+bool serverrec::CreateListener(char* newhost, int p)
+{
+        sockaddr_in host_address;
+        int flags;
+        in_addr addy;
+        int on = 0;
+        struct linger linger = { 0 };
+
+        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(newhost,""))
+        {
+                host_address.sin_addr.s_addr = htonl(INADDR_ANY);
+        }
+        else
+        {
+                inet_aton(newhost,&addy);
+                host_address.sin_addr = addy;
+        }
+
+        host_address.sin_port = htons(p);
+
+        if (bind(fd,(sockaddr*)&host_address,sizeof(host_address))<0)
+        {
+                return false;
+        }
+
+        // make the socket non-blocking
+        flags = fcntl(fd, F_GETFL, 0);
+        fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+
+        this->port = p;
+
+        listen(this->fd,32);
+
+        return true;
+}
+
+
+bool serverrec::BeginLink(char* targethost, int newport, char* password, char* servername, int myport)
+{
+        char connect[MAXBUF];
+
+        ircd_connector connector;
+        ircd_connector *cn = this->FindHost(servername);
+
+
+        if (cn)
+        {
+                WriteOpers("CONNECT aborted: Server %s already exists",servername);
+                return false;
+        }
+
+
+        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,"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
+                {
+                        connector.SetState(STATE_DISCONNECTED);
+                        WriteOpers("Could not create outbound connection to %s:%d",targethost,newport);
+                }
+        }
+        return false;
+}
+
+
+bool serverrec::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);
+
+        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 serverrec::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,"serverrec::AddIncoming() Added connection: %s:%d",targethost,sourceport);
+        this->connectors.push_back(connector);
+        return true;
+}
+
+void serverrec::TerminateLink(char* targethost)
+{
+        // this locates the targethost in the serverrec::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
+}
+
+// Returns a pointer to the connector for 'host'
+ircd_connector* serverrec::FindHost(std::string findhost)
+{
+        for (int i = 0; i < this->connectors.size(); i++)
+        {
+                if (this->connectors[i].GetServerName() == findhost)
+                {
+                        return &this->connectors[i];
+                }
+        }
+        return NULL;
+}
+
+bool serverrec::SendPacket(char *message, const char* sendhost)
+{
+        if ((!message) || (!sendhost))
+                return true;
+
+        ircd_connector* cn = this->FindHost(sendhost);
+
+        if (!strchr(message,'\n'))
+        {
+                strlcat(message,"\n",MAXBUF);
+        }
+
+        if (cn)
+        {
+                log(DEBUG,"main: serverrec::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++)
+                                        {
+                                                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 serverrec::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;
+        }
+}
+
+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 serverrec::RecvPacket(std::deque<std::string> &messages, char* recvhost,std::deque<std::string> &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 serverrec::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
+                                                                                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,"serverrec::RecvPacket() %d:%s->%s",pushed++,recvhost,text.c_str());
+                                                }
+                                        }
+                                        return true;
+                                }
+                        }
+                }
+        }
+        // nothing new yet -- message and host will be undefined
+        return false;
 }