summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/commands/cmd_whowas.cpp11
-rw-r--r--src/helperfuncs.cpp21
-rw-r--r--src/inspircd.cpp2
-rw-r--r--src/inspsocket.cpp22
-rw-r--r--src/modules/extra/m_ssl_gnutls.cpp10
-rw-r--r--src/modules/extra/m_ssl_openssl.cpp2
-rw-r--r--src/modules/m_dnsbl.cpp32
-rw-r--r--src/modules/m_ircv3.cpp2
-rw-r--r--src/modules/m_permchannels.cpp106
-rw-r--r--src/modules/m_spanningtree/fjoin.cpp32
-rw-r--r--src/modules/m_spanningtree/main.cpp7
-rw-r--r--src/modules/m_spanningtree/utils.h3
-rw-r--r--src/modules/m_userip.cpp2
-rw-r--r--src/socketengine.cpp23
-rw-r--r--src/socketengines/socketengine_epoll.cpp4
-rw-r--r--src/socketengines/socketengine_kqueue.cpp4
-rw-r--r--src/socketengines/socketengine_poll.cpp44
-rw-r--r--src/socketengines/socketengine_ports.cpp4
-rw-r--r--src/socketengines/socketengine_select.cpp4
-rw-r--r--src/threadengines/threadengine_pthread.cpp11
-rw-r--r--src/threadengines/threadengine_win32.cpp10
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);
}
}