diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/commands/cmd_whowas.cpp | 11 | ||||
-rw-r--r-- | src/helperfuncs.cpp | 21 | ||||
-rw-r--r-- | src/inspircd.cpp | 2 | ||||
-rw-r--r-- | src/inspsocket.cpp | 22 | ||||
-rw-r--r-- | src/modules/extra/m_ssl_gnutls.cpp | 10 | ||||
-rw-r--r-- | src/modules/extra/m_ssl_openssl.cpp | 2 | ||||
-rw-r--r-- | src/modules/m_dnsbl.cpp | 32 | ||||
-rw-r--r-- | src/modules/m_ircv3.cpp | 2 | ||||
-rw-r--r-- | src/modules/m_permchannels.cpp | 106 | ||||
-rw-r--r-- | src/modules/m_spanningtree/fjoin.cpp | 32 | ||||
-rw-r--r-- | src/modules/m_spanningtree/main.cpp | 7 | ||||
-rw-r--r-- | src/modules/m_spanningtree/utils.h | 3 | ||||
-rw-r--r-- | src/modules/m_userip.cpp | 2 | ||||
-rw-r--r-- | src/socketengine.cpp | 23 | ||||
-rw-r--r-- | src/socketengines/socketengine_epoll.cpp | 4 | ||||
-rw-r--r-- | src/socketengines/socketengine_kqueue.cpp | 4 | ||||
-rw-r--r-- | src/socketengines/socketengine_poll.cpp | 44 | ||||
-rw-r--r-- | src/socketengines/socketengine_ports.cpp | 4 | ||||
-rw-r--r-- | src/socketengines/socketengine_select.cpp | 4 | ||||
-rw-r--r-- | src/threadengines/threadengine_pthread.cpp | 11 | ||||
-rw-r--r-- | src/threadengines/threadengine_win32.cpp | 10 |
21 files changed, 235 insertions, 121 deletions
diff --git a/src/commands/cmd_whowas.cpp b/src/commands/cmd_whowas.cpp index b406781b1..75d1ee8ff 100644 --- a/src/commands/cmd_whowas.cpp +++ b/src/commands/cmd_whowas.cpp @@ -54,14 +54,6 @@ CmdResult CommandWhowas::Handle (const std::vector<std::string>& parameters, Use for (whowas_set::iterator ux = grp->begin(); ux != grp->end(); ux++) { WhoWasGroup* u = *ux; - time_t rawtime = u->signon; - tm *timeinfo; - char b[25]; - - timeinfo = localtime(&rawtime); - - strncpy(b,asctime(timeinfo),24); - b[24] = 0; user->WriteNumeric(314, "%s %s %s %s * :%s",user->nick.c_str(),parameters[0].c_str(), u->ident.c_str(),u->dhost.c_str(),u->gecos.c_str()); @@ -70,8 +62,9 @@ CmdResult CommandWhowas::Handle (const std::vector<std::string>& parameters, Use user->WriteNumeric(379, "%s %s :was connecting from *@%s", user->nick.c_str(), parameters[0].c_str(), u->host.c_str()); + std::string signon = ServerInstance->TimeString(u->signon); bool hide_server = (!ServerInstance->Config->HideWhoisServer.empty() && !user->HasPrivPermission("servers/auspex")); - user->WriteNumeric(312, "%s %s %s :%s",user->nick.c_str(), parameters[0].c_str(), (hide_server ? ServerInstance->Config->HideWhoisServer.c_str() : u->server.c_str()), b); + user->WriteNumeric(312, "%s %s %s :%s",user->nick.c_str(), parameters[0].c_str(), (hide_server ? ServerInstance->Config->HideWhoisServer.c_str() : u->server.c_str()), signon.c_str()); } } else diff --git a/src/helperfuncs.cpp b/src/helperfuncs.cpp index 2626da6bb..cfbd53c98 100644 --- a/src/helperfuncs.cpp +++ b/src/helperfuncs.cpp @@ -437,7 +437,26 @@ bool InspIRCd::SilentULine(const std::string& sserver) std::string InspIRCd::TimeString(time_t curtime) { - return std::string(ctime(&curtime),24); +#ifdef _WIN32 + if (curtime < 0) + curtime = 0; +#endif + + struct tm* timeinfo = localtime(&curtime); + if (!timeinfo) + { + curtime = 0; + timeinfo = localtime(&curtime); + } + + // If the calculated year exceeds four digits or is less than the year 1000, + // the behavior of asctime() is undefined + if (timeinfo->tm_year + 1900 > 9999) + timeinfo->tm_year = 9999 - 1900; + else if (timeinfo->tm_year + 1900 < 1000) + timeinfo->tm_year = 0; + + return std::string(asctime(timeinfo),24); } std::string InspIRCd::GenRandomStr(int length, bool printable) diff --git a/src/inspircd.cpp b/src/inspircd.cpp index c94f08842..2171e2a9f 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -155,7 +155,7 @@ void InspIRCd::SetSignals() void InspIRCd::QuickExit(int status) { - exit(0); + exit(status); } bool InspIRCd::DaemonSeed() diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp index ec528571b..d7a25785d 100644 --- a/src/inspsocket.cpp +++ b/src/inspsocket.cpp @@ -57,7 +57,7 @@ void BufferedSocket::DoConnect(const std::string &ipaddr, int aport, unsigned lo if (err != I_ERR_NONE) { state = I_ERROR; - SetError(strerror(errno)); + SetError(SocketEngine::LastError()); OnError(err); } } @@ -211,7 +211,7 @@ void StreamSocket::DoRead() } else { - error = strerror(errno); + error = SocketEngine::LastError(); ServerInstance->SE->ChangeEventMask(this, FD_WANT_NO_READ | FD_WANT_NO_WRITE); } } @@ -249,11 +249,13 @@ void StreamSocket::DoWrite() // The length limit of 1024 is to prevent merging strings // more than once when writes begin to block. std::string tmp; - tmp.reserve(sendq_len); - for(unsigned int i=0; i < sendq.size(); i++) - tmp.append(sendq[i]); - sendq.clear(); - sendq.push_back(tmp); + tmp.reserve(1280); + while (!sendq.empty() && tmp.length() < 1024) + { + tmp.append(sendq.front()); + sendq.pop_front(); + } + sendq.push_front(tmp); } std::string& front = sendq.front(); int itemlen = front.length(); @@ -295,7 +297,7 @@ void StreamSocket::DoWrite() if (errno == EINTR || SocketEngine::IgnoreError()) ServerInstance->SE->ChangeEventMask(this, FD_WANT_FAST_WRITE | FD_WRITE_WILL_BLOCK); else - SetError(strerror(errno)); + SetError(SocketEngine::LastError()); return; } else if (rv < itemlen) @@ -400,7 +402,7 @@ void StreamSocket::DoWrite() } else { - error = strerror(errno); + error = SocketEngine::LastError(); } } if (!error.empty()) @@ -496,7 +498,7 @@ void StreamSocket::HandleEvent(EventType et, int errornum) if (errornum == 0) SetError("Connection closed"); else - SetError(strerror(errornum)); + SetError(SocketEngine::GetError(errornum)); switch (errornum) { case ETIMEDOUT: diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp index dab377397..53fc38ec0 100644 --- a/src/modules/extra/m_ssl_gnutls.cpp +++ b/src/modules/extra/m_ssl_gnutls.cpp @@ -47,8 +47,14 @@ /* $CompileFlags: pkgconfincludes("gnutls","/gnutls/gnutls.h","") exec("libgcrypt-config --cflags") -Wno-pedantic */ /* $LinkerFlags: rpath("pkg-config --libs gnutls") pkgconflibs("gnutls","/libgnutls.so","-lgnutls") exec("libgcrypt-config --libs") */ +#ifndef GNUTLS_VERSION_MAJOR +#define GNUTLS_VERSION_MAJOR LIBGNUTLS_VERSION_MAJOR +#define GNUTLS_VERSION_MINOR LIBGNUTLS_VERSION_MINOR +#define GNUTLS_VERSION_PATCH LIBGNUTLS_VERSION_PATCH +#endif + // These don't exist in older GnuTLS versions -#if ((GNUTLS_VERSION_MAJOR > 2) || (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR > 1) || (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR == 1 && GNUTLS_VERSION_MICRO >= 7)) +#if ((GNUTLS_VERSION_MAJOR > 2) || (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR > 1) || (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR == 1 && GNUTLS_VERSION_PATCH >= 7)) #define GNUTLS_NEW_PRIO_API #endif @@ -115,6 +121,8 @@ class GnuTLSIOHook : public SSLIOHook #ifdef GNUTLS_NEW_PRIO_API gnutls_priority_set(session->sess, priority); + #else + gnutls_set_default_priority(session->sess); #endif gnutls_credentials_set(session->sess, GNUTLS_CRD_CERTIFICATE, x509_cred); gnutls_dh_set_prime_bits(session->sess, dh_bits); diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp index 4cb6ee07b..29c3568ef 100644 --- a/src/modules/extra/m_ssl_openssl.cpp +++ b/src/modules/extra/m_ssl_openssl.cpp @@ -184,7 +184,7 @@ class OpenSSLIOHook : public SSLIOHook certinfo->invalid = (SSL_get_verify_result(session->sess) != X509_V_OK); - if (SelfSigned) + if (!SelfSigned) { certinfo->unknownsigner = false; certinfo->trusted = true; diff --git a/src/modules/m_dnsbl.cpp b/src/modules/m_dnsbl.cpp index becc7a6e8..3c9d64d49 100644 --- a/src/modules/m_dnsbl.cpp +++ b/src/modules/m_dnsbl.cpp @@ -26,7 +26,7 @@ #include "modules/dns.h" /* Class holding data for a single entry */ -class DNSBLConfEntry +class DNSBLConfEntry : public refcountbase { public: enum EnumBanaction { I_UNKNOWN, I_KILL, I_ZLINE, I_KLINE, I_GLINE, I_MARK }; @@ -49,11 +49,11 @@ class DNSBLResolver : public DNS::Request std::string theiruid; LocalStringExt& nameExt; LocalIntExt& countExt; - DNSBLConfEntry *ConfEntry; + reference<DNSBLConfEntry> ConfEntry; public: - DNSBLResolver(DNS::Manager *mgr, Module *me, LocalStringExt& match, LocalIntExt& ctr, const std::string &hostname, LocalUser* u, DNSBLConfEntry *conf) + DNSBLResolver(DNS::Manager *mgr, Module *me, LocalStringExt& match, LocalIntExt& ctr, const std::string &hostname, LocalUser* u, reference<DNSBLConfEntry> conf) : DNS::Request(mgr, me, hostname, DNS::QUERY_A, true), theiruid(u->uuid), nameExt(match), countExt(ctr), ConfEntry(conf) { } @@ -203,7 +203,7 @@ class DNSBLResolver : public DNS::Request class ModuleDNSBL : public Module { - std::vector<DNSBLConfEntry *> DNSBLConfEntries; + std::vector<reference<DNSBLConfEntry> > DNSBLConfEntries; dynamic_reference<DNS::Manager> DNS; LocalStringExt nameExt; LocalIntExt countExt; @@ -236,36 +236,22 @@ class ModuleDNSBL : public Module ServerInstance->Modules->AddService(countExt); } - ~ModuleDNSBL() - { - ClearEntries(); - } - Version GetVersion() CXX11_OVERRIDE { return Version("Provides handling of DNS blacklists", VF_VENDOR); } - /** Clear entries and free the mem it was using - */ - void ClearEntries() - { - for (std::vector<DNSBLConfEntry *>::iterator i = DNSBLConfEntries.begin(); i != DNSBLConfEntries.end(); i++) - delete *i; - DNSBLConfEntries.clear(); - } - /** Fill our conf vector with data */ void ReadConf() { - ClearEntries(); + DNSBLConfEntries.clear(); ConfigTagList dnsbls = ServerInstance->Config->ConfTags("dnsbl"); for(ConfigIter i = dnsbls.first; i != dnsbls.second; ++i) { ConfigTag* tag = i->second; - DNSBLConfEntry *e = new DNSBLConfEntry(); + reference<DNSBLConfEntry> e = new DNSBLConfEntry(); e->name = tag->getString("name"); e->ident = tag->getString("ident"); @@ -325,11 +311,7 @@ class ModuleDNSBL : public Module /* add it, all is ok */ DNSBLConfEntries.push_back(e); - continue; } - - /* delete and drop it, error somewhere */ - delete e; } } @@ -410,7 +392,7 @@ class ModuleDNSBL : public Module unsigned long total_hits = 0, total_misses = 0; - for (std::vector<DNSBLConfEntry*>::iterator i = DNSBLConfEntries.begin(); i != DNSBLConfEntries.end(); i++) + for (std::vector<reference<DNSBLConfEntry> >::const_iterator i = DNSBLConfEntries.begin(); i != DNSBLConfEntries.end(); ++i) { total_hits += (*i)->stats_hits; total_misses += (*i)->stats_misses; diff --git a/src/modules/m_ircv3.cpp b/src/modules/m_ircv3.cpp index 59a69f669..f46ae97b4 100644 --- a/src/modules/m_ircv3.cpp +++ b/src/modules/m_ircv3.cpp @@ -84,7 +84,7 @@ class ModuleIRCv3 : public Module void OnRehash(User* user) CXX11_OVERRIDE { ConfigTag* conf = ServerInstance->Config->ConfValue("ircv3"); - accountnotify = conf->getBool("accoutnotify", true); + accountnotify = conf->getBool("accountnotify", true); awaynotify = conf->getBool("awaynotify", true); extendedjoin = conf->getBool("extendedjoin", true); } diff --git a/src/modules/m_permchannels.cpp b/src/modules/m_permchannels.cpp index 2a3dff6ee..a19a184e0 100644 --- a/src/modules/m_permchannels.cpp +++ b/src/modules/m_permchannels.cpp @@ -19,9 +19,16 @@ #include "inspircd.h" +#include "listmode.h" #include <fstream> +struct ListModeData +{ + std::string modes; + std::string params; +}; + /** Handles the +P channel mode */ class PermChannel : public ModeHandler @@ -48,8 +55,9 @@ class PermChannel : public ModeHandler // Not in a class due to circular dependancy hell. static std::string permchannelsconf; -static bool WriteDatabase(PermChannel& permchanmode) +static bool WriteDatabase(PermChannel& permchanmode, Module* mod, bool save_listmodes) { + ChanModeReference ban(mod, "ban"); /* * We need to perform an atomic write so as not to fuck things up. * So, let's write to a temporary file, flush it, then rename the file.. @@ -78,9 +86,45 @@ static bool WriteDatabase(PermChannel& permchanmode) if (!chan->IsModeSet(permchanmode)) continue; + std::string chanmodes = chan->ChanModes(true); + if (save_listmodes) + { + ListModeData lm; + + // Bans are managed by the core, so we have to process them separately + static_cast<ListModeBase*>(*ban)->DoSyncChannel(chan, mod, &lm); + + // All other listmodes are managed by modules, so we need to ask them (call their + // OnSyncChannel() handler) to give our ProtoSendMode() a list of modes that are + // set on the channel. The ListModeData struct is passed as an opaque pointer + // that will be passed back to us by the module handling the mode. + FOREACH_MOD(OnSyncChannel, (chan, mod, &lm)); + + if (!lm.modes.empty()) + { + // Remove the last space + lm.params.erase(lm.params.end()-1); + + // If there is at least a space in chanmodes (that is, a non-listmode has a parameter) + // insert the listmode mode letters before the space. Otherwise just append them. + std::string::size_type p = chanmodes.find(' '); + if (p == std::string::npos) + chanmodes += lm.modes; + else + chanmodes.insert(p, lm.modes); + + // Append the listmode parameters (the masks themselves) + chanmodes += ' '; + chanmodes += lm.params; + } + } + stream << "<permchannels channel=\"" << ServerConfig::Escape(chan->name) + << "\" ts=\"" << chan->age << "\" topic=\"" << ServerConfig::Escape(chan->topic) - << "\" modes=\"" << ServerConfig::Escape(chan->ChanModes(true)) + << "\" topicts=\"" << chan->topicset + << "\" topicsetby=\"" << ServerConfig::Escape(chan->setby) + << "\" modes=\"" << ServerConfig::Escape(chanmodes) << "\">" << std::endl; } @@ -115,6 +159,7 @@ class ModulePermanentChannels : public Module { PermChannel p; bool dirty; + bool save_listmodes; public: ModulePermanentChannels() : p(this), dirty(false) @@ -156,7 +201,9 @@ public: void OnRehash(User *user) CXX11_OVERRIDE { - permchannelsconf = ServerInstance->Config->ConfValue("permchanneldb")->getString("filename"); + ConfigTag* tag = ServerInstance->Config->ConfValue("permchanneldb"); + permchannelsconf = tag->getString("filename"); + save_listmodes = tag->getBool("listmodes"); } void LoadDatabase() @@ -170,12 +217,11 @@ public: { ConfigTag* tag = i->second; std::string channel = tag->getString("channel"); - std::string topic = tag->getString("topic"); std::string modes = tag->getString("modes"); - if (channel.empty()) + if ((channel.empty()) || (channel.length() > ServerInstance->Config->Limits.ChanMax)) { - ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Malformed permchannels tag with empty channel name."); + ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Ignoring permchannels tag with empty or too long channel name (\"" + channel + "\")"); continue; } @@ -183,20 +229,23 @@ public: if (!c) { - c = new Channel(channel, ServerInstance->Time()); - if (!topic.empty()) + time_t TS = tag->getInt("ts", ServerInstance->Time(), 1); + c = new Channel(channel, TS); + + unsigned int topicset = tag->getInt("topicts"); + c->topic = tag->getString("topic"); + + if ((topicset != 0) || (!c->topic.empty())) { - c->SetTopic(ServerInstance->FakeClient, topic); - - /* - * Due to the way protocol works in 1.2, we need to hack the topic TS in such a way that this - * topic will always win over others. - * - * This is scheduled for (proper) fixing in a later release, and can be removed at a later date. - */ - c->topicset = 42; + if (topicset == 0) + topicset = ServerInstance->Time(); + c->topicset = topicset; + c->setby = tag->getString("topicsetby"); + if (c->setby.empty()) + c->setby = ServerInstance->Config->ServerName; } - ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Added %s with topic %s", channel.c_str(), topic.c_str()); + + ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Added %s with topic %s", channel.c_str(), c->topic.c_str()); if (modes.empty()) continue; @@ -242,7 +291,7 @@ public: void OnBackgroundTimer(time_t) CXX11_OVERRIDE { if (dirty) - WriteDatabase(p); + WriteDatabase(p, this, save_listmodes); dirty = false; } @@ -278,6 +327,25 @@ public: } } + void ProtoSendMode(void* opaque, TargetTypeFlags type, void* target, const std::vector<std::string>& modes, const std::vector<TranslateType>& translate) + { + // We never pass an empty modelist but better be sure + if (modes.empty()) + return; + + ListModeData* lm = static_cast<ListModeData*>(opaque); + + // Append the mode letters without the trailing '+' (for example "IIII", "gg") + lm->modes.append(modes[0].begin()+1, modes[0].end()); + + // Append the parameters + for (std::vector<std::string>::const_iterator i = modes.begin()+1; i != modes.end(); ++i) + { + lm->params += *i; + lm->params += ' '; + } + } + Version GetVersion() CXX11_OVERRIDE { return Version("Provides support for channel mode +P to provide permanent channels",VF_VENDOR); diff --git a/src/modules/m_spanningtree/fjoin.cpp b/src/modules/m_spanningtree/fjoin.cpp index 93320757c..0fb446877 100644 --- a/src/modules/m_spanningtree/fjoin.cpp +++ b/src/modules/m_spanningtree/fjoin.cpp @@ -124,12 +124,36 @@ CmdResult CommandFJoin::Handle(User* srcuser, std::vector<std::string>& params) /* First up, apply their channel modes if they won the TS war */ if (apply_other_sides_modes) { + // Need to use a modestacker here due to maxmodes + irc::modestacker stack(true); + std::vector<std::string>::const_iterator paramit = params.begin() + 3; + const std::vector<std::string>::const_iterator lastparamit = ((params.size() > 3) ? (params.end() - 1) : params.end()); + for (std::string::const_iterator i = params[2].begin(); i != params[2].end(); ++i) + { + ModeHandler* mh = ServerInstance->Modes->FindMode(*i, MODETYPE_CHANNEL); + if (!mh) + continue; + + std::string modeparam; + if ((paramit != lastparamit) && (mh->GetNumParams(true))) + { + modeparam = *paramit; + ++paramit; + } + + stack.Push(*i, modeparam); + } + std::vector<std::string> modelist; - modelist.push_back(channel); - /* Remember, params[params.size() - 1] is userlist, and we don't want to apply *that* */ - modelist.insert(modelist.end(), params.begin()+2, params.end()-1); - ServerInstance->Modes->Process(modelist, srcuser, ModeParser::MODE_LOCALONLY | ModeParser::MODE_MERGE); + // Mode parser needs to know what channel to act on. + modelist.push_back(params[0]); + + while (stack.GetStackedLine(modelist)) + { + ServerInstance->Modes->Process(modelist, srcuser, ModeParser::MODE_LOCALONLY | ModeParser::MODE_MERGE); + modelist.erase(modelist.begin() + 1, modelist.end()); + } } irc::modestacker modestack(true); diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp index 98f9a304b..9ece3c03d 100644 --- a/src/modules/m_spanningtree/main.cpp +++ b/src/modules/m_spanningtree/main.cpp @@ -669,6 +669,13 @@ void ModuleSpanningTree::OnUnloadModule(Module* mod) sock->Close(); } } + + for (SpanningTreeUtilities::TimeoutList::const_iterator i = Utils->timeoutlist.begin(); i != Utils->timeoutlist.end(); ++i) + { + TreeSocket* sock = i->first; + if (sock->GetIOHook() && sock->GetIOHook()->creator == mod) + sock->Close(); + } } // note: the protocol does not allow direct umode +o except diff --git a/src/modules/m_spanningtree/utils.h b/src/modules/m_spanningtree/utils.h index 9e6f41852..164bed1ca 100644 --- a/src/modules/m_spanningtree/utils.h +++ b/src/modules/m_spanningtree/utils.h @@ -50,6 +50,7 @@ class SpanningTreeUtilities : public classbase public: typedef std::set<TreeSocket*> TreeSocketSet; + typedef std::map<TreeSocket*, std::pair<std::string, int> > TimeoutList; /** Creator module */ @@ -91,7 +92,7 @@ class SpanningTreeUtilities : public classbase server_hash sidlist; /** List of all outgoing sockets and their timeouts */ - std::map<TreeSocket*, std::pair<std::string, int> > timeoutlist; + TimeoutList timeoutlist; /** Holds the data from the <link> tags in the conf */ std::vector<reference<Link> > LinkBlocks; diff --git a/src/modules/m_userip.cpp b/src/modules/m_userip.cpp index 97e4c9284..79e69ec5e 100644 --- a/src/modules/m_userip.cpp +++ b/src/modules/m_userip.cpp @@ -36,7 +36,7 @@ class CommandUserip : public Command std::string retbuf = "340 " + user->nick + " :"; int nicks = 0; bool checked_privs = false; - bool has_privs; + bool has_privs = false; for (int i = 0; i < (int)parameters.size(); i++) { diff --git a/src/socketengine.cpp b/src/socketengine.cpp index 80e9eaed9..219d154f2 100644 --- a/src/socketengine.cpp +++ b/src/socketengine.cpp @@ -255,3 +255,26 @@ void SocketEngine::GetStats(float &kbitpersec_in, float &kbitpersec_out, float & kbitpersec_in = in_kbit / 1024; kbitpersec_out = out_kbit / 1024; } + +std::string SocketEngine::LastError() +{ +#ifndef _WIN32 + return strerror(errno); +#else + char szErrorString[500]; + DWORD dwErrorCode = WSAGetLastError(); + if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)szErrorString, _countof(szErrorString), NULL) == 0) + sprintf_s(szErrorString, _countof(szErrorString), "Error code: %u", dwErrorCode); + return szErrorString; +#endif +} + +std::string SocketEngine::GetError(int errnum) +{ +#ifndef _WIN32 + return strerror(errnum); +#else + WSASetLastError(errnum); + return LastError(); +#endif +} diff --git a/src/socketengines/socketengine_epoll.cpp b/src/socketengines/socketengine_epoll.cpp index 68f14cc38..099f793a1 100644 --- a/src/socketengines/socketengine_epoll.cpp +++ b/src/socketengines/socketengine_epoll.cpp @@ -63,7 +63,7 @@ EPollEngine::EPollEngine() { ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Can't determine maximum number of open sockets!"); std::cout << "ERROR: Can't determine maximum number of open sockets!" << std::endl; - ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE); + ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE); } // This is not a maximum, just a hint at the eventual number of sockets that may be polled. @@ -75,7 +75,7 @@ EPollEngine::EPollEngine() ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Your kernel probably does not have the proper features. This is a fatal error, exiting now."); std::cout << "ERROR: Could not initialize epoll socket engine: " << strerror(errno) << std::endl; std::cout << "ERROR: Your kernel probably does not have the proper features. This is a fatal error, exiting now." << std::endl; - ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE); + ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE); } ref = new EventHandler* [GetMaxFds()]; diff --git a/src/socketengines/socketengine_kqueue.cpp b/src/socketengines/socketengine_kqueue.cpp index a6c84133a..99ac51499 100644 --- a/src/socketengines/socketengine_kqueue.cpp +++ b/src/socketengines/socketengine_kqueue.cpp @@ -74,7 +74,7 @@ KQueueEngine::KQueueEngine() { ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Can't determine maximum number of open sockets!"); std::cout << "ERROR: Can't determine maximum number of open sockets!" << std::endl; - ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE); + ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE); } this->RecoverFromFork(); @@ -97,7 +97,7 @@ void KQueueEngine::RecoverFromFork() ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: this is a fatal error, exiting now."); std::cout << "ERROR: Could not initialize socket engine. Your kernel probably does not have the proper features." << std::endl; std::cout << "ERROR: this is a fatal error, exiting now." << std::endl; - ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE); + ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE); } CurrentSetSize = 0; } diff --git a/src/socketengines/socketengine_poll.cpp b/src/socketengines/socketengine_poll.cpp index 37f4b6836..493b22630 100644 --- a/src/socketengines/socketengine_poll.cpp +++ b/src/socketengines/socketengine_poll.cpp @@ -32,15 +32,15 @@ #include "socketengine.h" #ifndef _WIN32 - #ifndef __USE_XOPEN - #define __USE_XOPEN /* fuck every fucking OS ever made. needed by poll.h to work.*/ - #endif - #include <poll.h> - #include <sys/poll.h> +# ifndef __USE_XOPEN +# define __USE_XOPEN /* fuck every fucking OS ever made. needed by poll.h to work.*/ +# endif +# include <poll.h> +# include <sys/poll.h> +# include <sys/resource.h> #else - /* *grumble* */ - #define struct pollfd WSAPOLLFD - #define poll WSAPoll +# define struct pollfd WSAPOLLFD +# define poll WSAPoll #endif class InspIRCd; @@ -73,40 +73,20 @@ public: #endif -#ifdef BSD - #include <sys/sysctl.h> -#else - #include <ulimit.h> -#endif - PollEngine::PollEngine() { CurrentSetSize = 0; -#ifdef BSD - int mib[2]; - size_t len; - - mib[0] = CTL_KERN; -#ifdef KERN_MAXFILESPERPROC - mib[1] = KERN_MAXFILESPERPROC; -#else - mib[1] = KERN_MAXFILES; -#endif - len = sizeof(MAX_DESCRIPTORS); - sysctl(mib, 2, &MAX_DESCRIPTORS, &len, NULL, 0); -#else - int max = ulimit(4, 0); - if (max > 0) + struct rlimit limits; + if (!getrlimit(RLIMIT_NOFILE, &limits)) { - MAX_DESCRIPTORS = max; + MAX_DESCRIPTORS = limits.rlim_cur; } else { ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Can't determine maximum number of open sockets: %s", strerror(errno)); std::cout << "ERROR: Can't determine maximum number of open sockets: " << strerror(errno) << std::endl; - ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE); + ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE); } -#endif ref = new EventHandler* [GetMaxFds()]; events = new struct pollfd[GetMaxFds()]; diff --git a/src/socketengines/socketengine_ports.cpp b/src/socketengines/socketengine_ports.cpp index 8a2fb87f4..ba4e8f2d7 100644 --- a/src/socketengines/socketengine_ports.cpp +++ b/src/socketengines/socketengine_ports.cpp @@ -76,7 +76,7 @@ PortsEngine::PortsEngine() { ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Can't determine maximum number of open sockets!"); std::cout << "ERROR: Can't determine maximum number of open sockets!" << std::endl; - ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE); + ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE); } EngineHandle = port_create(); @@ -86,7 +86,7 @@ PortsEngine::PortsEngine() ServerInstance->Logs->Log("SOCKET", LOG_SPARSE, "ERROR: This is a fatal error, exiting now."); std::cout << "ERROR: Could not initialize socket engine: " << strerror(errno) << std::endl; std::cout << "ERROR: This is a fatal error, exiting now." << std::endl; - ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE); + ServerInstance->QuickExit(EXIT_STATUS_SOCKETENGINE); } CurrentSetSize = 0; diff --git a/src/socketengines/socketengine_select.cpp b/src/socketengines/socketengine_select.cpp index de366266f..f995b5472 100644 --- a/src/socketengines/socketengine_select.cpp +++ b/src/socketengines/socketengine_select.cpp @@ -177,7 +177,9 @@ int SelectEngine::DispatchEvents() if (has_write) { WriteEvents++; - SetEventMask(ev, ev->GetEventMask() & ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE)); + int newmask = (ev->GetEventMask() & ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE)); + this->OnSetEvent(ev, ev->GetEventMask(), newmask); + SetEventMask(ev, newmask); ev->HandleEvent(EVENT_WRITE); } } diff --git a/src/threadengines/threadengine_pthread.cpp b/src/threadengines/threadengine_pthread.cpp index c1b964430..e16e401f3 100644 --- a/src/threadengines/threadengine_pthread.cpp +++ b/src/threadengines/threadengine_pthread.cpp @@ -80,6 +80,8 @@ class ThreadSignalSocket : public EventHandler ~ThreadSignalSocket() { + ServerInstance->SE->DelFd(this); + ServerInstance->SE->Close(GetFd()); } void Notify() @@ -104,6 +106,7 @@ class ThreadSignalSocket : public EventHandler SocketThread::SocketThread() { + signal.sock = NULL; int fd = eventfd(0, EFD_NONBLOCK); if (fd < 0) throw new CoreException("Could not create pipe " + std::string(strerror(errno))); @@ -127,6 +130,8 @@ class ThreadSignalSocket : public EventHandler ~ThreadSignalSocket() { close(send_fd); + ServerInstance->SE->DelFd(this); + ServerInstance->SE->Close(GetFd()); } void Notify() @@ -152,6 +157,7 @@ class ThreadSignalSocket : public EventHandler SocketThread::SocketThread() { + signal.sock = NULL; int fds[2]; if (pipe(fds)) throw new CoreException("Could not create pipe " + std::string(strerror(errno))); @@ -166,4 +172,9 @@ void SocketThread::NotifyParent() SocketThread::~SocketThread() { + if (signal.sock) + { + signal.sock->cull(); + delete signal.sock; + } } diff --git a/src/threadengines/threadengine_win32.cpp b/src/threadengines/threadengine_win32.cpp index 529e24a29..ea37892f8 100644 --- a/src/threadengines/threadengine_win32.cpp +++ b/src/threadengines/threadengine_win32.cpp @@ -35,17 +35,11 @@ void ThreadEngine::Start(Thread* thread) if (data->handle == NULL) { + DWORD lasterr = GetLastError(); thread->state = NULL; delete data; - std::string err = "Unable to create new thread: "; -#ifdef _WIN32 - CHAR errdetail[100]; - FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errdetail, 100, 0); + std::string err = "Unable to create new thread: " + ConvToStr(lasterr); SetLastError(ERROR_SUCCESS); - err += errdetail; -#else - err += dlerror(); -#endif throw CoreException(err); } } |