#include <sys/ioctl.h>
#include <time.h>
#include <string>
+#include <exception>
+#include <stdexcept>
+#include <new>
#ifdef GCC3
#include <ext/hash_map>
#else
extern int MODCOUNT;
extern char LOG_FILE[MAXBUF];
-int openSockfd[MAXSOCKS];
+int openSockfd[MAX_DESCRIPTORS];
+int yield_depth;
+int iterations = 0;
sockaddr_in client,server;
socklen_t length;
user_hash clientlist;
chan_hash chanlist;
-whowas_hash whowas;
+
servernamelist servernames;
char lowermap[255];
if (argc > 1) {
for (int i = 1; i < argc; i++)
{
- if (!strcmp(argv[i],"-nofork")) {
+ if (!strcmp(argv[i],"-nofork"))
+ {
Config->nofork = true;
}
- if (!strcmp(argv[i],"-wait")) {
+ if (!strcmp(argv[i],"-wait"))
+ {
sleep(6);
}
- if (!strcmp(argv[i],"-nolimit")) {
- Config->unlimitcore = true;
+ if (!strcmp(argv[i],"-nolimit"))
+ {
+ printf("WARNING: The `-nolimit' option is deprecated, and now on by default. This behaviour may change in the future.\n");
}
- if (!strcmp(argv[i],"-logfile")) {
+ if (!strcmp(argv[i],"-logfile"))
+ {
if (argc > i+1)
{
strlcpy(LOG_FILE,argv[i+1],MAXBUF);
this->MakeLowerMap();
OpenLog(argv, argc);
+ this->stats = new serverstats();
Config->ClearStack();
Config->Read(true,NULL);
CheckRoot();
this->ModeGrok = new ModeParser();
this->Parser = new CommandParser();
- this->stats = new serverstats();
AddServerName(Config->ServerName);
CheckDie();
- stats->BoundPortCount = BindPorts();
+ stats->BoundPortCount = BindPorts(true);
for(int t = 0; t < 255; t++)
Config->global_implementation[t] = 0;
SetSignals();
if (!Config->nofork)
{
- if (DaemonSeed() == ERROR)
+ if (!DaemonSeed())
{
printf("ERROR: could not go into daemon mode. Shutting down.\n");
Exit(ERROR);
void InspIRCd::MoveTo(std::string modulename,int slot)
{
unsigned int v2 = 256;
- log(DEBUG,"Moving %s to slot %d",modulename.c_str(),slot);
for (unsigned int v = 0; v < Config->module_names.size(); v++)
{
if (Config->module_names[v] == modulename)
break;
}
}
- if (v2 == (unsigned int)slot)
- {
- log(DEBUG,"Item %s already in slot %d!",modulename.c_str(),slot);
- }
- else if (v2 < 256)
+ if ((v2 != (unsigned int)slot) && (v2 < 256))
{
// Swap the module names over
Config->module_names[v2] = Config->module_names[slot];
Config->implement_lists[v2][n] = Config->implement_lists[slot][n];
Config->implement_lists[slot][n] = x;
}
- log(DEBUG,"Moved %s to slot successfully",modulename.c_str());
}
else
{
void InspIRCd::MoveAfter(std::string modulename, std::string after)
{
- log(DEBUG,"Move %s after %s...",modulename.c_str(),after.c_str());
for (unsigned int v = 0; v < Config->module_names.size(); v++)
{
if (Config->module_names[v] == after)
void InspIRCd::MoveBefore(std::string modulename, std::string before)
{
- log(DEBUG,"Move %s before %s...",modulename.c_str(),before.c_str());
for (unsigned int v = 0; v < Config->module_names.size(); v++)
{
if (Config->module_names[v] == before)
modules[MODCOUNT+1]->Implements(x);
for(int t = 0; t < 255; t++)
- {
Config->global_implementation[t] += Config->implement_lists[MODCOUNT+1][t];
- if (Config->implement_lists[MODCOUNT+1][t])
- {
- log(DEBUG,"Add global implementation: %d %d => %d",MODCOUNT+1,t,Config->global_implementation[t]);
- }
- }
}
else
{
}
else if ((modules[j]->Prioritize() & 0xFF) == PRIORITY_BEFORE)
{
- log(DEBUG,"Module %d wants PRIORITY_BEFORE",j);
put_before[Config->module_names[j]] = Config->module_names[modules[j]->Prioritize() >> 8];
- log(DEBUG,"Before: %s",Config->module_names[modules[j]->Prioritize() >> 8].c_str());
}
else if ((modules[j]->Prioritize() & 0xFF) == PRIORITY_AFTER)
{
- log(DEBUG,"Module %d wants PRIORITY_AFTER",j);
put_after[Config->module_names[j]] = Config->module_names[modules[j]->Prioritize() >> 8];
- log(DEBUG,"After: %s",Config->module_names[modules[j]->Prioritize() >> 8].c_str());
}
}
for (unsigned int j = 0; j < put_to_back.size(); j++)
sockaddr_in sock_us; // our port number
socklen_t uslen; // length of our port number
+ if (yield_depth > 100)
+ return;
+
+ yield_depth++;
+
/* time() seems to be a pretty expensive syscall, so avoid calling it too much.
* Once per loop iteration is pleanty.
*/
if (((TIME % 5) == 0) && (!expire_run))
{
expire_lines();
- FOREACH_MOD(I_OnBackgroundTimer,OnBackgroundTimer(TIME));
+ if (process_module_sockets)
+ {
+ /* Fix by brain - the addition of DoOneIteration means that this
+ * can end up getting called recursively in the following pattern:
+ *
+ * m_spanningtree DoPingChecks
+ * (server pings out and is squit)
+ * (squit causes call to DoOneIteration)
+ * DoOneIteration enters here
+ * calls DoBackground timer
+ * enters m_spanningtree DoPingChecks... see step 1.
+ *
+ * This should do the job and fix the bug.
+ */
+ FOREACH_MOD(I_OnBackgroundTimer,OnBackgroundTimer(TIME));
+ }
TickMissedTimers(TIME);
expire_run = true;
+ yield_depth--;
return;
}
else if ((TIME % 5) == 1)
{
expire_run = false;
}
+
+ if (iterations++ == 15)
+ {
+ iterations = 0;
+ DoBackgroundUserStuff(TIME);
+ }
/* Once a second, do the background processing */
if (TIME != OLDTIME)
{
if (TIME < OLDTIME)
WriteOpers("*** \002EH?!\002 -- Time is flowing BACKWARDS in this dimension! Clock drifted backwards %d secs.",abs(OLDTIME-TIME));
- DoBackgroundUserStuff(TIME);
+ if ((TIME % 3600) == 0)
+ {
+ MaintainWhoWas(TIME);
+ }
}
-
+
/* Process timeouts on module sockets each time around
* the loop. There shouldnt be many module sockets, at
* most, 20 or so, so this won't be much of a performance
* servers... so its nice and easy, just one call.
*/
if (!(numberactive = SE->Wait(activefds)))
+ {
+ yield_depth--;
return;
+ }
/**
* Now process each of the fd's. For users, we have a fast
* listening ports or module sockets though, things could get
* ugly.
*/
+ log(DEBUG,"There are %d fd's to process.",numberactive);
+
for (unsigned int activefd = 0; activefd < numberactive; activefd++)
{
int socket_type = SE->GetType(activefds[activefd]);
{
case X_ESTAB_CLIENT:
+ log(DEBUG,"Type: X_ESTAB_CLIENT: fd=%d",activefds[activefd]);
cu = fd_ref_table[activefds[activefd]];
if (cu)
ProcessUser(cu);
case X_ESTAB_MODULE:
+ log(DEBUG,"Type: X_ESTAB_MODULE: fd=%d",activefds[activefd]);
+
if (!process_module_sockets)
- return;
+ break;
/* Process module-owned sockets.
* Modules are encouraged to inherit their sockets from
if ((s) && (!s->Poll()))
{
- log(DEBUG,"Socket poll returned false, close and bail");
+ log(DEBUG,"inspircd.cpp: Socket poll returned false, close and bail");
SE->DelFd(s->GetFd());
+ socket_ref[activefds[activefd]] = NULL;
for (std::vector<InspSocket*>::iterator a = module_sockets.begin(); a < module_sockets.end(); a++)
{
s_del = (InspSocket*)*a;
s->Close();
delete s;
}
+ else if (!s)
+ {
+ log(DEBUG,"WTF, X_ESTAB_MODULE for nonexistent InspSocket, removed!");
+ SE->DelFd(s->GetFd());
+ }
break;
case X_ESTAB_DNS:
* and independent of the mainloop.
*/
#ifndef THREADED_DNS
+ log(DEBUG,"Type: X_ESTAB_DNS: fd=%d",activefds[activefd]);
dns_poll(activefds[activefd]);
#endif
break;
case X_LISTEN:
+ log(DEBUG,"Type: X_LISTEN_MODULE: fd=%d",activefds[activefd]);
+
/* It's a listener */
uslen = sizeof(sock_us);
length = sizeof(client);
}
catch (ModuleException& modexcept)
{
- log(DEBUG,"Module exception cought: %s",modexcept.GetReason()); \
+ log(DEBUG,"Module exception cought: %s",modexcept.GetReason());
}
}
stats->statsAccept++;
* what we would do, so for now, its going
* to safely do bugger all.
*/
+ log(DEBUG,"Type: X_WHAT_THE_FUCK_BBQ: fd=%d",activefds[activefd]);
+ SE->DelFd(activefds[activefd]);
break;
}
}
+ yield_depth--;
}
int InspIRCd::Run()
LoadAllModules(this);
+ /* Just in case no modules were loaded - fix for bug #101 */
+ this->BuildISupport();
+
printf("\nInspIRCd is now running!\n");
if (!Config->nofork)
{
- freopen("/dev/null","w",stdout);
- freopen("/dev/null","w",stderr);
+ fclose(stdout);
+ fclose(stderr);
+ fclose(stdin);
}
/* Add the listening sockets used for client inbound connections
/* main loop, this never returns */
expire_run = false;
+ yield_depth = 0;
+ iterations = 0;
while (true)
{
int main(int argc, char** argv)
{
- ServerInstance = new InspIRCd(argc, argv);
- ServerInstance->Run();
- delete ServerInstance;
- return 0;
+ try
+ {
+ ServerInstance = new InspIRCd(argc, argv);
+ ServerInstance->Run();
+ delete ServerInstance;
+ }
+ catch (std::bad_alloc)
+ {
+ log(DEFAULT,"You are out of memory! (got exception std::bad_alloc!)");
+ send_error("**** OUT OF MEMORY **** We're gonna need a bigger boat!");
+ printf("Out of memory! (got exception std::bad_alloc!");
+ }
+ return 0;
}