From 90550c9c650276e2830f677b8d2a509c911b6bdd Mon Sep 17 00:00:00 2001 From: w00t Date: Tue, 29 May 2007 16:35:18 +0000 Subject: Commit multiaccept diff by myself to speed up large numbers of connections. git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@7183 e03df62e-2008-0410-955e-edbf42e46eb7 --- src/socket.cpp | 88 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 35 deletions(-) diff --git a/src/socket.cpp b/src/socket.cpp index 411465ad6..11a617e41 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -69,10 +69,9 @@ ListenSocket::~ListenSocket() void ListenSocket::HandleEvent(EventType et, int errornum) { - sockaddr* sock_us = new sockaddr[2]; // our port number - sockaddr* client = new sockaddr[2]; socklen_t uslen, length; // length of our port number int incomingSockfd, in_port; + int clients; #ifdef IPV6 if (this->family == AF_INET6) @@ -89,49 +88,68 @@ void ListenSocket::HandleEvent(EventType et, int errornum) uslen = sizeof(sockaddr_in); length = sizeof(sockaddr_in); #endif - incomingSockfd = _accept (this->GetFd(), (sockaddr*)client, &length); - if ((incomingSockfd > -1) && (!_getsockname(incomingSockfd, sock_us, &uslen))) + /* + * This loop may make you wonder 'why' - simple reason. If we just sit here accept()ing until the + * metaphorical cows come home, then we could very well end up with unresponsiveness in a ddos style + * situation, which is not desirable (to put it mildly!). This will mean we'll stop accepting and get + * on with our lives after accepting enough clients to sink a metaphorical battleship. :) -- w00t + */ + for (clients = 0; clients < ServerInstance->Config->MaxConn; clients++) { - char buf[MAXBUF]; -#ifdef IPV6 - if (this->family == AF_INET6) - { - inet_ntop(AF_INET6, &((const sockaddr_in6*)client)->sin6_addr, buf, sizeof(buf)); - in_port = ntohs(((sockaddr_in6*)sock_us)->sin6_port); - } - else + sockaddr* sock_us = new sockaddr[2]; // our port number + sockaddr* client = new sockaddr[2]; + + incomingSockfd = _accept (this->GetFd(), (sockaddr*)client, &length); + + if ((incomingSockfd > -1) && (!_getsockname(incomingSockfd, sock_us, &uslen))) { + char buf[MAXBUF]; +#ifdef IPV6 + if (this->family == AF_INET6) + { + inet_ntop(AF_INET6, &((const sockaddr_in6*)client)->sin6_addr, buf, sizeof(buf)); + in_port = ntohs(((sockaddr_in6*)sock_us)->sin6_port); + } + else + { + inet_ntop(AF_INET, &((const sockaddr_in*)client)->sin_addr, buf, sizeof(buf)); + in_port = ntohs(((sockaddr_in*)sock_us)->sin_port); + } +#else inet_ntop(AF_INET, &((const sockaddr_in*)client)->sin_addr, buf, sizeof(buf)); in_port = ntohs(((sockaddr_in*)sock_us)->sin_port); - } -#else - inet_ntop(AF_INET, &((const sockaddr_in*)client)->sin_addr, buf, sizeof(buf)); - in_port = ntohs(((sockaddr_in*)sock_us)->sin_port); #endif - NonBlocking(incomingSockfd); - if (ServerInstance->Config->GetIOHook(in_port)) - { - try - { - ServerInstance->Config->GetIOHook(in_port)->OnRawSocketAccept(incomingSockfd, buf, in_port); - } - catch (CoreException& modexcept) + NonBlocking(incomingSockfd); + if (ServerInstance->Config->GetIOHook(in_port)) { - ServerInstance->Log(DEBUG,"%s threw an exception: %s", modexcept.GetSource(), modexcept.GetReason()); + try + { + ServerInstance->Config->GetIOHook(in_port)->OnRawSocketAccept(incomingSockfd, buf, in_port); + } + catch (CoreException& modexcept) + { + ServerInstance->Log(DEBUG,"%s threw an exception: %s", modexcept.GetSource(), modexcept.GetReason()); + } } + ServerInstance->stats->statsAccept++; + userrec::AddClient(ServerInstance, incomingSockfd, in_port, false, this->family, client); } - ServerInstance->stats->statsAccept++; - userrec::AddClient(ServerInstance, incomingSockfd, in_port, false, this->family, client); - } - else - { - shutdown(incomingSockfd,2); - close(incomingSockfd); - ServerInstance->stats->statsRefused++; + else + { + /* + * bail, bail, bail! if we get here, accept failed, meaning something is hardcore wrong. + * cut our losses and don't try soak up any more clients during this loop iteration. -- w00t + */ + shutdown(incomingSockfd,2); + close(incomingSockfd); + ServerInstance->stats->statsRefused++; + return; + } + + delete[] client; + delete[] sock_us; } - delete[] client; - delete[] sock_us; } /* Match raw bytes using CIDR bit matching, used by higher level MatchCIDR() */ -- cgit v1.2.3