From 31d07a9bd2702085aaabe2ad5105f58c70e2ec40 Mon Sep 17 00:00:00 2001 From: brain Date: Fri, 25 Nov 2005 12:17:34 +0000 Subject: Removed static meshed linking from core git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@1940 e03df62e-2008-0410-955e-edbf42e46eb7 --- configure | 28 +-- include/connection.h | 364 ---------------------------------- include/servers.h | 126 ------------ src/connection.cpp | 398 ------------------------------------- src/servers.cpp | 548 --------------------------------------------------- 5 files changed, 7 insertions(+), 1457 deletions(-) delete mode 100644 include/connection.h delete mode 100644 include/servers.h delete mode 100644 src/connection.cpp delete mode 100644 src/servers.cpp diff --git a/configure b/configure index 37458acee..477300a5b 100755 --- a/configure +++ b/configure @@ -854,7 +854,7 @@ HEADER $flags = getcompilerflags("src/modules/m_".$i.".cpp"); if ($config{OSNAME} =~ /CYGWIN/) { print FILEHANDLE < - * - * - * Written by Craig Edwards, Craig McLure, and others. - * This program is free but copyrighted software; see - * the file COPYING for details. - * - * --------------------------------------------------- - */ - -#include "inspircd_config.h" -#include "base.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef __CONNECTION_H__ -#define __CONNECTION_H__ - -#define STATE_DISCONNECTED 0 -#define STATE_CONNECTED 1 -#define STATE_SYNC 2 -#define STATE_NOAUTH_INBOUND 3 -#define STATE_NOAUTH_OUTBOUND 4 -#define STATE_SERVICES 5 -#define STATE_COOKIE_OUTBOUND 6 - -std::string CreateSum(); - -/** Each connection has one or more of these - * each represents ONE outbound connection to another ircd - * so each inbound has multiple outbounds. A listening socket - * that accepts server type connections is represented by one - * class serverrec. Class serverrec will instantiate several - * objects of type ircd_connector to represent each established - * connection, inbound or outbound. So, to determine all linked - * servers you must walk through all the serverrecs that the - * core defines, and in each one iterate through until you find - * connection(s) relating to the server you want information on. - * The core and module API provide functions for this. - */ -class ircd_connector : public Extensible -{ - private: - /** Sockaddr of the outbound ip and port - */ - sockaddr_in addr; - - /** File descriptor of the connection - */ - int fd; - - /** Server name - */ - std::string servername; - - /** Server 'GECOS' - */ - std::string description; - - /** State. STATE_NOAUTH_INBOUND, STATE_NOAUTH_OUTBOUND - * STATE_SYNC, STATE_DISCONNECTED, STATE_CONNECTED - */ - char state; - - /** PRIVATE function to set the host address and port to connect to - */ - bool SetHostAddress(char* host, int port); - - /** This string holds the ircd's version response - */ - std::string version; - - /** SendQ of the outbound connector, does not have a limit - */ - std::string sendq; - - /** Write error of connection - */ - std::string WriteError; - - /** Time this connection was last pinged - */ - time_t nextping; - - /** Did this connection reply to its last ping? - */ - bool replied; - - public: - - /** IRCD Buffer for input characters, holds as many lines as are - * pending - Note that the final line may not be complete and should - * only be read when there is a \n seperator. - */ - std::string ircdbuffer; - - - /** When MakeOutboundConnection is called, these public members are - * filled with the details passed to the function, for future - * reference - */ - char host[MAXBUF]; - - /** When MakeOutboundConnection is called, these public members are - * filled with the details passed to the function, for future - * reference - */ - int port; - - /** Server names of servers that this server is linked to - * So for A->B->C, if this was the record for B it would contain A and C - * whilever both servers are connected to B. - */ - std::vector routes; - - /** Constructor clears the sendq and initialises the fd to -1 - */ - ircd_connector(); - - /** Create an outbound connection to a listening socket - */ - bool MakeOutboundConnection(char* newhost, int newport); - - /** Return the servername on this established connection - */ - std::string GetServerName(); - - /** Set the server name of this connection - * @param serv The server name to set - */ - void SetServerName(std::string serv); - - /** Get the file descriptor associated with this connection - * @return The file descriptor associated with this connection - */ - int GetDescriptor(); - - /** Set the file descriptor for this connection - * @param fd The file descriptor to associate with the connection - */ - void SetDescriptor(int fd); - - /** Get the state flags for this connection - * @return The state flags associated with this connection - */ - int GetState(); - - /** Set the state flags for this connection - * @param state The state flags to set for this connection - */ - void SetState(int state); - - /** Get the ip address (not servername) associated with this connection - * @return The connections IP address in dotted decimal form - */ - char* GetServerIP(); - - /** Get the server description of this connection - * @return The description (GECOS) of this connection - */ - std::string GetDescription(); - - /** Set the server description of this connection - * @param desc The description (GECOS) of this connection to be set - */ - void SetDescription(std::string desc); - - /** Get the port number being used for this connection - * If the connection is outbound this will be the remote port - * otherwise it will be the local port, so it can always be - * gautanteed as open at the address given in GetServerIP(). - * - * @return The port number of this connection - */ - int GetServerPort(); - - /** Set the port used by this connection - * @param p The port number to set for this connection - */ - void SetServerPort(int p); - - /** Set both the host and the port in one operation for this connection - * @param newhost The hostname to set for this connection - * @param newport The port number to set for this connection - * @return True on success, false on failure - */ - bool SetHostAndPort(char* newhost, int newport); - - /** Close the connection by calling close() on its file descriptor - * This function call updates no other data. - */ - void CloseConnection(); - - /** This method adds text to the ircd connection's buffer - * @param a The text to add to the buffer up to a maximum size of 1MB - * - * This buffer's maximum size is one megabyte, the method returning false - * if the buffer is full. - * - * @return True on success, false if the buffer is full or the connection is down - */ - bool AddBuffer(std::string a); - - /** This method returns true if the buffer contains at least one - * carriage return character, e.g. one line can be read from the - * buffer successfully. - * - * @return True if there is at least one complete line waiting to be processed - */ - bool BufferIsComplete(); - - /** This method clears the server's buffer by setting it to an empty string. - */ - void ClearBuffer(); - - /** This method retrieves the first string from the tail end of the - * buffer and advances the tail end of the buffer past the returned - * string, in a similar manner to strtok(). - * - * @return The first line of the buffer up to a carriage return - */ - std::string GetBuffer(); - - /** This method sets the version string of the remote server - * @param newversion The version string to set - */ - void SetVersionString(std::string newversion); - - /** This method returns the version string of the remote server. - * If the server has no version string an empty string is returned. - * - * @return The version text of this connection - */ - std::string GetVersionString(); - - /** Adds data to the connection's sendQ to be flushed later. - * @param data The data to add to the write buffer - * - * Fails if there is an error pending on the connection. - * - * @return True on success, false if the connection is down or the buffer is full - */ - bool AddWriteBuf(std::string data); - - /** Flushes as much of the data from the buffer as possible, - * and advances the queue pointer to what is left. - * - * @return True if the flush succeeded, false if the connection is down - */ - bool FlushWriteBuf(); - - /** Sets the error string for this connection - * @param error The error string to set - */ - void SetWriteError(std::string error); - - /** Gets the error string for this connection - * @return The last error to occur or an empty string - */ - std::string GetWriteError(); - - /** Returns true if there is data to be written that hasn't been sent yet - * @return True if the buffer is not empty - */ - bool HasBufferedOutput(); - - /** Checks if the connection replied to its last ping, and if it did - * sends another and returns true, if not, returns false. - * @return True if the server is still replying to pings - */ - bool CheckPing(); - - /** Resets the ping counter - */ - void ResetPing(); -}; - - -/** Please note: classes serverrec and userrec both inherit from class connection. - */ -class connection : public Extensible -{ - public: - /** File descriptor of the connection - */ - int fd; - - /** Hostname of connection. Not used if this is a serverrec - */ - char host[160]; - - /** IP of connection. - */ - char ip[16]; - - /** Stats counter for bytes inbound - */ - int bytes_in; - - /** Stats counter for bytes outbound - */ - int bytes_out; - - /** Stats counter for commands inbound - */ - int cmds_in; - - /** Stats counter for commands outbound - */ - int cmds_out; - - /** True if server/user has authenticated, false if otherwise - */ - bool haspassed; - - /** Port number - * For a userrec, this is the port they connected to the network on. - * For a serverrec this is the current listening port of the serverrec object. - */ - int port; - - /** Used by userrec to indicate the registration status of the connection - */ - char registered; - - /** Time the connection was last pinged - */ - time_t lastping; - - /** Time the connection was created, set in the constructor - */ - time_t signon; - - /** Time that the connection last sent data, used to calculate idle time - */ - time_t idle_lastmsg; - - /** Used by PING checks with clients - */ - time_t nping; - - /** Default constructor - */ - connection(); -}; - - -#endif diff --git a/include/servers.h b/include/servers.h deleted file mode 100644 index e9940704c..000000000 --- a/include/servers.h +++ /dev/null @@ -1,126 +0,0 @@ -/* +------------------------------------+ - * | 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 "inspircd_config.h" -#include "connection.h" -#include -#include - -#ifndef __SERVERS_H__ -#define __SERVERS_H__ - -#define LINK_ACTIVE 1 -#define LINK_INACTIVE 0 - -/** A class that defines the local server or a remote server - */ -class serverrec : public connection -{ - private: - public: - /** server name - */ - char name[MAXBUF]; - /** last ping response (ms) - */ - long pingtime; - /** invisible users on server - */ - long usercount_i; - /** non-invisible users on server - */ - long usercount; - /** opers on server - */ - long opercount; - /** number of hops away (for quick access) - */ - int hops_away; - /** ircd version - */ - long version; - /** is a JUPE server (faked to enforce a server ban) - */ - bool jupiter; - - /** Description of the server - */ - char description[MAXBUF]; - - /** Holds nickserv's name on U:lined (services) servers (this is a kludge for ircservices which ASSUMES things :/) - */ - char nickserv[NICKMAX]; - - bool sync_soon; - - /** Constructor - */ - serverrec(); - /** Constructor which initialises some of the main variables - */ - serverrec(char* n, long ver, bool jupe); - /** Destructor - */ - ~serverrec(); - - /** With a serverrec, this is a list of all established server connections. - */ - std::vector 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 &messages, char* host, std::deque &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); - - /** Flushes all data waiting to be written for all of this server's connections - */ - void FlushWriteBuffers(); -}; - -#endif - diff --git a/src/connection.cpp b/src/connection.cpp deleted file mode 100644 index f5640e5be..000000000 --- a/src/connection.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/* +------------------------------------+ - * | 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. - * - * --------------------------------------------------- - */ - -using namespace std; - -#include "inspircd.h" -#include "connection.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "modules.h" -#include "inspstring.h" -#include "helperfuncs.h" - -extern char ServerName[MAXBUF]; -extern serverrec* me[32]; -extern bool has_been_netsplit; -extern std::vector modules; -extern std::vector factory; - -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 = -1; -} - - -ircd_connector::ircd_connector() -{ - fd = -1; - port = 0; - sendq = ""; - WriteError = ""; - nextping = TIME+120; - replied = false; -} - -char* ircd_connector::GetServerIP() -{ - return this->host; -} - -int ircd_connector::GetServerPort() -{ - return this->port; -} - -bool ircd_connector::SetHostAndPort(char* newhost, int newport) -{ - strncpy(this->host,newhost,160); - this->port = newport; - return true; -} - -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; -} - -void ircd_connector::SetServerPort(int p) -{ - this->port = p; -} - -bool ircd_connector::AddBuffer(std::string a) -{ - std::string b = ""; - for (unsigned 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(); - return (ircdbuffer.length() < 1048576); -} - -bool ircd_connector::BufferIsComplete() -{ - for (unsigned int i = 0; i < ircdbuffer.length(); i++) - if (ircdbuffer[i] == '\n') - return true; - return false; -} - -void ircd_connector::ClearBuffer() -{ - ircdbuffer = ""; -} - -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; -} - -bool ircd_connector::AddWriteBuf(std::string data) -{ - log(DEBUG,"connector::AddWriteBuf(%s)",data.c_str()); - if (this->GetWriteError() != "") - return false; - if (this->GetState() == STATE_DISCONNECTED) - return false; - std::stringstream stream; - stream << sendq << data; - sendq = stream.str(); - return (sendq.length() < 1048576); -} - -bool ircd_connector::HasBufferedOutput() -{ - return (sendq.length() > 0); -} - -bool ircd_connector::CheckPing() -{ - if (TIME > this->nextping) - { - if (this->replied) - { - this->AddWriteBuf("?\n"); - this->nextping = TIME+120; - this->replied = false; - return true; - } - else - { - if (this->GetState() == STATE_CONNECTED) - { - this->SetWriteError("Ping timeout"); - this->CloseConnection(); - this->SetState(STATE_DISCONNECTED); - WriteOpers("*** Ping timeout on link to %s (more routes may remain)",this->GetServerName().c_str()); - has_been_netsplit = true; - return false; - } - } - } - return true; -} - -void ircd_connector::ResetPing() -{ - log(DEBUG,"Reset ping counter"); - this->replied = true; - this->nextping = TIME+120; -} - -// send AS MUCH OF THE USERS SENDQ as we are able to (might not be all of it) -bool ircd_connector::FlushWriteBuf() -{ - char buffer[MAXBUF]; - if ((this->GetState() == STATE_NOAUTH_OUTBOUND) || (this->GetState() == STATE_COOKIE_OUTBOUND)) - { - // if the outbound socket hasnt connected yet... return true and don't - // actually do anything until it IS connected. This should probably - // have a timeout somewhere, 10 secs should suffice. ;-) - pollfd polls; - polls.fd = this->fd; - polls.events = POLLOUT; - int ret = poll(&polls,1,1); - if (ret < 1) - return true; - // this falls through and sends any waiting data, which can put it into the - // connected state. - if (this->GetState() == STATE_COOKIE_OUTBOUND) - { - log(DEBUG,"Moving cookie_outbound into STATE_CONNECTED state"); - this->SetState(STATE_CONNECTED); - for (int t = 0; t < 32; t++) if (me[t]) for (unsigned int l = 0; l < me[t]->connectors.size(); l++) - { - if (me[t]->connectors[l].GetDescription() != "") - { - snprintf(buffer,MAXBUF,"%s = %s :%s\r\n",CreateSum().c_str(),me[t]->connectors[l].GetServerName().c_str(),me[t]->connectors[l].GetDescription().c_str()); - this->AddWriteBuf(buffer); - } - } - } - snprintf(buffer,MAXBUF,"%s v %s %s\r\n",CreateSum().c_str(),ServerName,GetVersionString().c_str()); - this->AddWriteBuf(buffer); - } - if ((sendq.length()) && (this->GetState() != STATE_DISCONNECTED)) - { - char* tb = (char*)this->sendq.c_str(); - int n_sent = write(this->fd,tb,this->sendq.length()); - if (n_sent != 0) - { - if (n_sent == -1) - { - this->SetWriteError(strerror(errno)); - return false; - } - else - { - log(DEBUG,"Wrote %d chars to socket",n_sent); - // advance the queue - tb += n_sent; - this->sendq = tb; - return true; - } - } - } - return true; -} - -void ircd_connector::SetWriteError(std::string error) -{ - if (this->WriteError == "") - this->WriteError = error; -} - -std::string ircd_connector::GetWriteError() -{ - return this->WriteError; -} - - -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); - } - - this->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (this->fd >= 0) - { - int flags = fcntl(this->fd, F_GETFL, 0); - fcntl(this->fd, F_SETFL, flags | O_NONBLOCK); - if(connect(this->fd, (sockaddr*)&this->addr,sizeof(this->addr)) == -1) - { - if (errno != EINPROGRESS) - { - WriteOpers("connect() failed for %s",host); - return false; - } - } - 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; - } - else - { - WriteOpers("socket() failed!"); - } - - 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; -} - - -std::string ircd_connector::GetServerName() -{ - return this->servername; -} - -std::string ircd_connector::GetDescription() -{ - return this->description; -} - -void ircd_connector::SetServerName(std::string serv) -{ - this->servername = serv; -} - -void ircd_connector::SetDescription(std::string desc) -{ - this->description = desc; -} - - -int ircd_connector::GetDescriptor() -{ - return this->fd; -} - -int ircd_connector::GetState() -{ - return this->state; -} - - -void ircd_connector::SetState(int newstate) -{ - this->state = newstate; -} - -void ircd_connector::CloseConnection() -{ - log(DEBUG,"Closing connection"); - // flush the queues - shutdown(this->fd,2); - close(this->fd); -} - -void ircd_connector::SetDescriptor(int newfd) -{ - this->fd = newfd; -} diff --git a/src/servers.cpp b/src/servers.cpp deleted file mode 100644 index f392c9510..000000000 --- a/src/servers.cpp +++ /dev/null @@ -1,548 +0,0 @@ -/* +------------------------------------+ - * | 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. - * - * --------------------------------------------------- - */ - -using namespace std; - -#include "inspircd_config.h" -#include "servers.h" -#include "inspircd.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "inspstring.h" -#include "helperfuncs.h" -#include "connection.h" - -extern time_t TIME; -extern int MaxConn; - -extern serverrec* me[32]; - -extern bool has_been_netsplit; - -std::deque xsums; - -serverrec::serverrec() -{ - strlcpy(name,"",256); - pingtime = 0; - lastping = TIME; - usercount_i = usercount = opercount = version = 0; - hops_away = 1; - signon = TIME; - jupiter = false; - fd = 0; - sync_soon = false; - strlcpy(nickserv,"",NICKMAX); - connectors.clear(); -} - - -serverrec::~serverrec() -{ -} - -serverrec::serverrec(char* n, long ver, bool jupe) -{ - strlcpy(name,n,256); - lastping = TIME; - usercount_i = usercount = opercount = 0; - version = ver; - hops_away = 1; - signon = TIME; - jupiter = 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, MaxConn); - - 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 %s :%s",getservername().c_str(),password,(unsigned long)myport,GetRevision().c_str(),getserverdesc().c_str()); - connector.SetState(STATE_NOAUTH_OUTBOUND); - connector.SetHostAndPort(targethost, newport); - this->connectors.push_back(connector); - // this packet isn't actually sent until the socket connects -- the STATE_NOAUTH_OUTBOUND state - // queues outbound data until the socket is polled as writeable (e.g. the connection is established) - return this->SendPacket(connect, servername); - } - else - { - connector.SetState(STATE_DISCONNECTED); - WriteOpers("Could not create outbound connection to %s:%d",targethost,newport); - return false; - } - } - 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_COOKIE_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::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 (unsigned int i = 0; i < this->connectors.size(); i++) - { - if (this->connectors[i].GetServerName() == findhost) - { - return &this->connectors[i]; - } - } - return NULL; -} - - -// Checks to see if we can still reach a server at all (e.g. is it in ANY routing table?) -bool IsRoutable(std::string servername) -{ - int c = 0; - for (int x = 0; x < 32; x++) - if (me[x]) - { - for (unsigned int i = 0; i < me[x]->connectors.size(); i++) - { - if ((me[x]->connectors[i].GetServerName() == servername) && (me[x]->connectors[i].GetState() != STATE_DISCONNECTED)) - { - c++; - } - } - } - return (c != 0); -} - - -void serverrec::FlushWriteBuffers() -{ - char buffer[MAXBUF]; - for (unsigned int i = 0; i < this->connectors.size(); i++) - { - // don't try and ping a NOAUTH_OUTBOUND state, its not authed yet! - if ((this->connectors[i].GetState() == STATE_NOAUTH_OUTBOUND) && (TIME > this->connectors[i].age+30)) - { - // however if we reach this timer its connected timed out :) - WriteOpers("*** Connection to %s timed out",this->connectors[i].GetServerName().c_str()); - return; - } - if ((this->connectors[i].GetState() == STATE_NOAUTH_INBOUND) && (TIME > this->connectors[i].age+30)) - { - WriteOpers("*** Connection from %s timed out",this->connectors[i].GetServerName().c_str()); - return; - } - if (this->connectors[i].GetState() != STATE_DISCONNECTED) - { - if (!this->connectors[i].CheckPing()) - { - WriteOpers("*** Lost single connection to %s: Ping timeout",this->connectors[i].GetServerName().c_str()); - this->connectors[i].SetState(STATE_DISCONNECTED); - if (!IsRoutable(this->connectors[i].GetServerName())) - { - WriteOpers("*** Server %s is no longer routable, disconnecting.",this->connectors[i].GetServerName().c_str()); - } - this->connectors[i].CloseConnection(); - has_been_netsplit = true; - } - } - if ((this->connectors[i].GetWriteError() !="") && (this->connectors[i].GetState() != STATE_DISCONNECTED)) - { - // if we're here the write() caused an error, we cannot proceed - WriteOpers("*** Lost single connection to %s, link inactive and retrying: %s",this->connectors[i].GetServerName().c_str(),this->connectors[i].GetWriteError().c_str()); - this->connectors[i].SetState(STATE_DISCONNECTED); - if (!IsRoutable(this->connectors[i].GetServerName())) - { - WriteOpers("*** Server %s is no longer routable, disconnecting.",this->connectors[i].GetServerName().c_str()); - } - this->connectors[i].CloseConnection(); - has_been_netsplit = true; - } - if ((this->connectors[i].HasBufferedOutput()) && (this->connectors[i].GetState() != STATE_DISCONNECTED)) - { - if (!this->connectors[i].FlushWriteBuf()) - { - // if we're here the write() caused an error, we cannot proceed - WriteOpers("*** Lost single connection to %s, link inactive and retrying: %s",this->connectors[i].GetServerName().c_str(),this->connectors[i].GetWriteError().c_str()); - this->connectors[i].SetState(STATE_DISCONNECTED); - if (!IsRoutable(this->connectors[i].GetServerName())) - { - WriteOpers("*** Server %s is no longer routable, disconnecting.",this->connectors[i].GetServerName().c_str()); - } - this->connectors[i].CloseConnection(); - has_been_netsplit = true; - } - } - } -} - -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) - { - // 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 (unsigned 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 (unsigned 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()); - if (this->connectors[k].GetState() != STATE_DISCONNECTED) - { - char buffer[MAXBUF]; - snprintf(buffer,MAXBUF,"R %s %s",sendhost,message); - this->SendPacket(buffer,this->connectors[k].GetServerName().c_str()); - return true; - } - else - { - log(DEBUG,"Nope, this route is down..."); - return false; - } - } - } - } - } - char buffer[MAXBUF]; - snprintf(buffer,MAXBUF,"& %s",sendhost); - return false; - } - - // returns false if the packet could not be sent (e.g. target host down) - if (!cn->AddWriteBuf(message)) - { - // if we're here, there was an error pending, and the send cannot proceed - log(DEBUG,"cn->AddWriteBuf() failed for serverrec::SendPacket(): %s",cn->GetWriteError().c_str()); - log(DEBUG,"Disabling connector: %s",cn->GetServerName().c_str()); - cn->CloseConnection(); - cn->SetState(STATE_DISCONNECTED); - WriteOpers("*** Lost single connection to %s, link inactive and retrying: %s",cn->GetServerName().c_str(),cn->GetWriteError().c_str()); - // retry the packet along a new route so either arrival OR failure are gauranteed (bugfix) - return this->SendPacket(message,sendhost); - } - if (!cn->FlushWriteBuf()) - { - // if we're here the write() caused an error, we cannot proceed - log(DEBUG,"cn->FlushWriteBuf() failed for serverrec::SendPacket(): %s",cn->GetWriteError().c_str()); - log(DEBUG,"Disabling connector: %s",cn->GetServerName().c_str()); - cn->CloseConnection(); - cn->SetState(STATE_DISCONNECTED); - WriteOpers("*** Lost single connection to %s, link inactive and retrying: %s",cn->GetServerName().c_str(),cn->GetWriteError().c_str()); - // retry the packet along a new route so either arrival OR failure are gauranteed - return this->SendPacket(message,sendhost); - } - return true; - } - return false; -} - -bool already_have_sum(std::string sum) -{ - for (unsigned 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 &messages, char* recvhost,std::deque &sums) -{ - char data[65536],buffer[MAXBUF]; - memset(data, 0, 65536); - for (unsigned 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 == 0) - { - log(DEBUG,"recv() failed for serverrec::RecvPacket(): EOF"); - std::string sn = this->connectors[i].GetServerName(); - log(DEBUG,"Disabling connector: %s",sn.c_str()); - this->connectors[i].SetState(STATE_DISCONNECTED); - if (!IsRoutable(sn)) - { - WriteOpers("*** Server %s is no longer routable, disconnecting (EOF)",sn.c_str()); - } - this->connectors[i].CloseConnection(); - has_been_netsplit = true; - } - if (rcvsize == -1) - { - if (errno != EAGAIN) - { - log(DEBUG,"recv() failed for serverrec::RecvPacket(): %s",strerror(errno)); - std::string sn = this->connectors[i].GetServerName(); - log(DEBUG,"Disabling connector: %s",sn.c_str()); - this->connectors[i].SetState(STATE_DISCONNECTED); - if (!IsRoutable(sn)) - { - WriteOpers("*** Server %s is no longer routable, disconnecting.",sn.c_str()); - } - has_been_netsplit = true; - this->connectors[i].CloseConnection(); - } - } - int pushed = 0; - if (rcvsize > 0) - { - if (!this->connectors[i].AddBuffer(data)) - { - std::string sn = this->connectors[i].GetServerName(); - WriteOpers("*** Read buffer for %s exceeds maximum, closing connection!",sn.c_str()); - this->connectors[i].SetState(STATE_DISCONNECTED); - if (!IsRoutable(sn)) - { - WriteOpers("*** Server %s is no longer routable, disconnecting.",sn.c_str()); - } - has_been_netsplit = true; - this->connectors[i].CloseConnection(); - } - if (this->connectors[i].BufferIsComplete()) - { - this->connectors[i].ResetPing(); - 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; -} - -- cgit v1.2.3