diff options
author | brain <brain@e03df62e-2008-0410-955e-edbf42e46eb7> | 2008-04-02 17:08:09 +0000 |
---|---|---|
committer | brain <brain@e03df62e-2008-0410-955e-edbf42e46eb7> | 2008-04-02 17:08:09 +0000 |
commit | 2db77cda56947d4ee0f913c8082f6607855ca713 (patch) | |
tree | f7f83c80f62adc4e3eb0f9f3b680229466c4352e | |
parent | d9d33e7246baf59241d083eb2c253e729390d205 (diff) |
Automatic detection and allocation of max fds. No longer needs recompile to change, just adjust it in your kernel or whatever and restart insp.
Please note that select and iocp socket engines do not support detection and are always set to FD_SETSIZE and 10240 descriptors respectively.
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@9263 e03df62e-2008-0410-955e-edbf42e46eb7
-rwxr-xr-x | configure | 1 | ||||
-rw-r--r-- | include/modules.h | 6 | ||||
-rw-r--r-- | include/socketengine.h | 4 | ||||
-rw-r--r-- | include/socketengines/socketengine_epoll.h | 2 | ||||
-rw-r--r-- | include/socketengines/socketengine_kqueue.h | 2 | ||||
-rw-r--r-- | include/socketengines/socketengine_ports.h | 2 | ||||
-rw-r--r-- | include/socketengines/socketengine_select.h | 2 | ||||
-rw-r--r-- | src/inspircd.cpp | 4 | ||||
-rw-r--r-- | src/modules/extra/m_ssl_gnutls.cpp | 18 | ||||
-rw-r--r-- | src/modules/extra/m_ssl_openssl.cpp | 16 | ||||
-rw-r--r-- | src/modules/extra/m_ziplink.cpp | 5 | ||||
-rw-r--r-- | src/socketengine.cpp | 1 | ||||
-rw-r--r-- | src/socketengines/socketengine_epoll.cpp | 35 | ||||
-rw-r--r-- | src/socketengines/socketengine_iocp.cpp | 3 | ||||
-rw-r--r-- | src/socketengines/socketengine_kqueue.cpp | 34 | ||||
-rw-r--r-- | src/socketengines/socketengine_ports.cpp | 34 | ||||
-rw-r--r-- | src/socketengines/socketengine_select.cpp | 15 | ||||
-rw-r--r-- | src/usermanager.cpp | 2 | ||||
-rw-r--r-- | src/users.cpp | 19 |
19 files changed, 150 insertions, 55 deletions
@@ -1224,7 +1224,6 @@ sub writefiles { #define MAXCLIENTS $config{MAX_CLIENT} #define MAXCLIENTS_S "$config{MAX_CLIENT}" #define SOMAXCONN_S "$config{_SOMAXCONN}" -#define MAX_DESCRIPTORS $config{MAX_DESCRIPTORS} #define NICKMAX $NL #define CHANMAX $CL #define MAXMODES $config{MAXI_MODES} diff --git a/include/modules.h b/include/modules.h index ce6e3fa21..efb9113aa 100644 --- a/include/modules.h +++ b/include/modules.h @@ -230,13 +230,9 @@ do { \ #define FD_MAGIC_NUMBER -42 /* Useful macros */ -#ifdef WINDOWS + /** Is a local user */ #define IS_LOCAL(x) ((x->GetFd() > -1)) -#else -/** Is a local user */ -#define IS_LOCAL(x) ((x->GetFd() > -1) && (x->GetFd() <= MAX_DESCRIPTORS)) -#endif /** Is a remote user */ #define IS_REMOTE(x) (x->GetFd() < 0) /** Is a module created user */ diff --git a/include/socketengine.h b/include/socketengine.h index 3acc7bd4f..f647f4df3 100644 --- a/include/socketengine.h +++ b/include/socketengine.h @@ -167,7 +167,9 @@ protected: int CurrentSetSize; /** Reference table, contains all current handlers */ - EventHandler* ref[MAX_DESCRIPTORS]; + EventHandler** ref; + + int MAX_DESCRIPTORS; public: double TotalEvents; diff --git a/include/socketengines/socketengine_epoll.h b/include/socketengines/socketengine_epoll.h index 87829582a..07d0e3621 100644 --- a/include/socketengines/socketengine_epoll.h +++ b/include/socketengines/socketengine_epoll.h @@ -33,7 +33,7 @@ class EPollEngine : public SocketEngine private: /** These are used by epoll() to hold socket events */ - struct epoll_event events[MAX_DESCRIPTORS]; + struct epoll_event* events; public: /** Create a new EPollEngine * @param Instance The creator of this object diff --git a/include/socketengines/socketengine_kqueue.h b/include/socketengines/socketengine_kqueue.h index 7ef24085a..49b51590a 100644 --- a/include/socketengines/socketengine_kqueue.h +++ b/include/socketengines/socketengine_kqueue.h @@ -34,7 +34,7 @@ class KQueueEngine : public SocketEngine private: /** These are used by kqueue() to hold socket events */ - struct kevent ke_list[MAX_DESCRIPTORS]; + struct kevent* ke_list; /** This is a specialised time value used by kqueue() */ struct timespec ts; diff --git a/include/socketengines/socketengine_ports.h b/include/socketengines/socketengine_ports.h index d055912e5..519eaad8b 100644 --- a/include/socketengines/socketengine_ports.h +++ b/include/socketengines/socketengine_ports.h @@ -36,7 +36,7 @@ class PortsEngine : public SocketEngine private: /** These are used by epoll() to hold socket events */ - port_event_t events[MAX_DESCRIPTORS]; + port_event_t* events; public: /** Create a new PortsEngine * @param Instance The creator of this object diff --git a/include/socketengines/socketengine_select.h b/include/socketengines/socketengine_select.h index 83d92d48f..3540c0944 100644 --- a/include/socketengines/socketengine_select.h +++ b/include/socketengines/socketengine_select.h @@ -37,7 +37,7 @@ private: std::map<int,int> fds; /** List of writeable ones (WantWrite()) */ - bool writeable[MAX_DESCRIPTORS]; + bool* writeable; /** The read set and write set, populated before each call to select(). */ fd_set wfdset, rfdset, errfdset; diff --git a/src/inspircd.cpp b/src/inspircd.cpp index 1d6986f57..f7f969835 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -581,8 +581,8 @@ InspIRCd::InspIRCd(int argc, char** argv) } #endif - printf("\nInspIRCd is now running as '%s'[%s]\n", Config->ServerName,Config->GetSID().c_str()); - Logs->Log("STARTUP", DEFAULT, "Startup complete as '%s'[%s]", Config->ServerName,Config->GetSID().c_str()); + printf("\nInspIRCd is now running as '%s'[%s] with %d max open sockets\n", Config->ServerName,Config->GetSID().c_str(), SE->GetMaxFds()); + Logs->Log("STARTUP", DEFAULT, "Startup complete as '%s'[%s], %d max open sockets", Config->ServerName,Config->GetSID().c_str(), SE->GetMaxFds()); this->WritePID(Config->PID); } diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp index 3f9c4ac5d..797019fd4 100644 --- a/src/modules/extra/m_ssl_gnutls.cpp +++ b/src/modules/extra/m_ssl_gnutls.cpp @@ -28,8 +28,6 @@ #ifdef WINDOWS #pragma comment(lib, "libgnutls-13.lib") -#undef MAX_DESCRIPTORS -#define MAX_DESCRIPTORS 10000 #endif /* $ModDesc: Provides SSL support for clients */ @@ -94,7 +92,7 @@ class ModuleSSLGnuTLS : public Module std::vector<std::string> listenports; int inbufsize; - issl_session sessions[MAX_DESCRIPTORS]; + issl_session* sessions; gnutls_certificate_credentials x509_cred; gnutls_dh_params dh_params; @@ -117,6 +115,8 @@ class ModuleSSLGnuTLS : public Module { ServerInstance->Modules->PublishInterface("BufferedSocketHook", this); + sessions = new issl_session[ServerInstance->SE->GetMaxFds()]; + // Not rehashable...because I cba to reduce all the sizes of existing buffers. inbufsize = ServerInstance->Config->NetBufferSize; @@ -270,6 +270,8 @@ class ModuleSSLGnuTLS : public Module gnutls_dh_params_deinit(dh_params); gnutls_certificate_free_credentials(x509_cred); gnutls_global_deinit(); + ServerInstance->Modules->UnpublishInterface("BufferedSocketHook", this); + delete[] sessions; } virtual void OnCleanup(int target_type, void* item) @@ -383,7 +385,7 @@ class ModuleSSLGnuTLS : public Module virtual void OnRawSocketAccept(int fd, const std::string &ip, int localport) { /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1)) return; issl_session* session = &sessions[fd]; @@ -416,7 +418,7 @@ class ModuleSSLGnuTLS : public Module virtual void OnRawSocketConnect(int fd) { /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1)) return; issl_session* session = &sessions[fd]; @@ -438,7 +440,7 @@ class ModuleSSLGnuTLS : public Module virtual void OnRawSocketClose(int fd) { /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds())) return; CloseSession(&sessions[fd]); @@ -457,7 +459,7 @@ class ModuleSSLGnuTLS : public Module virtual int OnRawSocketRead(int fd, char* buffer, unsigned int count, int &readresult) { /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1)) return 0; issl_session* session = &sessions[fd]; @@ -552,7 +554,7 @@ class ModuleSSLGnuTLS : public Module virtual int OnRawSocketWrite(int fd, const char* buffer, int count) { /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1)) return 0; issl_session* session = &sessions[fd]; diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp index de7101db1..83fa94e96 100644 --- a/src/modules/extra/m_ssl_openssl.cpp +++ b/src/modules/extra/m_ssl_openssl.cpp @@ -107,7 +107,7 @@ class ModuleSSLOpenSSL : public Module std::vector<std::string> listenports; int inbufsize; - issl_session sessions[MAX_DESCRIPTORS]; + issl_session* sessions; SSL_CTX* ctx; SSL_CTX* clictx; @@ -133,6 +133,8 @@ class ModuleSSLOpenSSL : public Module { ServerInstance->Modules->PublishInterface("BufferedSocketHook", this); + sessions = new issl_session[ServerInstance->SE->GetMaxFds()]; + // Not rehashable...because I cba to reduce all the sizes of existing buffers. inbufsize = ServerInstance->Config->NetBufferSize; @@ -302,6 +304,8 @@ class ModuleSSLOpenSSL : public Module { SSL_CTX_free(ctx); SSL_CTX_free(clictx); + ServerInstance->Modules->UnpublishInterface("BufferedSocketHook", this); + delete[] sessions; } virtual void OnCleanup(int target_type, void* item) @@ -396,7 +400,7 @@ class ModuleSSLOpenSSL : public Module virtual void OnRawSocketAccept(int fd, const std::string &ip, int localport) { /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1)) return; issl_session* session = &sessions[fd]; @@ -423,7 +427,7 @@ class ModuleSSLOpenSSL : public Module virtual void OnRawSocketConnect(int fd) { /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() -1)) return; issl_session* session = &sessions[fd]; @@ -450,7 +454,7 @@ class ModuleSSLOpenSSL : public Module virtual void OnRawSocketClose(int fd) { /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1)) return; CloseSession(&sessions[fd]); @@ -469,7 +473,7 @@ class ModuleSSLOpenSSL : public Module virtual int OnRawSocketRead(int fd, char* buffer, unsigned int count, int &readresult) { /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1)) return 0; issl_session* session = &sessions[fd]; @@ -546,7 +550,7 @@ class ModuleSSLOpenSSL : public Module virtual int OnRawSocketWrite(int fd, const char* buffer, int count) { /* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */ - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if ((fd < 0) || (fd > ServerInstance->SE->GetMaxFds() - 1)) return 0; issl_session* session = &sessions[fd]; diff --git a/src/modules/extra/m_ziplink.cpp b/src/modules/extra/m_ziplink.cpp index 5202287fa..7b1cb281c 100644 --- a/src/modules/extra/m_ziplink.cpp +++ b/src/modules/extra/m_ziplink.cpp @@ -137,7 +137,7 @@ class izip_session : public classbase class ModuleZLib : public Module { - izip_session sessions[MAX_DESCRIPTORS]; + izip_session* sessions; /* Used for stats z extensions */ float total_out_compressed; @@ -152,6 +152,8 @@ class ModuleZLib : public Module { ServerInstance->Modules->PublishInterface("BufferedSocketHook", this); + sessions = new izip_session[ServerInstance->SE->GetMaxFds()]; + total_out_compressed = total_in_compressed = 0; total_out_uncompressed = total_out_uncompressed = 0; Implementation eventlist[] = { I_OnRawSocketConnect, I_OnRawSocketAccept, I_OnRawSocketClose, I_OnRawSocketRead, I_OnRawSocketWrite, I_OnStats, I_OnRequest }; @@ -161,6 +163,7 @@ class ModuleZLib : public Module virtual ~ModuleZLib() { ServerInstance->Modules->UnpublishInterface("BufferedSocketHook", this); + delete[] sessions; } virtual Version GetVersion() diff --git a/src/socketengine.cpp b/src/socketengine.cpp index a4b6d7d29..d0c181be4 100644 --- a/src/socketengine.cpp +++ b/src/socketengine.cpp @@ -61,7 +61,6 @@ void SocketEngine::WantWrite(EventHandler* eh) SocketEngine::SocketEngine(InspIRCd* Instance) : ServerInstance(Instance) { - memset(ref, 0, sizeof(ref)); TotalEvents = WriteEvents = ReadEvents = ErrorEvents = 0; } diff --git a/src/socketengines/socketengine_epoll.cpp b/src/socketengines/socketengine_epoll.cpp index 1a0c5d53e..a749208d1 100644 --- a/src/socketengines/socketengine_epoll.cpp +++ b/src/socketengines/socketengine_epoll.cpp @@ -15,10 +15,11 @@ #include "exitcodes.h" #include <sys/epoll.h> #include "socketengines/socketengine_epoll.h" +#include <ulimit.h> EPollEngine::EPollEngine(InspIRCd* Instance) : SocketEngine(Instance) { - EngineHandle = epoll_create(MAX_DESCRIPTORS); + EngineHandle = epoll_create(GetMaxFds()); if (EngineHandle == -1) { @@ -29,17 +30,24 @@ EPollEngine::EPollEngine(InspIRCd* Instance) : SocketEngine(Instance) ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE); } CurrentSetSize = 0; + + ref = new EventHandler* [GetMaxFds()]; + events = new struct epoll_event[GetMaxFds()]; + + memset(ref, 0, GetMaxFds() * sizeof(EventHandler*)); } EPollEngine::~EPollEngine() { this->Close(EngineHandle); + delete[] ref; + delete[] events; } bool EPollEngine::AddFd(EventHandler* eh) { int fd = eh->GetFd(); - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if ((fd < 0) || (fd > GetMaxFds() - 1)) { ServerInstance->Logs->Log("SOCKET",DEBUG,"Out of range FD"); return false; @@ -83,7 +91,7 @@ void EPollEngine::WantWrite(EventHandler* eh) bool EPollEngine::DelFd(EventHandler* eh, bool force) { int fd = eh->GetFd(); - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if ((fd < 0) || (fd > GetMaxFds() - 1)) return false; struct epoll_event ev; @@ -107,19 +115,34 @@ bool EPollEngine::DelFd(EventHandler* eh, bool force) int EPollEngine::GetMaxFds() { - return MAX_DESCRIPTORS; + if (MAX_DESCRIPTORS) + return MAX_DESCRIPTORS; + + int max = ulimit(4, 0); + if (max > 0) + { + MAX_DESCRIPTORS = max; + return max; + } + else + { + ServerInstance->Logs->Log("SOCKET", DEFAULT, "ERROR: Can't determine maximum number of open sockets!"); + printf("ERROR: Can't determine maximum number of open sockets!\n"); + ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE); + } + return 0; } int EPollEngine::GetRemainingFds() { - return MAX_DESCRIPTORS - CurrentSetSize; + return GetMaxFds() - CurrentSetSize; } int EPollEngine::DispatchEvents() { socklen_t codesize; int errcode; - int i = epoll_wait(EngineHandle, events, MAX_DESCRIPTORS, 1000); + int i = epoll_wait(EngineHandle, events, GetMaxFds() - 1, 1000); TotalEvents += i; diff --git a/src/socketengines/socketengine_iocp.cpp b/src/socketengines/socketengine_iocp.cpp index 5bc1faed4..b27f96035 100644 --- a/src/socketengines/socketengine_iocp.cpp +++ b/src/socketengines/socketengine_iocp.cpp @@ -32,6 +32,8 @@ IOCPEngine::IOCPEngine(InspIRCd * Instance) : SocketEngine(Instance) /* Null variables out. */ CurrentSetSize = 0; EngineHandle = 0; + MAX_DESCRIPTORS = 10240; + ref = new EventHandler* [10240]; memset(ref, 0, sizeof(EventHandler*) * MAX_DESCRIPTORS); } @@ -40,6 +42,7 @@ IOCPEngine::~IOCPEngine() /* Clean up winsock and close completion port */ CloseHandle(m_completionPort); WSACleanup(); + delete[] ref; } bool IOCPEngine::AddFd(EventHandler* eh) diff --git a/src/socketengines/socketengine_kqueue.cpp b/src/socketengines/socketengine_kqueue.cpp index f245830de..63a1844cb 100644 --- a/src/socketengines/socketengine_kqueue.cpp +++ b/src/socketengines/socketengine_kqueue.cpp @@ -6,7 +6,7 @@ * See: http://www.inspircd.org/wiki/index.php/Credits * * This program is free but copyrighted software; see - * the file COPYING for details. + * the file COPYING for details. * * --------------------------------------------------- */ @@ -17,11 +17,13 @@ #include <sys/event.h> #include <sys/time.h> #include "socketengines/socketengine_kqueue.h" - +#include <ulimit.h> KQueueEngine::KQueueEngine(InspIRCd* Instance) : SocketEngine(Instance) { this->RecoverFromFork(); + ref = new EventHandler* [GetMaxFds()]; + ke_list = new struct kevent[GetMaxFds()]; } void KQueueEngine::RecoverFromFork() @@ -41,18 +43,21 @@ void KQueueEngine::RecoverFromFork() ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE); } CurrentSetSize = 0; + memset(ref, 0, GetMaxFds() * sizeof(EventHandler*)); } KQueueEngine::~KQueueEngine() { this->Close(EngineHandle); + delete[] ref; + delete[] ke_list; } bool KQueueEngine::AddFd(EventHandler* eh) { int fd = eh->GetFd(); - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if ((fd < 0) || (fd > GetMaxFds() - 1)) return false; if (GetRemainingFds() <= 1) @@ -81,7 +86,7 @@ bool KQueueEngine::DelFd(EventHandler* eh, bool force) { int fd = eh->GetFd(); - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if ((fd < 0) || (fd > GetMaxFds() - 1)) return false; struct kevent ke; @@ -116,12 +121,27 @@ void KQueueEngine::WantWrite(EventHandler* eh) int KQueueEngine::GetMaxFds() { - return MAX_DESCRIPTORS; + if (MAX_DESCRIPTORS) + return MAX_DESCRIPTORS; + + int max = ulimit(4, 0); + if (max > 0) + { + MAX_DESCRIPTORS = max; + return max; + } + else + { + ServerInstance->Logs->Log("SOCKET", DEFAULT, "ERROR: Can't determine maximum number of open sockets!"); + printf("ERROR: Can't determine maximum number of open sockets!\n"); + ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE); + } + return 0; } int KQueueEngine::GetRemainingFds() { - return MAX_DESCRIPTORS - CurrentSetSize; + return GetMaxFds() - CurrentSetSize; } int KQueueEngine::DispatchEvents() @@ -129,7 +149,7 @@ int KQueueEngine::DispatchEvents() ts.tv_nsec = 0; ts.tv_sec = 1; - int i = kevent(EngineHandle, NULL, 0, &ke_list[0], MAX_DESCRIPTORS, &ts); + int i = kevent(EngineHandle, NULL, 0, &ke_list[0], GetMaxFds(), &ts); TotalEvents += i; diff --git a/src/socketengines/socketengine_ports.cpp b/src/socketengines/socketengine_ports.cpp index 767ea0df0..113c6794e 100644 --- a/src/socketengines/socketengine_ports.cpp +++ b/src/socketengines/socketengine_ports.cpp @@ -6,7 +6,7 @@ * See: http://www.inspircd.org/wiki/index.php/Credits * * This program is free but copyrighted software; see - * the file COPYING for details. + * the file COPYING for details. * * --------------------------------------------------- */ @@ -15,6 +15,7 @@ #include "exitcodes.h" #include <port.h> #include "socketengines/socketengine_ports.h" +#include <ulimit.h> PortsEngine::PortsEngine(InspIRCd* Instance) : SocketEngine(Instance) { @@ -29,17 +30,23 @@ PortsEngine::PortsEngine(InspIRCd* Instance) : SocketEngine(Instance) ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE); } CurrentSetSize = 0; + + ref = new EventHandler* [GetMaxFds()]; + events = new port_event_t[GetMaxFds()]; + memset(ref, 0, GetMaxFds() * sizeof(EventHandler*)); } PortsEngine::~PortsEngine() { this->Close(EngineHandle); + delete[] ref; + delete[] events; } bool PortsEngine::AddFd(EventHandler* eh) { int fd = eh->GetFd(); - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if ((fd < 0) || (fd > GetMaxFds() - 1)) return false; if (GetRemainingFds() <= 1) @@ -64,7 +71,7 @@ void PortsEngine::WantWrite(EventHandler* eh) bool PortsEngine::DelFd(EventHandler* eh, bool force) { int fd = eh->GetFd(); - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if ((fd < 0) || (fd > GetMaxFds() - 1)) return false; port_dissociate(EngineHandle, PORT_SOURCE_FD, fd); @@ -78,12 +85,27 @@ bool PortsEngine::DelFd(EventHandler* eh, bool force) int PortsEngine::GetMaxFds() { - return MAX_DESCRIPTORS; + if (MAX_DESCRIPTORS) + return MAX_DESCRIPTORS; + + int max = ulimit(4, 0); + if (max > 0) + { + MAX_DESCRIPTORS = max; + return max; + } + else + { + ServerInstance->Logs->Log("SOCKET", DEFAULT, "ERROR: Can't determine maximum number of open sockets!"); + printf("ERROR: Can't determine maximum number of open sockets!\n"); + ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE); + } +#include <ulimit.h> } int PortsEngine::GetRemainingFds() { - return MAX_DESCRIPTORS - CurrentSetSize; + return GetMaxFds() - CurrentSetSize; } int PortsEngine::DispatchEvents() @@ -94,7 +116,7 @@ int PortsEngine::DispatchEvents() poll_time.tv_nsec = 0; unsigned int nget = 1; // used to denote a retrieve request. - int i = port_getn(EngineHandle, this->events, MAX_DESCRIPTORS, &nget, &poll_time); + int i = port_getn(EngineHandle, this->events, GetMaxFds() - 1, &nget, &poll_time); // first handle an error condition if (i == -1) diff --git a/src/socketengines/socketengine_select.cpp b/src/socketengines/socketengine_select.cpp index 055637890..5a5d61147 100644 --- a/src/socketengines/socketengine_select.cpp +++ b/src/socketengines/socketengine_select.cpp @@ -6,7 +6,7 @@ * See: http://www.inspircd.org/wiki/index.php/Credits * * This program is free but copyrighted software; see - * the file COPYING for details. + * the file COPYING for details. * * --------------------------------------------------- */ @@ -22,17 +22,22 @@ SelectEngine::SelectEngine(InspIRCd* Instance) : SocketEngine(Instance) { EngineHandle = 0; CurrentSetSize = 0; + + writeable = new bool [GetMaxFds()]; memset(writeable, 0, sizeof(writeable)); + ref = new EventHandler* [GetMaxFds()]; + memset(ref, 0, GetMaxFds() * sizeof(EventHandler*)); } SelectEngine::~SelectEngine() { + delete[] ref; } bool SelectEngine::AddFd(EventHandler* eh) { int fd = eh->GetFd(); - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if ((fd < 0) || (fd > GetMaxFds() - 1)) return false; if (GetRemainingFds() <= 1) @@ -58,7 +63,7 @@ bool SelectEngine::DelFd(EventHandler* eh, bool force) { int fd = eh->GetFd(); - if ((fd < 0) || (fd > MAX_DESCRIPTORS)) + if ((fd < 0) || (fd > GetMaxFds() - 1)) return false; std::map<int,int>::iterator t = fds.find(fd); @@ -79,7 +84,7 @@ int SelectEngine::GetMaxFds() int SelectEngine::GetRemainingFds() { - return FD_SETSIZE - CurrentSetSize; + return GetMaxFds() - CurrentSetSize; } int SelectEngine::DispatchEvents() @@ -87,7 +92,7 @@ int SelectEngine::DispatchEvents() int result = 0; timeval tval; int sresult = 0; - EventHandler* ev[MAX_DESCRIPTORS]; + EventHandler* ev[GetMaxFds()]; socklen_t codesize; int errcode; diff --git a/src/usermanager.cpp b/src/usermanager.cpp index af76f5651..6a23ad795 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -126,7 +126,7 @@ void UserManager::AddClient(InspIRCd* Instance, int socket, int port, bool iscac * than about 10,000 users on ONE server!) */ #ifndef WINDOWS - if ((unsigned int)socket >= MAX_DESCRIPTORS) + if (socket >= Instance->SE->GetMaxFds()) { User::QuitUser(Instance, New, "Server is full"); return; diff --git a/src/users.cpp b/src/users.cpp index df7a36683..361b7ba21 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -21,7 +21,13 @@ #include "bancache.h" #include "commands/cmd_whowas.h" -static unsigned long already_sent[MAX_DESCRIPTORS] = {0}; +static unsigned long* already_sent = NULL; + + +void InitializeAlreadySent(SocketEngine* SE) +{ + already_sent = new unsigned long[SE->GetMaxFds()]; +} /* XXX: Used for speeding up WriteCommon operations */ unsigned long uniq_id = 0; @@ -1322,6 +1328,9 @@ void User::WriteCommon(const std::string &text) uniq_id++; + if (!already_sent) + InitializeAlreadySent(ServerInstance->SE); + /* We dont want to be doing this n times, just once */ snprintf(tb,MAXBUF,":%s %s",this->GetFullHost(),text.c_str()); std::string out = tb; @@ -1376,6 +1385,10 @@ void User::WriteCommonQuit(const std::string &normal_text, const std::string &op return; uniq_id++; + + if (!already_sent) + InitializeAlreadySent(ServerInstance->SE); + snprintf(tb1,MAXBUF,":%s QUIT :%s",this->GetFullHost(),normal_text.c_str()); snprintf(tb2,MAXBUF,":%s QUIT :%s",this->GetFullHost(),oper_text.c_str()); std::string out1 = tb1; @@ -1407,6 +1420,10 @@ void User::WriteCommonExcept(const std::string &text) return; uniq_id++; + + if (!already_sent) + InitializeAlreadySent(ServerInstance->SE); + snprintf(tb1,MAXBUF,":%s %s",this->GetFullHost(),text.c_str()); out1 = tb1; |