#include <servers.h>
Inheritance diagram for serverrec:
Public Member Functions | |
serverrec () | |
Constructor. | |
serverrec (char *n, long ver, bool jupe) | |
Constructor which initialises some of the main variables. | |
~serverrec () | |
Destructor. | |
bool | CreateListener (char *host, int p) |
Create a listening socket on 'host' using port number 'p'. | |
bool | BeginLink (char *targethost, int port, char *password, char *servername, int myport) |
Begin an outbound link to another ircd at targethost. | |
bool | MeshCookie (char *targethost, int port, unsigned long cookie, char *servername) |
Begin an outbound mesh link to another ircd on a network you are already an authenticated member of. | |
void | TerminateLink (char *targethost) |
Terminate a link to 'targethost' by calling the ircd_connector::CloseConnection method. | |
bool | SendPacket (char *message, const char *host) |
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 | RecvPacket (std::deque< std::string > &messages, char *host, std::deque< std::string > &sums) |
Returns the next available packet and returns true if data is available. | |
ircd_connector * | FindHost (std::string host) |
Find the ircd_connector oject related to a certain servername given in 'host'. | |
bool | AddIncoming (int fd, char *targethost, int sourceport) |
Add an incoming connection to the connection pool. | |
void | FlushWriteBuffers () |
Flushes all data waiting to be written for all of this server's connections. | |
Public Attributes | |
char | name [MAXBUF] |
server name | |
long | pingtime |
last ping response (ms) | |
long | usercount_i |
invisible users on server | |
long | usercount |
non-invisible users on server | |
long | opercount |
opers on server | |
int | hops_away |
number of hops away (for quick access) | |
long | version |
ircd version | |
bool | jupiter |
is a JUPE server (faked to enforce a server ban) | |
char | description [MAXBUF] |
Description of the server. | |
char | nickserv [NICKMAX] |
Holds nickserv's name on U:lined (services) servers (this is a kludge for ircservices which ASSUMES things :/). | |
bool | sync_soon |
std::vector< ircd_connector > | connectors |
With a serverrec, this is a list of all established server connections. |
Definition at line 30 of file servers.h.
|
Constructor.
Definition at line 46 of file servers.cpp. References connectors, connection::fd, hops_away, jupiter, connection::lastping, name, nickserv, opercount, pingtime, connection::signon, sync_soon, TIME, usercount, usercount_i, and version.
00047 { 00048 strlcpy(name,"",256); 00049 pingtime = 0; 00050 lastping = TIME; 00051 usercount_i = usercount = opercount = version = 0; 00052 hops_away = 1; 00053 signon = TIME; 00054 jupiter = false; 00055 fd = 0; 00056 sync_soon = false; 00057 strlcpy(nickserv,"",NICKMAX); 00058 connectors.clear(); 00059 } |
|
Constructor which initialises some of the main variables.
Definition at line 66 of file servers.cpp. References connectors, connection::fd, hops_away, jupiter, connection::lastping, name, nickserv, opercount, connection::signon, sync_soon, TIME, usercount, usercount_i, and version.
|
|
Destructor.
Definition at line 62 of file servers.cpp.
00063 { 00064 } |
|
Add an incoming connection to the connection pool. (reserved for core use) Definition at line 212 of file servers.cpp. References connectors, DEBUG, ircd_connector::SetDescriptor(), ircd_connector::SetHostAndPort(), ircd_connector::SetServerName(), ircd_connector::SetState(), and STATE_NOAUTH_INBOUND.
00213 { 00214 ircd_connector connector; 00215 00216 // targethost has been turned into an ip... 00217 // we dont want this as the server name. 00218 connector.SetServerName(targethost); 00219 connector.SetDescriptor(newfd); 00220 connector.SetState(STATE_NOAUTH_INBOUND); 00221 int flags = fcntl(newfd, F_GETFL, 0); 00222 fcntl(newfd, F_SETFL, flags | O_NONBLOCK); 00223 int sendbuf = 32768; 00224 int recvbuf = 32768; 00225 setsockopt(newfd,SOL_SOCKET,SO_SNDBUF,(const void *)&sendbuf,sizeof(sendbuf)); 00226 setsockopt(newfd,SOL_SOCKET,SO_RCVBUF,(const void *)&recvbuf,sizeof(sendbuf)); 00227 connector.SetHostAndPort(targethost, sourceport); 00228 connector.SetState(STATE_NOAUTH_INBOUND); 00229 log(DEBUG,"serverrec::AddIncoming() Added connection: %s:%d",targethost,sourceport); 00230 this->connectors.push_back(connector); 00231 return true; 00232 } |
|
Begin an outbound link to another ircd at targethost.
Definition at line 142 of file servers.cpp. References connectors, connection::fd, FindHost(), ircd_connector::MakeOutboundConnection(), SendPacket(), ircd_connector::SetHostAndPort(), ircd_connector::SetServerName(), ircd_connector::SetState(), STATE_DISCONNECTED, and STATE_NOAUTH_OUTBOUND.
00143 { 00144 char connect[MAXBUF]; 00145 00146 ircd_connector connector; 00147 ircd_connector *cn = this->FindHost(servername); 00148 00149 00150 if (cn) 00151 { 00152 WriteOpers("CONNECT aborted: Server %s already exists",servername); 00153 return false; 00154 } 00155 00156 00157 if (this->fd) 00158 { 00159 if (connector.MakeOutboundConnection(targethost,newport)) 00160 { 00161 // targethost has been turned into an ip... 00162 // we dont want this as the server name. 00163 connector.SetServerName(servername); 00164 snprintf(connect,MAXBUF,"S %s %s %lu %s :%s",getservername().c_str(),password,(unsigned long)myport,GetRevision().c_str(),getserverdesc().c_str()); 00165 connector.SetState(STATE_NOAUTH_OUTBOUND); 00166 connector.SetHostAndPort(targethost, newport); 00167 this->connectors.push_back(connector); 00168 // this packet isn't actually sent until the socket connects -- the STATE_NOAUTH_OUTBOUND state 00169 // queues outbound data until the socket is polled as writeable (e.g. the connection is established) 00170 return this->SendPacket(connect, servername); 00171 } 00172 else 00173 { 00174 connector.SetState(STATE_DISCONNECTED); 00175 WriteOpers("Could not create outbound connection to %s:%d",targethost,newport); 00176 } 00177 } 00178 return false; 00179 } |
|
Create a listening socket on 'host' using port number 'p'.
Definition at line 81 of file servers.cpp. References connection::fd, MaxConn, and connection::port.
00082 { 00083 sockaddr_in host_address; 00084 int flags; 00085 in_addr addy; 00086 int on = 0; 00087 struct linger linger = { 0 }; 00088 00089 this->port = p; 00090 00091 fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 00092 if (fd <= 0) 00093 { 00094 return false; 00095 } 00096 00097 setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(const char*)&on,sizeof(on)); 00098 linger.l_onoff = 1; 00099 linger.l_linger = 1; 00100 setsockopt(fd,SOL_SOCKET,SO_LINGER,(const char*)&linger,sizeof(linger)); 00101 00102 // attempt to increase socket sendq and recvq as high as its possible 00103 // to get them on linux. 00104 int sendbuf = 32768; 00105 int recvbuf = 32768; 00106 setsockopt(fd,SOL_SOCKET,SO_SNDBUF,(const void *)&sendbuf,sizeof(sendbuf)); 00107 setsockopt(fd,SOL_SOCKET,SO_RCVBUF,(const void *)&recvbuf,sizeof(sendbuf)); 00108 00109 memset((void*)&host_address, 0, sizeof(host_address)); 00110 00111 host_address.sin_family = AF_INET; 00112 00113 if (!strcmp(newhost,"")) 00114 { 00115 host_address.sin_addr.s_addr = htonl(INADDR_ANY); 00116 } 00117 else 00118 { 00119 inet_aton(newhost,&addy); 00120 host_address.sin_addr = addy; 00121 } 00122 00123 host_address.sin_port = htons(p); 00124 00125 if (bind(fd,(sockaddr*)&host_address,sizeof(host_address))<0) 00126 { 00127 return false; 00128 } 00129 00130 // make the socket non-blocking 00131 flags = fcntl(fd, F_GETFL, 0); 00132 fcntl(fd, F_SETFL, flags | O_NONBLOCK); 00133 00134 this->port = p; 00135 00136 listen(this->fd, MaxConn); 00137 00138 return true; 00139 } |
|
Find the ircd_connector oject related to a certain servername given in 'host'.
Definition at line 242 of file servers.cpp. References connectors. Referenced by BeginLink(), IsRoutable(), and SendPacket().
00243 { 00244 for (int i = 0; i < this->connectors.size(); i++) 00245 { 00246 if (this->connectors[i].GetServerName() == findhost) 00247 { 00248 return &this->connectors[i]; 00249 } 00250 } 00251 return NULL; 00252 } |
|
Flushes all data waiting to be written for all of this server's connections.
Definition at line 284 of file servers.cpp. References connectors, has_been_netsplit, IsRoutable(), STATE_DISCONNECTED, STATE_NOAUTH_INBOUND, STATE_NOAUTH_OUTBOUND, and TIME.
00285 { 00286 for (int i = 0; i < this->connectors.size(); i++) 00287 { 00288 // don't try and ping a NOAUTH_OUTBOUND state, its not authed yet! 00289 if ((this->connectors[i].GetState() == STATE_NOAUTH_OUTBOUND) && (TIME > this->connectors[i].age+30)) 00290 { 00291 // however if we reach this timer its connected timed out :) 00292 WriteOpers("*** Connection to %s timed out",this->connectors[i].GetServerName().c_str()); 00293 DoSplit(this->connectors[i].GetServerName().c_str()); 00294 return; 00295 } 00296 else if ((this->connectors[i].GetState() == STATE_NOAUTH_INBOUND) && (TIME > this->connectors[i].age+30)) 00297 { 00298 WriteOpers("*** Connection from %s timed out",this->connectors[i].GetServerName().c_str()); 00299 DoSplit(this->connectors[i].GetServerName().c_str()); 00300 return; 00301 } 00302 else if (this->connectors[i].GetState() != STATE_DISCONNECTED) 00303 { 00304 if (!this->connectors[i].CheckPing()) 00305 { 00306 WriteOpers("*** Lost single connection to %s: Ping timeout",this->connectors[i].GetServerName().c_str()); 00307 this->connectors[i].CloseConnection(); 00308 this->connectors[i].SetState(STATE_DISCONNECTED); 00309 if (!IsRoutable(this->connectors[i].GetServerName())) 00310 { 00311 WriteOpers("*** Server %s is no longer routable, disconnecting.",this->connectors[i].GetServerName().c_str()); 00312 DoSplit(this->connectors[i].GetServerName().c_str()); 00313 } 00314 has_been_netsplit = true; 00315 } 00316 } 00317 if (this->connectors[i].HasBufferedOutput()) 00318 { 00319 if (!this->connectors[i].FlushWriteBuf()) 00320 { 00321 // if we're here the write() caused an error, we cannot proceed 00322 WriteOpers("*** Lost single connection to %s, link inactive and retrying: %s",this->connectors[i].GetServerName().c_str(),this->connectors[i].GetWriteError().c_str()); 00323 this->connectors[i].CloseConnection(); 00324 this->connectors[i].SetState(STATE_DISCONNECTED); 00325 if (!IsRoutable(this->connectors[i].GetServerName())) 00326 { 00327 WriteOpers("*** Server %s is no longer routable, disconnecting.",this->connectors[i].GetServerName().c_str()); 00328 DoSplit(this->connectors[i].GetServerName().c_str()); 00329 } 00330 has_been_netsplit = true; 00331 } 00332 } 00333 } 00334 } |
|
Begin an outbound mesh link to another ircd on a network you are already an authenticated member of.
Definition at line 182 of file servers.cpp. References connectors, connection::fd, ircd_connector::MakeOutboundConnection(), SendPacket(), ircd_connector::SetHostAndPort(), ircd_connector::SetServerName(), ircd_connector::SetState(), STATE_DISCONNECTED, and STATE_NOAUTH_OUTBOUND.
00183 { 00184 char connect[MAXBUF]; 00185 00186 ircd_connector connector; 00187 00188 WriteOpers("Establishing meshed link to %s:%d",servername,newport); 00189 00190 if (this->fd) 00191 { 00192 if (connector.MakeOutboundConnection(targethost,newport)) 00193 { 00194 // targethost has been turned into an ip... 00195 // we dont want this as the server name. 00196 connector.SetServerName(servername); 00197 snprintf(connect,MAXBUF,"- %lu %s :%s",cookie,getservername().c_str(),getserverdesc().c_str()); 00198 connector.SetState(STATE_NOAUTH_OUTBOUND); 00199 connector.SetHostAndPort(targethost, newport); 00200 this->connectors.push_back(connector); 00201 return this->SendPacket(connect, servername); 00202 } 00203 else 00204 { 00205 connector.SetState(STATE_DISCONNECTED); 00206 WriteOpers("Could not create outbound connection to %s:%d",targethost,newport); 00207 } 00208 } 00209 return false; 00210 } |
|
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. Definition at line 431 of file servers.cpp. References already_have_sum(), connectors, DEBUG, has_been_netsplit, IsRoutable(), and STATE_DISCONNECTED.
00432 { 00433 char data[65536]; 00434 memset(data, 0, 65536); 00435 for (int i = 0; i < this->connectors.size(); i++) 00436 { 00437 if (this->connectors[i].GetState() != STATE_DISCONNECTED) 00438 { 00439 // returns false if the packet could not be sent (e.g. target host down) 00440 int rcvsize = 0; 00441 00442 // check if theres any data on this socket 00443 // if not, continue onwards to the next. 00444 pollfd polls; 00445 polls.fd = this->connectors[i].GetDescriptor(); 00446 polls.events = POLLIN; 00447 int ret = poll(&polls,1,1); 00448 if (ret <= 0) continue; 00449 00450 rcvsize = recv(this->connectors[i].GetDescriptor(),data,65000,0); 00451 data[rcvsize] = '\0'; 00452 if (rcvsize == -1) 00453 { 00454 if (errno != EAGAIN) 00455 { 00456 log(DEBUG,"recv() failed for serverrec::RecvPacket(): %s",strerror(errno)); 00457 log(DEBUG,"Disabling connector: %s",this->connectors[i].GetServerName().c_str()); 00458 this->connectors[i].CloseConnection(); 00459 this->connectors[i].SetState(STATE_DISCONNECTED); 00460 if (!IsRoutable(this->connectors[i].GetServerName())) 00461 { 00462 WriteOpers("*** Server %s is no longer routable, disconnecting.",this->connectors[i].GetServerName().c_str()); 00463 DoSplit(this->connectors[i].GetServerName().c_str()); 00464 } 00465 has_been_netsplit = true; 00466 } 00467 } 00468 int pushed = 0; 00469 if (rcvsize > 0) 00470 { 00471 if (!this->connectors[i].AddBuffer(data)) 00472 { 00473 WriteOpers("*** Read buffer for %s exceeds maximum, closing connection!",this->connectors[i].GetServerName().c_str()); 00474 this->connectors[i].CloseConnection(); 00475 this->connectors[i].SetState(STATE_DISCONNECTED); 00476 if (!IsRoutable(this->connectors[i].GetServerName())) 00477 { 00478 WriteOpers("*** Server %s is no longer routable, disconnecting.",this->connectors[i].GetServerName().c_str()); 00479 DoSplit(this->connectors[i].GetServerName().c_str()); 00480 } 00481 has_been_netsplit = true; 00482 } 00483 if (this->connectors[i].BufferIsComplete()) 00484 { 00485 this->connectors[i].ResetPing(); 00486 while (this->connectors[i].BufferIsComplete()) 00487 { 00488 std::string text = this->connectors[i].GetBuffer(); 00489 if (text != "") 00490 { 00491 if ((text[0] == ':') && (text.find(" ") != std::string::npos)) 00492 { 00493 std::string orig = text; 00494 log(DEBUG,"Original: %s",text.c_str()); 00495 std::string sum = text.substr(1,text.find(" ")-1); 00496 text = text.substr(text.find(" ")+1,text.length()); 00497 std::string possible_token = text.substr(1,text.find(" ")-1); 00498 if (possible_token.length() > 1) 00499 { 00500 sums.push_back("*"); 00501 text = orig; 00502 log(DEBUG,"Non-mesh, non-tokenized string passed up the chain"); 00503 } 00504 else 00505 { 00506 log(DEBUG,"Packet sum: '%s'",sum.c_str()); 00507 if ((already_have_sum(sum)) && (sum != "*")) 00508 { 00509 // we don't accept dupes 00510 continue; 00511 } 00512 sums.push_back(sum.c_str()); 00513 } 00514 } 00515 else sums.push_back("*"); 00516 messages.push_back(text.c_str()); 00517 strlcpy(recvhost,this->connectors[i].GetServerName().c_str(),160); 00518 log(DEBUG,"serverrec::RecvPacket() %d:%s->%s",pushed++,recvhost,text.c_str()); 00519 } 00520 } 00521 return true; 00522 } 00523 } 00524 } 00525 } 00526 // nothing new yet -- message and host will be undefined 00527 return false; 00528 } |
|
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.
Definition at line 336 of file servers.cpp. References ircd_connector::AddWriteBuf(), ircd_connector::CloseConnection(), connectors, DEBUG, FindHost(), ircd_connector::FlushWriteBuf(), ircd_connector::GetServerName(), ircd_connector::GetState(), ircd_connector::GetWriteError(), ircd_connector::SetState(), and STATE_DISCONNECTED. Referenced by BeginLink(), and MeshCookie().
00337 { 00338 if ((!message) || (!sendhost)) 00339 return true; 00340 00341 ircd_connector* cn = this->FindHost(sendhost); 00342 00343 if (!strchr(message,'\n')) 00344 { 00345 strlcat(message,"\n",MAXBUF); 00346 } 00347 00348 if (cn) 00349 { 00350 log(DEBUG,"main: serverrec::SendPacket() sent '%s' to %s",message,cn->GetServerName().c_str()); 00351 00352 if (cn->GetState() == STATE_DISCONNECTED) 00353 { 00354 // fix: can only route one hop to avoid a loop 00355 if (strncmp(message,"R ",2)) 00356 { 00357 log(DEBUG,"Not a double reroute"); 00358 // this route is down, we must re-route the packet through an available point in the mesh. 00359 for (int k = 0; k < this->connectors.size(); k++) 00360 { 00361 log(DEBUG,"Check connector %d: %s",k,this->connectors[k].GetServerName().c_str()); 00362 // search for another point in the mesh which can 'reach' where we want to go 00363 for (int m = 0; m < this->connectors[k].routes.size(); m++) 00364 { 00365 if (!strcasecmp(this->connectors[k].routes[m].c_str(),sendhost)) 00366 { 00367 log(DEBUG,"Found alternative route for packet: %s",this->connectors[k].GetServerName().c_str()); 00368 char buffer[MAXBUF]; 00369 snprintf(buffer,MAXBUF,"R %s %s",sendhost,message); 00370 this->SendPacket(buffer,this->connectors[k].GetServerName().c_str()); 00371 return true; 00372 } 00373 } 00374 } 00375 } 00376 char buffer[MAXBUF]; 00377 snprintf(buffer,MAXBUF,"& %s",sendhost); 00378 WriteOpers("*** All connections to %s lost.",sendhost); 00379 NetSendToAllExcept(sendhost,buffer); 00380 DoSplit(sendhost); 00381 return false; 00382 } 00383 00384 // returns false if the packet could not be sent (e.g. target host down) 00385 if (!cn->AddWriteBuf(message)) 00386 { 00387 // if we're here, there was an error pending, and the send cannot proceed 00388 log(DEBUG,"cn->AddWriteBuf() failed for serverrec::SendPacket(): %s",cn->GetWriteError().c_str()); 00389 log(DEBUG,"Disabling connector: %s",cn->GetServerName().c_str()); 00390 cn->CloseConnection(); 00391 cn->SetState(STATE_DISCONNECTED); 00392 WriteOpers("*** Lost single connection to %s, link inactive and retrying: %s",cn->GetServerName().c_str(),cn->GetWriteError().c_str()); 00393 // retry the packet along a new route so either arrival OR failure are gauranteed (bugfix) 00394 return this->SendPacket(message,sendhost); 00395 } 00396 if (!cn->FlushWriteBuf()) 00397 { 00398 // if we're here the write() caused an error, we cannot proceed 00399 log(DEBUG,"cn->FlushWriteBuf() failed for serverrec::SendPacket(): %s",cn->GetWriteError().c_str()); 00400 log(DEBUG,"Disabling connector: %s",cn->GetServerName().c_str()); 00401 cn->CloseConnection(); 00402 cn->SetState(STATE_DISCONNECTED); 00403 WriteOpers("*** Lost single connection to %s, link inactive and retrying: %s",cn->GetServerName().c_str(),cn->GetWriteError().c_str()); 00404 // retry the packet along a new route so either arrival OR failure are gauranteed 00405 return this->SendPacket(message,sendhost); 00406 } 00407 return true; 00408 } 00409 } |
|
Terminate a link to 'targethost' by calling the ircd_connector::CloseConnection method.
Definition at line 234 of file servers.cpp.
00235 { 00236 // this locates the targethost in the serverrec::connectors vector of the class, 00237 // and terminates it by sending it an SQUIT token and closing its descriptor. 00238 // TerminateLink with a null string causes a terminate of ALL links 00239 } |
|
With a serverrec, this is a list of all established server connections.
Definition at line 81 of file servers.h. Referenced by AddIncoming(), BeginLink(), FindHost(), FlushWriteBuffers(), IsRoutable(), MeshCookie(), RecvPacket(), SendPacket(), and serverrec(). |
|
Description of the server.
|
|
number of hops away (for quick access)
Definition at line 51 of file servers.h. Referenced by serverrec(). |
|
is a JUPE server (faked to enforce a server ban)
Definition at line 57 of file servers.h. Referenced by serverrec(). |
|
server name
Definition at line 36 of file servers.h. Referenced by serverrec(). |
|
Holds nickserv's name on U:lined (services) servers (this is a kludge for ircservices which ASSUMES things :/).
Definition at line 65 of file servers.h. Referenced by serverrec(). |
|
opers on server
Definition at line 48 of file servers.h. Referenced by serverrec(). |
|
last ping response (ms)
Definition at line 39 of file servers.h. Referenced by serverrec(). |
|
Definition at line 67 of file servers.h. Referenced by serverrec(). |
|
non-invisible users on server
Definition at line 45 of file servers.h. Referenced by serverrec(). |
|
invisible users on server
Definition at line 42 of file servers.h. Referenced by serverrec(). |
|
ircd version
Definition at line 54 of file servers.h. Referenced by serverrec(). |